Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-29600

Memory leak in row_log_table_apply_update(), in UPDATE involving BLOB, during online table rebuild

Details

    Description

      Note: The test case is non-deterministic, run with --repeat=N. It usually fails for me within ~5 attempts. The test case is rr-able.
      The restart in the test case is not a part of the test itself, it is mainly there to capture LeakSanitizer errors right away; otherwise the test would run all N attempts before reporting the failure which is only seen on shutdown.

      --source include/have_innodb.inc
       
      CREATE TABLE t (pk INT PRIMARY KEY, f TEXT) ENGINE=InnoDB;
      INSERT INTO t(pk) VALUES (1);
       
      --connect (con1,localhost,root,,test)
      --send
        ALTER TABLE t FORCE;
       
      --connection default
      DROP TABLE IF EXISTS non_existing;
      UPDATE t SET f = REPEAT('a',10000);
       
      --source include/restart_mysqld.inc
       
      --connection default
      DROP TABLE t;
      

      10.3 b6bf7cd1

      ==3197705==ERROR: LeakSanitizer: detected memory leaks
       
      Direct leak of 10 byte(s) in 1 object(s) allocated from:
          #0 0x7f66010bee8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
          #1 0x56473333dc2c in rec_copy_prefix_to_buf(unsigned char const*, dict_index_t const*, unsigned long, unsigned char**, unsigned long*) /data/src/10.3/storage/innobase/rem/rem0rec.cc:2002
          #2 0x564733650dbe in btr_pcur_store_position(btr_pcur_t*, mtr_t*) /data/src/10.3/storage/innobase/btr/btr0pcur.cc:200
          #3 0x564733645c1c in btr_blob_log_check_t::check() /data/src/10.3/storage/innobase/btr/btr0cur.cc:7189
          #4 0x56473363e951 in btr_store_big_rec_extern_fields(btr_pcur_t*, unsigned short*, big_rec_t const*, mtr_t*, blob_op) /data/src/10.3/storage/innobase/btr/btr0cur.cc:7390
          #5 0x564733417aaf in row_log_table_apply_update /data/src/10.3/storage/innobase/row/row0log.cc:2327
          #6 0x56473341a4bc in row_log_table_apply_op /data/src/10.3/storage/innobase/row/row0log.cc:2669
          #7 0x56473341e8fa in row_log_table_apply_ops /data/src/10.3/storage/innobase/row/row0log.cc:3039
          #8 0x56473341f76e in row_log_table_apply(que_thr_t*, dict_table_t*, TABLE*, ut_stage_alter_t*, dict_table_t*) /data/src/10.3/storage/innobase/row/row0log.cc:3148
          #9 0x56473315f716 in ha_innobase::inplace_alter_table(TABLE*, Alter_inplace_info*) /data/src/10.3/storage/innobase/handler/handler0alter.cc:7223
          #10 0x56473264c815 in handler::ha_inplace_alter_table(TABLE*, Alter_inplace_info*) (/mnt8t/bld/10.3-asan-nightly/bin/mysqld+0x12a8815)
          #11 0x56473262fcf2 in mysql_inplace_alter_table /data/src/10.3/sql/sql_table.cc:7773
          #12 0x564732640afd in mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool) /data/src/10.3/sql/sql_table.cc:10111
          #13 0x5647327a887b in Sql_cmd_alter_table::execute(THD*) /data/src/10.3/sql/sql_alter.cc:512
          #14 0x5647323f6745 in mysql_execute_command(THD*) /data/src/10.3/sql/sql_parse.cc:6076
          #15 0x5647324025fb in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /data/src/10.3/sql/sql_parse.cc:7871
          #16 0x5647323d9ba1 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /data/src/10.3/sql/sql_parse.cc:1852
          #17 0x5647323d677d in do_command(THD*) /data/src/10.3/sql/sql_parse.cc:1398
          #18 0x564732798159 in do_handle_one_connection(CONNECT*) /data/src/10.3/sql/sql_connect.cc:1403
          #19 0x564732797a55 in handle_one_connection /data/src/10.3/sql/sql_connect.cc:1308
          #20 0x564733d42ae6 in pfs_spawn_thread /data/src/10.3/storage/perfschema/pfs.cc:1869
          #21 0x7f660081cea6 in start_thread nptl/pthread_create.c:477
       
      SUMMARY: AddressSanitizer: 10 byte(s) leaked in 1 allocation(s).
      

      Reproducible on all of 10.3-10.10, also on at least 2 last releases of 10.3.

      Attachments

        Issue Links

          Activity

            Indeed, it looks like even after MDEV-15250, the memory will be leaked in 10.6 and later:

            10.6 ca51c9fd596268900e466e26e5d3c2a3c6db9cb3

            Direct leak of 10 byte(s) in 1 object(s) allocated from:
                #0 0x7f3b64ab89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
                #1 0x55fb7d0a4026 in rec_copy_prefix_to_buf(unsigned char const*, dict_index_t const*, unsigned long, unsigned char**, unsigned long*) /mariadb/10.6/storage/innobase/rem/rem0rec.cc:2118
                #2 0x55fb7ce0c6db in btr_pcur_store_position(btr_pcur_t*, mtr_t*) /mariadb/10.6/storage/innobase/btr/btr0pcur.cc:215
                #3 0x55fb7ccc70f5 in btr_blob_log_check_t::check() /mariadb/10.6/storage/innobase/btr/btr0cur.cc:6823
                #4 0x55fb7cca7e25 in btr_store_big_rec_extern_fields(btr_pcur_t*, unsigned short*, big_rec_t const*, mtr_t*, blob_op) /mariadb/10.6/storage/innobase/btr/btr0cur.cc:7011
                #5 0x55fb7d13441c in row_log_table_apply_update /mariadb/10.6/storage/innobase/row/row0log.cc:2053
                #6 0x55fb7d135fb8 in row_log_table_apply_op /mariadb/10.6/storage/innobase/row/row0log.cc:2388
                #7 0x55fb7d139519 in row_log_table_apply_ops /mariadb/10.6/storage/innobase/row/row0log.cc:2758
                #8 0x55fb7d13a1f6 in row_log_table_apply(que_thr_t*, dict_table_t*, TABLE*, ut_stage_alter_t*, dict_table_t*) /mariadb/10.6/storage/innobase/row/row0log.cc:2866
                #9 0x55fb7cecbd60 in alter_rebuild_apply_log /mariadb/10.6/storage/innobase/handler/handler0alter.cc:10912
                #10 0x55fb7cef068b in ha_innobase::commit_inplace_alter_table(TABLE*, Alter_inplace_info*, bool) /mariadb/10.6/storage/innobase/handler/handler0alter.cc:11133
            

            marko Marko Mäkelä added a comment - Indeed, it looks like even after MDEV-15250 , the memory will be leaked in 10.6 and later: 10.6 ca51c9fd596268900e466e26e5d3c2a3c6db9cb3 Direct leak of 10 byte(s) in 1 object(s) allocated from: #0 0x7f3b64ab89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x55fb7d0a4026 in rec_copy_prefix_to_buf(unsigned char const*, dict_index_t const*, unsigned long, unsigned char**, unsigned long*) /mariadb/10.6/storage/innobase/rem/rem0rec.cc:2118 #2 0x55fb7ce0c6db in btr_pcur_store_position(btr_pcur_t*, mtr_t*) /mariadb/10.6/storage/innobase/btr/btr0pcur.cc:215 #3 0x55fb7ccc70f5 in btr_blob_log_check_t::check() /mariadb/10.6/storage/innobase/btr/btr0cur.cc:6823 #4 0x55fb7cca7e25 in btr_store_big_rec_extern_fields(btr_pcur_t*, unsigned short*, big_rec_t const*, mtr_t*, blob_op) /mariadb/10.6/storage/innobase/btr/btr0cur.cc:7011 #5 0x55fb7d13441c in row_log_table_apply_update /mariadb/10.6/storage/innobase/row/row0log.cc:2053 #6 0x55fb7d135fb8 in row_log_table_apply_op /mariadb/10.6/storage/innobase/row/row0log.cc:2388 #7 0x55fb7d139519 in row_log_table_apply_ops /mariadb/10.6/storage/innobase/row/row0log.cc:2758 #8 0x55fb7d13a1f6 in row_log_table_apply(que_thr_t*, dict_table_t*, TABLE*, ut_stage_alter_t*, dict_table_t*) /mariadb/10.6/storage/innobase/row/row0log.cc:2866 #9 0x55fb7cecbd60 in alter_rebuild_apply_log /mariadb/10.6/storage/innobase/handler/handler0alter.cc:10912 #10 0x55fb7cef068b in ha_innobase::commit_inplace_alter_table(TABLE*, Alter_inplace_info*, bool) /mariadb/10.6/storage/innobase/handler/handler0alter.cc:11133

            For every replicated UPDATE that involves off-page storage, btr_pcur_t::old_rec_buf will be leaded by row_log_table_apply_update().

            I also checked how row_log_table_apply_insert_low() is managing off-page records. It invokes row_ins_clust_index_entry_low(), which will free the pcur.old_rec_buf in its local variable before returning. So, there was no leak in the INSERT case.

            As far as I can tell, this memory leak was inherited from MySQL 5.7.5 to MariaDB Server 10.2.2.

            marko Marko Mäkelä added a comment - For every replicated UPDATE that involves off-page storage, btr_pcur_t::old_rec_buf will be leaded by row_log_table_apply_update() . I also checked how row_log_table_apply_insert_low() is managing off-page records. It invokes row_ins_clust_index_entry_low() , which will free the pcur.old_rec_buf in its local variable before returning. So, there was no leak in the INSERT case. As far as I can tell, this memory leak was inherited from MySQL 5.7.5 to MariaDB Server 10.2.2.

            People

              marko Marko Mäkelä
              elenst Elena Stepanova
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.