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

Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val

Details

    Description

      --source include/have_innodb.inc
      --source include/have_partition.inc
       
      CREATE TABLE t1 (a INT)
      ENGINE=InnoDB 
      PARTITION BY RANGE (a) (
        PARTITION p0 VALUES LESS THAN (6),
        PARTITION pn VALUES LESS THAN MAXVALUE
      );
      INSERT INTO t1 VALUES (4),(5),(6);
      ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY;
      UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5;
       
      # Cleanup
      DROP TABLE t1;
      

      10.3 82490a97db

      #3  <signal handler called>
      #4  0x000055e0922036ec in ha_innobase::update_thd (this=0x7ff5100a6738, thd=0x7ff510000b00) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:2946
      #5  0x000055e0921f3e02 in ha_innobase::info_low (this=0x7ff5100a6738, flag=64, is_analyze=false) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:13837
      #6  0x000055e0921f49e4 in ha_innobase::info (this=0x7ff5100a6738, flag=64) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:14151
      #7  0x000055e092631e8c in ha_partition::info (this=0x7ff5100a8a98, flag=64) at /data/src/10.3/sql/ha_partition.cc:8157
      #8  0x000055e0926367d1 in ha_partition::update_next_auto_inc_val (this=0x7ff5100a8a98) at /data/src/10.3/sql/ha_partition.cc:10322
      #9  0x000055e092627c4b in ha_partition::update_row (this=0x7ff5100a8a98, old_data=0x7ff510170480 "\377\005", new_data=0x7ff510170478 "\377\003") at /data/src/10.3/sql/ha_partition.cc:4453
      #10 0x000055e091ed3003 in handler::ha_update_row (this=0x7ff5100a8a98, old_data=0x7ff510170480 "\377\005", new_data=0x7ff510170478 "\377\003") at /data/src/10.3/sql/handler.cc:6269
      #11 0x000055e091cc68e0 in mysql_update (thd=0x7ff510000b00, table_list=0x7ff510014e30, fields=..., values=..., conds=0x7ff510015810, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7ff565e2a6f0, updated_return=0x7ff565e2a7b0) at /data/src/10.3/sql/sql_update.cc:947
      #12 0x000055e091bce24d in mysql_execute_command (thd=0x7ff510000b00) at /data/src/10.3/sql/sql_parse.cc:4581
      #13 0x000055e091bd9669 in mysql_parse (thd=0x7ff510000b00, rawbuf=0x7ff510014cd8 "UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5", length=46, parser_state=0x7ff565e2b5f0, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:8092
      #14 0x000055e091bc681d in dispatch_command (command=COM_QUERY, thd=0x7ff510000b00, packet=0x7ff510161011 "UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5", packet_length=46, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:1851
      #15 0x000055e091bc5241 in do_command (thd=0x7ff510000b00) at /data/src/10.3/sql/sql_parse.cc:1396
      #16 0x000055e091d2d256 in do_handle_one_connection (connect=0x55e094dc39d0) at /data/src/10.3/sql/sql_connect.cc:1402
      #17 0x000055e091d2cfda in handle_one_connection (arg=0x55e094dc39d0) at /data/src/10.3/sql/sql_connect.cc:1308
      #18 0x000055e0921c78dd in pfs_spawn_thread (arg=0x55e094dcc0c0) at /data/src/10.3/storage/perfschema/pfs.cc:1862
      #19 0x00007ff5727ca494 in start_thread (arg=0x7ff565e2c700) at pthread_create.c:333
      #20 0x00007ff570bb093f in clone () from /lib/x86_64-linux-gnu/libc.so.6
      

      All of debug, non-debug and ASAN builds crash with SIGSEGV.

      Not reproducible on 10.2.

      Attachments

        Issue Links

          Activity

            The problem is that ha_partition::open_read_partitions() is not opening all partitions that the UPDATE statement is accessing. I found this out by setting a breakpoint on ha_innobase::open() and noticing that the this pointer that is passed to ha_innobase::update_thd() did not occur previously. After the ALTER TABLE, only the first partition is being accessed.

            On the first look, the UPDATE should only access the first partition, but in reality it is accessing all partitions, because the auto-increment counter is being updated on all partitions.

            Apparently MDEV-11084 is missing an adjustment for this special case (updating AUTO_INCREMENT value).

            I verified that the crash was introduced by this change that implements MDEV-11084 . There was no crash with the parent commit.

            marko Marko Mäkelä added a comment - The problem is that ha_partition::open_read_partitions() is not opening all partitions that the UPDATE statement is accessing. I found this out by setting a breakpoint on ha_innobase::open() and noticing that the this pointer that is passed to ha_innobase::update_thd() did not occur previously. After the ALTER TABLE , only the first partition is being accessed. On the first look, the UPDATE should only access the first partition, but in reality it is accessing all partitions, because the auto-increment counter is being updated on all partitions. Apparently MDEV-11084 is missing an adjustment for this special case (updating AUTO_INCREMENT value). I verified that the crash was introduced by this change that implements MDEV-11084 . There was no crash with the parent commit.
            alice Alice Sherepa added a comment -

            Test case from MDEV-19907:

            --source include/have_innodb.inc
            --source include/have_partition.inc
            CREATE TABLE t1 (
                id1 int NOT NULL, 
                id2 int NOT NULL,
                id int(11) NOT NULL AUTO_INCREMENT, 
                PRIMARY KEY (id1,id2), 
                KEY id (id)) 
            ENGINE=innodb AUTO_INCREMENT=1 PARTITION BY HASH (id1) (PARTITION p0001, PARTITION p0002);
             
            INSERT INTO t1 partition(p0002) (id1,id2) VALUES (1,1), (1,2), (1,3);
             
            ANALYZE TABLE t1;
             
            INSERT INTO t1 partition(p0001) ( id1, id2) VALUES (2,1), (2,2), (2,3), (2,4), (2,5) ;
             
            DROP TABLE t1;
            

            10.3 099007c3c92d140562577

            ==24231==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x5594d2b16256 bp 0x7f9862d4b900 sp 0x7f9862d4b850 T27)
                #0 0x5594d2b16255 in ha_innobase::update_thd(THD*)  /10.3/storage/innobase/handler/ha_innodb.cc:2958
                #1 0x5594d2af35fe in ha_innobase::info_low(unsigned int, bool)  /10.3/storage/innobase/handler/ha_innodb.cc:13923
                #2 0x5594d2af52f0 in ha_innobase::info(unsigned int)  /10.3/storage/innobase/handler/ha_innodb.cc:14237
                #3 0x5594d32baf55 in ha_partition::info(unsigned int)  /10.3/sql/ha_partition.cc:8157
                #4 0x5594d32c7f0c in ha_partition::update_next_auto_inc_val()  /10.3/sql/ha_partition.cc:10326
                #5 0x5594d329c6aa in ha_partition::write_row(unsigned char*)  /10.3/sql/ha_partition.cc:4268
                #6 0x5594d22d05f3 in handler::ha_write_row(unsigned char*)  /10.3/sql/handler.cc:6420
                #7 0x5594d1b34aea in write_record(THD*, TABLE*, st_copy_info*)  /10.3/sql/sql_insert.cc:2030
                #8 0x5594d1b2e1d5 in mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool)  /10.3/sql/sql_insert.cc:1071
                #9 0x5594d1bc4a8d in mysql_execute_command(THD*)  /10.3/sql/sql_parse.cc:4735
                #10 0x5594d1bda295 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool)  /10.3/sql/sql_parse.cc:8105
                #11 0x5594d1bb4d9d in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool)  /10.3/sql/sql_parse.cc:1858
                #12 0x5594d1bb1f01 in do_command(THD*)  /10.3/sql/sql_parse.cc:1404
                #13 0x5594d1f08ec1 in do_handle_one_connection(CONNECT*)  /10.3/sql/sql_connect.cc:1402
                #14 0x5594d1f0889e in handle_one_connection  /10.3/sql/sql_connect.cc:1308
                #15 0x5594d3231cc0 in pfs_spawn_thread  /10.3/storage/perfschema/pfs.cc:1862
                #16 0x7f987a1eb6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
                #17 0x7f987968041c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)
            

            With MYISAM it results in a wrong values in the auto_incremented column:

            CREATE TABLE t1 (
                id1 int NOT NULL, 
                id2 int NOT NULL,
                id int(11) NOT NULL AUTO_INCREMENT, 
                PRIMARY KEY (id1,id2), 
                KEY id (id)) 
            ENGINE=myisam AUTO_INCREMENT=1 PARTITION BY HASH (id1) (PARTITION p0001, PARTITION p0002);
             
            INSERT INTO t1 partition(p0002) (id1,id2) VALUES (1,1), (1,2), (1,3);
             
            ANALYZE TABLE t1;
            INSERT INTO t1 partition(p0001) ( id1, id2) VALUES (2,1), (2,2), (2,3), (2,4), (2,5) ;
            SELECT id, count(*) FROM t1 GROUP BY id;
            

            MariaDB [test]> SELECT id, count(*) FROM t1 GROUP BY id;
            +----+----------+
            | id | count(*) |
            +----+----------+
            |  1 |        2 |
            |  2 |        2 |
            |  3 |        2 |
            |  4 |        1 |
            |  5 |        1 |
            +----+----------+
            5 rows in set (0.000 sec)
            

            alice Alice Sherepa added a comment - Test case from MDEV-19907 : --source include/have_innodb.inc --source include/have_partition.inc CREATE TABLE t1 ( id1 int NOT NULL, id2 int NOT NULL, id int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id1,id2), KEY id (id)) ENGINE=innodb AUTO_INCREMENT=1 PARTITION BY HASH (id1) (PARTITION p0001, PARTITION p0002); INSERT INTO t1 partition(p0002) (id1,id2) VALUES (1,1), (1,2), (1,3); ANALYZE TABLE t1;   INSERT INTO t1 partition(p0001) ( id1, id2) VALUES (2,1), (2,2), (2,3), (2,4), (2,5) ;   DROP TABLE t1; 10.3 099007c3c92d140562577 ==24231==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x5594d2b16256 bp 0x7f9862d4b900 sp 0x7f9862d4b850 T27) #0 0x5594d2b16255 in ha_innobase::update_thd(THD*) /10.3/storage/innobase/handler/ha_innodb.cc:2958 #1 0x5594d2af35fe in ha_innobase::info_low(unsigned int, bool) /10.3/storage/innobase/handler/ha_innodb.cc:13923 #2 0x5594d2af52f0 in ha_innobase::info(unsigned int) /10.3/storage/innobase/handler/ha_innodb.cc:14237 #3 0x5594d32baf55 in ha_partition::info(unsigned int) /10.3/sql/ha_partition.cc:8157 #4 0x5594d32c7f0c in ha_partition::update_next_auto_inc_val() /10.3/sql/ha_partition.cc:10326 #5 0x5594d329c6aa in ha_partition::write_row(unsigned char*) /10.3/sql/ha_partition.cc:4268 #6 0x5594d22d05f3 in handler::ha_write_row(unsigned char*) /10.3/sql/handler.cc:6420 #7 0x5594d1b34aea in write_record(THD*, TABLE*, st_copy_info*) /10.3/sql/sql_insert.cc:2030 #8 0x5594d1b2e1d5 in mysql_insert(THD*, TABLE_LIST*, List<Item>&, List<List<Item> >&, List<Item>&, List<Item>&, enum_duplicates, bool) /10.3/sql/sql_insert.cc:1071 #9 0x5594d1bc4a8d in mysql_execute_command(THD*) /10.3/sql/sql_parse.cc:4735 #10 0x5594d1bda295 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /10.3/sql/sql_parse.cc:8105 #11 0x5594d1bb4d9d in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /10.3/sql/sql_parse.cc:1858 #12 0x5594d1bb1f01 in do_command(THD*) /10.3/sql/sql_parse.cc:1404 #13 0x5594d1f08ec1 in do_handle_one_connection(CONNECT*) /10.3/sql/sql_connect.cc:1402 #14 0x5594d1f0889e in handle_one_connection /10.3/sql/sql_connect.cc:1308 #15 0x5594d3231cc0 in pfs_spawn_thread /10.3/storage/perfschema/pfs.cc:1862 #16 0x7f987a1eb6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9) #17 0x7f987968041c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c) With MYISAM it results in a wrong values in the auto_incremented column: CREATE TABLE t1 ( id1 int NOT NULL , id2 int NOT NULL , id int (11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id1,id2), KEY id (id)) ENGINE=myisam AUTO_INCREMENT=1 PARTITION BY HASH (id1) (PARTITION p0001, PARTITION p0002);   INSERT INTO t1 partition(p0002) (id1,id2) VALUES (1,1), (1,2), (1,3);   ANALYZE TABLE t1; INSERT INTO t1 partition(p0001) ( id1, id2) VALUES (2,1), (2,2), (2,3), (2,4), (2,5) ; SELECT id, count (*) FROM t1 GROUP BY id; MariaDB [test]> SELECT id, count(*) FROM t1 GROUP BY id; +----+----------+ | id | count(*) | +----+----------+ | 1 | 2 | | 2 | 2 | | 3 | 2 | | 4 | 1 | | 5 | 1 | +----+----------+ 5 rows in set (0.000 sec)
            alice Alice Sherepa added a comment -

            holyfoot, please check also test case from MDEV-20718 before closing:

            create table t1 (
            	id int(10) not null auto_increment,
            	groupid int,
            	name varchar(255),
            	primary key (id, groupid)
            )engine=innodb
            partition by list(groupid) (partition p1 values in (1), partition p2 values in (2));
             
            alter table t1 truncate partition p1;
            insert into t1 partition (p1) (groupid, name) values (1, 'tamara smith');
            select * from t1;
            

            alice Alice Sherepa added a comment - holyfoot , please check also test case from MDEV-20718 before closing: create table t1 ( id int (10) not null auto_increment, groupid int , name varchar (255), primary key (id, groupid) )engine=innodb partition by list(groupid) (partition p1 values in (1), partition p2 values in (2));   alter table t1 truncate partition p1; insert into t1 partition (p1) (groupid, name ) values (1, 'tamara smith' ); select * from t1;
            holyfoot Alexey Botchkov added a comment - https://github.com/MariaDB/server/commit/7a331ec820be89f8c2d0fd968bd4b003cbbf75fc
            jacob.williams Jacob Williams added a comment - - edited

            I noticed a related bug, but it may be the same root cause.

            We have some tables with old datetime columns, not yet updated to new temporal storage type. After doing a partition drop/add, the dates and times in the other partitions become corrupted. The dates look like nonsense afterward, and updating rows in the table will cause additional corruption in other columns.

            My theory is that the ALTER statement for DROP/ADD causes it to "upgrade" the datetime columns to the new temporal type, or at least mark them as updated, but it doesn't actually go into the other partitions to update the data on disk. When it goes back to read or modify the data, it reads the old datetime value and tries to interpret as if it was the new type.

            In my tests, upgrading to new temporal type by doing a non-partition targeted alter statement before doing partition maintenance prevented the corruption.

            jacob.williams Jacob Williams added a comment - - edited I noticed a related bug, but it may be the same root cause. We have some tables with old datetime columns, not yet updated to new temporal storage type. After doing a partition drop/add, the dates and times in the other partitions become corrupted. The dates look like nonsense afterward, and updating rows in the table will cause additional corruption in other columns. My theory is that the ALTER statement for DROP/ADD causes it to "upgrade" the datetime columns to the new temporal type, or at least mark them as updated, but it doesn't actually go into the other partitions to update the data on disk. When it goes back to read or modify the data, it reads the old datetime value and tries to interpret as if it was the new type. In my tests, upgrading to new temporal type by doing a non-partition targeted alter statement before doing partition maintenance prevented the corruption.

            Test case from MDEV-20910 – holyfoot, please make sure it is fixed as well before closing the bug:

            --source include/have_innodb.inc
            --source include/have_partition.inc
             
            CREATE TABLE `t` (
            `id` INT(5) NOT NULL AUTO_INCREMENT,
            PRIMARY KEY (`id`)
            ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
            PARTITION BY HASH (`id`)
            (PARTITION `p1`, 
            PARTITION `p2`);
             
            INSERT INTO t PARTITION (p1) VALUES (1);
            

            Given the number of affected users and the fact that it has already undergone at least one round of review, I'm raising it to a blocker.

            elenst Elena Stepanova added a comment - Test case from MDEV-20910 – holyfoot , please make sure it is fixed as well before closing the bug: --source include/have_innodb.inc --source include/have_partition.inc   CREATE TABLE `t` ( `id` INT (5) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT= DYNAMIC PARTITION BY HASH (`id`) (PARTITION `p1`, PARTITION `p2`); INSERT INTO t PARTITION (p1) VALUES (1); Given the number of affected users and the fact that it has already undergone at least one round of review, I'm raising it to a blocker.

            To be clear, this also affects RANGE partitions too:

            Test case:

            CREATE TABLE `t1` (
            `id1` BIGINT(20) NOT NULL AUTO_INCREMENT,
            `id2` BIGINT(20) NOT NULL,
            PRIMARY KEY (`id1`,`id2`)
            ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
            PARTITION BY RANGE (`id2`)
            (PARTITION `p1` VALUES LESS THAN (100),
            PARTITION `p2` VALUES LESS THAN (200),
            PARTITION `p3` VALUES LESS THAN MAXVALUE);
             
            INSERT INTO t1 PARTITION (p1) VALUES (1,1);
            

            Session Output:

            mysql> CREATE TABLE `t1` (
                -> `id1` BIGINT(20) NOT NULL AUTO_INCREMENT,
                -> `id2` BIGINT(20) NOT NULL,
                -> PRIMARY KEY (`id1`,`id2`)
                -> ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
                -> PARTITION BY RANGE (`id2`)
                -> (PARTITION `p1` VALUES LESS THAN (100),
                -> PARTITION `p2` VALUES LESS THAN (200),
                -> PARTITION `p3` VALUES LESS THAN MAXVALUE);
            ERROR 1050 (42S01): Table 't1' already exists
            mysql>
            mysql> INSERT INTO t1 PARTITION (p1) VALUES (1,1);
            ERROR 2013 (HY000): Lost connection to MySQL server during query
            

            ccalender Chris Calender (Inactive) added a comment - To be clear, this also affects RANGE partitions too: Test case: CREATE TABLE `t1` ( `id1` BIGINT(20) NOT NULL AUTO_INCREMENT, `id2` BIGINT(20) NOT NULL, PRIMARY KEY (`id1`,`id2`) ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC PARTITION BY RANGE (`id2`) (PARTITION `p1` VALUES LESS THAN (100), PARTITION `p2` VALUES LESS THAN (200), PARTITION `p3` VALUES LESS THAN MAXVALUE);   INSERT INTO t1 PARTITION (p1) VALUES (1,1); Session Output: mysql> CREATE TABLE `t1` ( -> `id1` BIGINT(20) NOT NULL AUTO_INCREMENT, -> `id2` BIGINT(20) NOT NULL, -> PRIMARY KEY (`id1`,`id2`) -> ) ENGINE=INNODB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC -> PARTITION BY RANGE (`id2`) -> (PARTITION `p1` VALUES LESS THAN (100), -> PARTITION `p2` VALUES LESS THAN (200), -> PARTITION `p3` VALUES LESS THAN MAXVALUE); ERROR 1050 (42S01): Table 't1' already exists mysql> mysql> INSERT INTO t1 PARTITION (p1) VALUES (1,1); ERROR 2013 (HY000): Lost connection to MySQL server during query

            I realized my comment above probably does relate to this bug. Reported it separately in MDEV-20940.

            jacob.williams Jacob Williams added a comment - I realized my comment above probably does relate to this bug. Reported it separately in MDEV-20940 .

            People

              holyfoot Alexey Botchkov
              elenst Elena Stepanova
              Votes:
              0 Vote for this issue
              Watchers:
              10 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.