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

Assertion `col->ord_part' in row_build_index_entry_low upon ROLLBACK or DELETE with concurrent ALTER on partitioned table

Details

    Description

      Note: It's possible that system versioning has nothing to do with the problem, but I couldn't avoid it in the test case: even if I switch from SYSTEM_TIME partitioning to HASH (both test cases are below), the problems still only happen when the table is system-versioned. Replacing it with explicit invisible columns doesn't help.

      Run test cases with --repeat=N --mem. N=50 has always been enough for me if the test is run in memory, although it can vary on different machines. The problem can also be hit if the test runs on disk, I don't have enough statistics to say anything about probability.

      IMPORTANT: Please note that the test is written to accept ER_DUP_ENTRY to allow multiple runs with repeat, but in fact this error itself is wrong. The test first removes two rows with potentially duplicate keys, and only then runs ALTER which adds the unique key. There is no user-level race condition for ER_DUP_ENTRY to happen, whatever causes it is in internals and it's wrong.

      Non-debug build doesn't (naturally) have the assertion failure and doesn't crash, but it has the same duplicate key error.

      PARTITION BY HASH, ROLLBACK

      --source include/have_partition.inc
      --source include/have_innodb.inc
       
      CREATE TABLE t1 (i INT, f VARCHAR(10)) ENGINE=InnoDB WITH SYSTEM VERSIONING PARTITION BY HASH(i) PARTITIONS 2;
      INSERT INTO t1 VALUES (1,'foo'),(2,'bar'),(2,'bar');
      DELETE FROM t1 WHERE f = 'bar';
       
      --connect (con1,localhost,root,,test)
      --send
        ALTER TABLE t1 ADD UNIQUE KEY (f(3),i);
       
      --connection default
      DELETE FROM t1 WHERE f = 'foo';
      BEGIN;
      INSERT INTO t1 VALUES (1,'foo');
      ROLLBACK;
       
      # Cleanup
      --connection con1
      --error ER_DUP_ENTRY
      --reap
      --disconnect con1
      --connection default
      DROP TABLE t1;
      

      PARTITION BY SYSTEM_TIME, ROLLBACK

      --source include/have_partition.inc
      --source include/have_innodb.inc
       
      CREATE TABLE t1 (f VARCHAR(10)) ENGINE=InnoDB WITH SYSTEM VERSIONING PARTITION BY system_time ( PARTITION ph HISTORY, PARTITION pc CURRENT );
      INSERT INTO t1 VALUES ('foo'),('bar'),('bar');
      DELETE FROM t1 WHERE f = 'bar';
       
      --connect (con1,localhost,root,,test)
      --send
        ALTER TABLE t1 ADD UNIQUE KEY (f(3));
       
      --connection default
      DELETE FROM t1 WHERE f = 'foo';
      BEGIN;
      INSERT INTO t1 VALUES ('foo');
      ROLLBACK;
       
      # Cleanup
      --connection con1
      --error ER_DUP_ENTRY
      --reap
      --disconnect con1
      --connection default
      DROP TABLE t1;
      

      10.3 cb16bc95ff9

      mysqld: /data/src/10.3/storage/innobase/row/row0row.cc:295: dtuple_t* row_build_index_entry_low(const dtuple_t*, const row_ext_t*, dict_index_t*, mem_heap_t*, ulint): Assertion `col->ord_part' failed.
      180501 20:19:59 [ERROR] mysqld got signal 6 ;
       
      #7  0x00007f15ba2a6ee2 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
      #8  0x000055ff44ff5eff in row_build_index_entry_low (row=0x7f156003e538, ext=0x0, index=0x7f156404fe38, heap=0x7f156003e850, flag=0) at /data/src/10.3/storage/innobase/row/row0row.cc:295
      #9  0x000055ff4521ea97 in row_build_index_entry (row=0x7f156003e538, ext=0x0, index=0x7f156404fe38, heap=0x7f156003e850) at /data/src/10.3/storage/innobase/include/row0row.ic:131
      #10 0x000055ff4522035c in row_undo_ins_remove_sec_rec (node=0x7f156003de08, thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/row/row0uins.cc:520
      #11 0x000055ff45220695 in row_undo_ins (node=0x7f156003de08, thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/row/row0uins.cc:593
      #12 0x000055ff45022816 in row_undo (node=0x7f156003de08, thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/row/row0undo.cc:303
      #13 0x000055ff45022a57 in row_undo_step (thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/row/row0undo.cc:362
      #14 0x000055ff44f74750 in que_thr_step (thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/que/que0que.cc:1044
      #15 0x000055ff44f7499f in que_run_threads_low (thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/que/que0que.cc:1108
      #16 0x000055ff44f74b90 in que_run_threads (thr=0x7f156003dc38) at /data/src/10.3/storage/innobase/que/que0que.cc:1148
      #17 0x000055ff45083b71 in trx_rollback_to_savepoint_low (trx=0x7f15b40e23a8, savept=0x0) at /data/src/10.3/storage/innobase/trx/trx0roll.cc:145
      #18 0x000055ff45083fdf in trx_rollback_for_mysql_low (trx=0x7f15b40e23a8) at /data/src/10.3/storage/innobase/trx/trx0roll.cc:214
      #19 0x000055ff4508431e in trx_rollback_for_mysql (trx=0x7f15b40e23a8) at /data/src/10.3/storage/innobase/trx/trx0roll.cc:240
      #20 0x000055ff44e6fa81 in innobase_rollback (hton=0x55ff47954b60, thd=0x7f1560000b00, rollback_trx=true) at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:4680
      #21 0x000055ff44b5a0ef in ha_rollback_trans (thd=0x7f1560000b00, all=true) at /data/src/10.3/sql/handler.cc:1721
      #22 0x000055ff449e67df in trans_rollback (thd=0x7f1560000b00) at /data/src/10.3/sql/transaction.cc:422
      #23 0x000055ff4487d679 in mysql_execute_command (thd=0x7f1560000b00) at /data/src/10.3/sql/sql_parse.cc:5829
      #24 0x000055ff44883a46 in mysql_parse (thd=0x7f1560000b00, rawbuf=0x7f1560014d68 "ROLLBACK", length=8, parser_state=0x7f15b404c5d0, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:8001
      #25 0x000055ff44871229 in dispatch_command (command=COM_QUERY, thd=0x7f1560000b00, packet=0x7f1560125fb1 "ROLLBACK", packet_length=8, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:1846
      #26 0x000055ff4486fc68 in do_command (thd=0x7f1560000b00) at /data/src/10.3/sql/sql_parse.cc:1391
      #27 0x000055ff449d2aef in do_handle_one_connection (connect=0x55ff47d7c770) at /data/src/10.3/sql/sql_connect.cc:1402
      #28 0x000055ff449d287c in handle_one_connection (arg=0x55ff47d7c770) at /data/src/10.3/sql/sql_connect.cc:1308
      #29 0x000055ff44e56a8d in pfs_spawn_thread (arg=0x55ff47d84bf0) at /data/src/10.3/storage/perfschema/pfs.cc:1862
      #30 0x00007f15bbf7d494 in start_thread (arg=0x7f15b404d700) at pthread_create.c:333
      #31 0x00007f15ba36393f in clone () from /lib/x86_64-linux-gnu/libc.so.6
      

      PARTITION BY SYSTEM_TIME, DELETE

      --source include/have_partition.inc
      --source include/have_innodb.inc
       
      CREATE TABLE t1 (f VARCHAR(10)) ENGINE=InnoDB WITH SYSTEM VERSIONING PARTITION BY system_time ( PARTITION ph HISTORY, PARTITION pc CURRENT );
      INSERT INTO t1 VALUES ('foo'),('bar'),('bar');
      DELETE FROM t1 WHERE f = 'bar';
       
      --connect (con1,localhost,root,,test)
      --send
        ALTER TABLE t1 ADD UNIQUE KEY (f(3));
       
      --connection default
      DELETE FROM t1 WHERE f = 'foo';
      INSERT INTO t1 VALUES ('foo');
      DELETE FROM t1;
       
      # Cleanup
      --connection con1
      --error ER_DUP_ENTRY
      --reap
      --disconnect con1
      --connection default
      DROP TABLE t1;
      

      10.3 cb16bc95ff9

      mysqld: /data/src/10.3/storage/innobase/row/row0row.cc:295: dtuple_t* row_build_index_entry_low(const dtuple_t*, const row_ext_t*, dict_index_t*, mem_heap_t*, ulint): Assertion `col->ord_part' failed.
      180501 20:24:02 [ERROR] mysqld got signal 6 ;
       
      #7  0x00007f215a6b4ee2 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
      #8  0x000056188a1c9eff in row_build_index_entry_low (row=0x7f210803cfa8, ext=0x0, index=0x7f20fc051a38, heap=0x7f210803d200, flag=0) at /data/src/10.3/storage/innobase/row/row0row.cc:295
      #9  0x000056188a1fbd52 in row_build_index_entry (row=0x7f210803cfa8, ext=0x0, index=0x7f20fc051a38, heap=0x7f210803d200) at /data/src/10.3/storage/innobase/include/row0row.ic:131
      #10 0x000056188a20102d in row_upd_sec_index_entry (node=0x7f210803c650, thr=0x7f210803c988) at /data/src/10.3/storage/innobase/row/row0upd.cc:2298
      #11 0x000056188a201d81 in row_upd_sec_step (node=0x7f210803c650, thr=0x7f210803c988) at /data/src/10.3/storage/innobase/row/row0upd.cc:2541
      #12 0x000056188a204519 in row_upd (node=0x7f210803c650, thr=0x7f210803c988) at /data/src/10.3/storage/innobase/row/row0upd.cc:3309
      #13 0x000056188a204881 in row_upd_step (thr=0x7f210803c988) at /data/src/10.3/storage/innobase/row/row0upd.cc:3424
      #14 0x000056188a1a13b6 in row_update_for_mysql (prebuilt=0x7f210803bb18) at /data/src/10.3/storage/innobase/row/row0mysql.cc:1882
      #15 0x000056188a04d9d7 in ha_innobase::delete_row (this=0x7f21081769b8, record=0x7f2108175d90 "\376\003foo") at /data/src/10.3/storage/innobase/handler/ha_innodb.cc:9005
      #16 0x0000561889d3ad1f in handler::ha_delete_row (this=0x7f21081769b8, buf=0x7f2108175d90 "\376\003foo") at /data/src/10.3/sql/handler.cc:6272
      #17 0x000056188a49253f in ha_partition::update_row (this=0x7f21081754a8, old_data=0x7f2108175d90 "\376\003foo", new_data=0x7f2108175d70 "\376\003foo") at /data/src/10.3/sql/ha_partition.cc:4392
      #18 0x0000561889d3a936 in handler::ha_update_row (this=0x7f21081754a8, old_data=0x7f2108175d90 "\376\003foo", new_data=0x7f2108175d70 "\376\003foo") at /data/src/10.3/sql/handler.cc:6216
      #19 0x0000561889ed04d5 in TABLE::delete_row (this=0x7f2108174860) at /data/src/10.3/sql/sql_delete.cc:257
      #20 0x0000561889ecd84c in mysql_delete (thd=0x7f2108000b00, table_list=0x7f2108014e30, conds=0x0, order_list=0x7f2108005348, limit=18446744073709551615, options=0, result=0x0) at /data/src/10.3/sql/sql_delete.cc:748
      #21 0x0000561889a4dfbe in mysql_execute_command (thd=0x7f2108000b00) at /data/src/10.3/sql/sql_parse.cc:4922
      #22 0x0000561889a57a46 in mysql_parse (thd=0x7f2108000b00, rawbuf=0x7f2108014d68 "DELETE FROM t1", length=14, parser_state=0x7f215425a5d0, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:8001
      #23 0x0000561889a45229 in dispatch_command (command=COM_QUERY, thd=0x7f2108000b00, packet=0x7f2108125fd1 "DELETE FROM t1", packet_length=14, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:1846
      #24 0x0000561889a43c68 in do_command (thd=0x7f2108000b00) at /data/src/10.3/sql/sql_parse.cc:1391
      #25 0x0000561889ba6aef in do_handle_one_connection (connect=0x56188ccd96a0) at /data/src/10.3/sql/sql_connect.cc:1402
      #26 0x0000561889ba687c in handle_one_connection (arg=0x56188ccd96a0) at /data/src/10.3/sql/sql_connect.cc:1308
      #27 0x000056188a02aa8d in pfs_spawn_thread (arg=0x56188cce1b20) at /data/src/10.3/storage/perfschema/pfs.cc:1862
      #28 0x00007f215c38b494 in start_thread (arg=0x7f215425b700) at pthread_create.c:333
      #29 0x00007f215a77193f in clone () from /lib/x86_64-linux-gnu/libc.so.6
      

      Attachments

        Issue Links

          Activity

            This appears to be corruption of the InnoDB data dictionary cache. Maybe some DDL operation is not correctly updating the dict_col_t::ord_part flag. Could there have been an aborted DROP INDEX operation in the past?

            marko Marko Mäkelä added a comment - This appears to be corruption of the InnoDB data dictionary cache. Maybe some DDL operation is not correctly updating the dict_col_t::ord_part flag. Could there have been an aborted DROP INDEX operation in the past?

            It turns out that the assertion failed in DELETE FROM t1 for the unique index that had failed to be built because of a duplicate key. There should be nothing particular in MariaDB 10.3 about this; a similar failure should be possible in 10.0 already.

            The issue is that the predicate dict_index_is_corrupted() does not consider index->online_status. I would replace it with a better predicate:

            inline bool dict_index_t::is_corrupted() const
            {
            	return UNIV_UNLIKELY(online_status >= ONLINE_INDEX_ABORTED
            			     || (type & DICT_CORRUPT)
            			     || (table && table->corrupted));
            }
            

            With this predicate, all variations of the test passed for me.

            marko Marko Mäkelä added a comment - It turns out that the assertion failed in DELETE FROM t1 for the unique index that had failed to be built because of a duplicate key. There should be nothing particular in MariaDB 10.3 about this; a similar failure should be possible in 10.0 already. The issue is that the predicate dict_index_is_corrupted()  does not consider index->online_status . I would replace it with a better predicate: inline bool dict_index_t::is_corrupted() const { return UNIV_UNLIKELY(online_status >= ONLINE_INDEX_ABORTED || (type & DICT_CORRUPT) || (table && table->corrupted)); } With this predicate, all variations of the test passed for me.

            The test case depends on system-versioned tables (MDEV-12894), which were introduced in MariaDB 10.3.4.

            The ALTER TABLE operation is creating an unique secondary index when a duplicate key exists. I tried to reproduce the scenario in MariaDB 10.0, but I failed to crash the server. Here is one version of my test:

            --source include/have_innodb.inc
            --source include/have_partition.inc
            --source include/have_debug.inc
            --source include/have_debug_sync.inc
             
            CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB
            PARTITION BY RANGE(a)
            (PARTITION pa VALUES LESS THAN (3),
            PARTITION pb VALUES LESS THAN (5));
             
            INSERT INTO t1 VALUES(2,2),(2,2),(4,4);
             
            connect ddl,localhost,root,,test;
            SET DEBUG_SYNC = 'inplace_after_index_build SIGNAL go WAIT_FOR done';
            send ALTER TABLE t1 ADD UNIQUE KEY (a,b);
             
            connection default;
            SET DEBUG_SYNC = 'now WAIT_FOR go';
            BEGIN;
            SELECT * FROM t1 FOR UPDATE;
            SET DEBUG_SYNC = 'now SIGNAL done';
             
            connection ddl;
            --error ER_DUP_ENTRY
            reap;
             
            connection default;
            DELETE FROM t1;
            disconnect ddl;
             
            SET DEBUG_SYNC = 'RESET';
             
            CHECK TABLE t1;
            DROP TABLE t1;
            

            During DELETE a stub for the unique index exists. The index creation obviously failed before the DELETE completed execution, just like it failed in my test case above (which failed to kill the server). Here is my stack trace from 10.3:

            10.3 005d53f6d59fe8e1e118c63b9af57fea2a31f4f2

            #7  0x00007f3357f5aa52 in __GI___assert_fail (assertion=0x3599ba0 <.str.10> "col->ord_part", file=0x35997c0 <.str.1> "/mariadb/10.3/storage/innobase/row/row0row.cc", line=294, function=0x3599880 <__PRETTY_FUNCTION__._Z25row_build_index_entry_lowPK8dtuple_tPK9row_ext_tP12dict_index_tP16mem_block_info_tm> "dtuple_t *row_build_index_entry_low(const dtuple_t *, const row_ext_t *, dict_index_t *, mem_heap_t *, ulint)") at assert.c:101
            #8  0x0000000002090f8c in row_build_index_entry_low (row=0x61700008cb88, ext=0x0, index=0x617000093108, heap=0x61a0000a1a80, flag=0) at /mariadb/10.3/storage/innobase/row/row0row.cc:294
            #9  0x0000000002140865 in row_build_index_entry (row=0x61700008cb88, ext=0x0, index=0x617000093108, heap=0x61a0000a1a80) at /mariadb/10.3/storage/innobase/include/row0row.ic:130
            #10 0x000000000213ec06 in row_upd_sec_index_entry (node=0x6210000cb4c0, thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:2293
            #11 0x0000000002135c62 in row_upd_sec_step (node=0x6210000cb4c0, thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:2536
            #12 0x000000000212e22e in row_upd (node=0x6210000cb4c0, thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:3304
            #13 0x000000000212ce52 in row_upd_step (thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:3419
            #14 0x000000000201e4d9 in row_update_for_mysql (prebuilt=0x6210000ca988) at /mariadb/10.3/storage/innobase/row/row0mysql.cc:1882
            #15 0x0000000001c38e4a in ha_innobase::delete_row (this=0x61d00033d6a0, record=0x61900016f3d8 "\376\003foo") at /mariadb/10.3/storage/innobase/handler/ha_innodb.cc:9000
            #16 0x000000000153948a in handler::ha_delete_row (this=0x61d00033d6a0, buf=0x61900016f3d8 "\376\003foo") at /mariadb/10.3/sql/handler.cc:6273
            #17 0x0000000002c33505 in ha_partition::update_row (this=0x61d00033c2a0, old_data=0x61900016f3d8 "\376\003foo", new_data=0x61900016f3b8 "\376\003foo") at /mariadb/10.3/sql/ha_partition.cc:4427
            #18 0x00000000015389dc in handler::ha_update_row (this=0x61d00033c2a0, old_data=0x61900016f3d8 "\376\003foo", new_data=0x61900016f3b8 "\376\003foo") at /mariadb/10.3/sql/handler.cc:6217
            #19 0x0000000001aad4e3 in TABLE::delete_row (this=0x61f000066688) at /mariadb/10.3/sql/sql_delete.cc:257
            #20 0x0000000001aa1183 in mysql_delete (thd=0x62a0000ae208, table_list=0x62b0000002e8, conds=0x0, order_list=0x62a0000b28c0, limit=18446744073709551615, options=0, result=0x0) at /mariadb/10.3/sql/sql_delete.cc:751
            #21 0x0000000000b6ccca in mysql_execute_command (thd=0x62a0000ae208) at /mariadb/10.3/sql/sql_parse.cc:4920
            #22 0x0000000000b527d4 in mysql_parse (thd=0x62a0000ae208, rawbuf=0x62b000000220 "DELETE FROM t1", length=14, parser_state=0x7f3345fc8da0, is_com_multi=false, is_next_command=false) at /mariadb/10.3/sql/sql_parse.cc:8003
            

            Because I cannot trigger this in earlier versions, I will fix this in 10.3 only.

            marko Marko Mäkelä added a comment - The test case depends on system-versioned tables ( MDEV-12894 ), which were introduced in MariaDB 10.3.4. The ALTER TABLE operation is creating an unique secondary index when a duplicate key exists. I tried to reproduce the scenario in MariaDB 10.0, but I failed to crash the server. Here is one version of my test: --source include/have_innodb.inc --source include/have_partition.inc --source include/have_debug.inc --source include/have_debug_sync.inc   CREATE TABLE t1 (a INT , b INT ) ENGINE=InnoDB PARTITION BY RANGE(a) (PARTITION pa VALUES LESS THAN (3), PARTITION pb VALUES LESS THAN (5));   INSERT INTO t1 VALUES (2,2),(2,2),(4,4);   connect ddl,localhost,root,,test; SET DEBUG_SYNC = 'inplace_after_index_build SIGNAL go WAIT_FOR done' ; send ALTER TABLE t1 ADD UNIQUE KEY (a,b);   connection default ; SET DEBUG_SYNC = 'now WAIT_FOR go' ; BEGIN ; SELECT * FROM t1 FOR UPDATE ; SET DEBUG_SYNC = 'now SIGNAL done' ;   connection ddl; --error ER_DUP_ENTRY reap;   connection default ; DELETE FROM t1; disconnect ddl;   SET DEBUG_SYNC = 'RESET' ;   CHECK TABLE t1; DROP TABLE t1; During DELETE  a stub for the unique index exists. The index creation obviously failed before the DELETE  completed execution, just like it failed in my test case above (which failed to kill the server). Here is my stack trace from 10.3: 10.3 005d53f6d59fe8e1e118c63b9af57fea2a31f4f2 #7 0x00007f3357f5aa52 in __GI___assert_fail (assertion=0x3599ba0 <.str.10> "col->ord_part", file=0x35997c0 <.str.1> "/mariadb/10.3/storage/innobase/row/row0row.cc", line=294, function=0x3599880 <__PRETTY_FUNCTION__._Z25row_build_index_entry_lowPK8dtuple_tPK9row_ext_tP12dict_index_tP16mem_block_info_tm> "dtuple_t *row_build_index_entry_low(const dtuple_t *, const row_ext_t *, dict_index_t *, mem_heap_t *, ulint)") at assert.c:101 #8 0x0000000002090f8c in row_build_index_entry_low (row=0x61700008cb88, ext=0x0, index=0x617000093108, heap=0x61a0000a1a80, flag=0) at /mariadb/10.3/storage/innobase/row/row0row.cc:294 #9 0x0000000002140865 in row_build_index_entry (row=0x61700008cb88, ext=0x0, index=0x617000093108, heap=0x61a0000a1a80) at /mariadb/10.3/storage/innobase/include/row0row.ic:130 #10 0x000000000213ec06 in row_upd_sec_index_entry (node=0x6210000cb4c0, thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:2293 #11 0x0000000002135c62 in row_upd_sec_step (node=0x6210000cb4c0, thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:2536 #12 0x000000000212e22e in row_upd (node=0x6210000cb4c0, thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:3304 #13 0x000000000212ce52 in row_upd_step (thr=0x6210000cb7f8) at /mariadb/10.3/storage/innobase/row/row0upd.cc:3419 #14 0x000000000201e4d9 in row_update_for_mysql (prebuilt=0x6210000ca988) at /mariadb/10.3/storage/innobase/row/row0mysql.cc:1882 #15 0x0000000001c38e4a in ha_innobase::delete_row (this=0x61d00033d6a0, record=0x61900016f3d8 "\376\003foo") at /mariadb/10.3/storage/innobase/handler/ha_innodb.cc:9000 #16 0x000000000153948a in handler::ha_delete_row (this=0x61d00033d6a0, buf=0x61900016f3d8 "\376\003foo") at /mariadb/10.3/sql/handler.cc:6273 #17 0x0000000002c33505 in ha_partition::update_row (this=0x61d00033c2a0, old_data=0x61900016f3d8 "\376\003foo", new_data=0x61900016f3b8 "\376\003foo") at /mariadb/10.3/sql/ha_partition.cc:4427 #18 0x00000000015389dc in handler::ha_update_row (this=0x61d00033c2a0, old_data=0x61900016f3d8 "\376\003foo", new_data=0x61900016f3b8 "\376\003foo") at /mariadb/10.3/sql/handler.cc:6217 #19 0x0000000001aad4e3 in TABLE::delete_row (this=0x61f000066688) at /mariadb/10.3/sql/sql_delete.cc:257 #20 0x0000000001aa1183 in mysql_delete (thd=0x62a0000ae208, table_list=0x62b0000002e8, conds=0x0, order_list=0x62a0000b28c0, limit=18446744073709551615, options=0, result=0x0) at /mariadb/10.3/sql/sql_delete.cc:751 #21 0x0000000000b6ccca in mysql_execute_command (thd=0x62a0000ae208) at /mariadb/10.3/sql/sql_parse.cc:4920 #22 0x0000000000b527d4 in mysql_parse (thd=0x62a0000ae208, rawbuf=0x62b000000220 "DELETE FROM t1", length=14, parser_state=0x7f3345fc8da0, is_com_multi=false, is_next_command=false) at /mariadb/10.3/sql/sql_parse.cc:8003 Because I cannot trigger this in earlier versions, I will fix this in 10.3 only.

            My test would not cover the assertion failure, because the assertion would only be executed if there is a column prefix index. The assertion is present in 10.0, and col->ord_part holds when the assertion is executed there:

            10.1 xtradb 7b9486d2eb3876d55edc05173235e6ccad2e6ae3

            #0  row_build_index_entry_low (row=0x7fffc001ecf8, ext=0x0, 
                index=0x7fffb4017c58, heap=0x7fffc00280f0)
                at /mariadb/10.0/storage/xtradb/row/row0row.cc:135
            #1  0x0000555556013971 in row_build_index_entry (row=0x7fffc001ecf8, ext=0x0, 
                index=0x7fffb4017c58, heap=0x7fffc00280f0)
                at /mariadb/10.0/storage/xtradb/include/row0row.ic:129
            #2  0x0000555556016d2b in row_upd_sec_index_entry (node=0x7fffc0035a78, 
                thr=0x7fffc0035d28) at /mariadb/10.0/storage/xtradb/row/row0upd.cc:1673
            #3  0x000055555601746d in row_upd_sec_step (node=0x7fffc0035a78, 
                thr=0x7fffc0035d28) at /mariadb/10.0/storage/xtradb/row/row0upd.cc:1863
            #4  0x0000555556018d9f in row_upd (node=0x7fffc0035a78, thr=0x7fffc0035d28)
                at /mariadb/10.0/storage/xtradb/row/row0upd.cc:2586
            #5  0x0000555556019089 in row_upd_step (thr=0x7fffc0035d28)
                at /mariadb/10.0/storage/xtradb/row/row0upd.cc:2703
            #6  0x0000555555fdc7d6 in row_update_for_mysql (
                mysql_rec=0x7fffc00075a8 "\374\004", prebuilt=0x7fffc0035048)
                at /mariadb/10.0/storage/xtradb/row/row0mysql.cc:1814
            #7  0x0000555555ee3097 in ha_innobase::delete_row (this=0x7fffc00255e0, 
                record=0x7fffc00075a8 "\374\004")
                at /mariadb/10.0/storage/xtradb/handler/ha_innodb.cc:8579
            #8  0x0000555555bd3045 in handler::ha_delete_row (this=0x7fffc00255e0, 
                buf=0x7fffc00075a8 "\374\004") at /mariadb/10.0/sql/handler.cc:6094
            #9  0x000055555617f327 in ha_partition::delete_row (this=0x7fffc0024790, 
                buf=0x7fffc00075a8 "\374\004") at /mariadb/10.0/sql/ha_partition.cc:4428
            #10 0x0000555555bd2fff in handler::ha_delete_row (this=0x7fffc0024790, 
                buf=0x7fffc00075a8 "\374\004") at /mariadb/10.0/sql/handler.cc:6094
            #11 0x0000555555d1e2d2 in mysql_delete (thd=0x555557b8a108, 
                table_list=0x7fffc0012338, conds=0x0, order_list=0x555557b8e3f8, 
                limit=18446744073709551613, options=0, result=0x7fffc0012920)
                at /mariadb/10.0/sql/sql_delete.cc:570
            #12 0x00005555559dbec8 in mysql_execute_command (thd=0x555557b8a108)
                at /mariadb/10.0/sql/sql_parse.cc:3599
            #13 0x00005555559e3e19 in mysql_parse (thd=0x555557b8a108, 
                rawbuf=0x7fffc0012270 "DELETE FROM t1", length=14, 
                parser_state=0x7ffff023a650) at /mariadb/10.0/sql/sql_parse.cc:6573
            #14 0x00005555559d6778 in dispatch_command (command=COM_QUERY, 
                thd=0x555557b8a108, packet=0x555557b8fa59 "DELETE FROM t1", 
                packet_length=14) at /mariadb/10.0/sql/sql_parse.cc:1296
            

            The revised test:

            --source include/have_innodb.inc
            --source include/have_partition.inc
            --source include/have_debug.inc
            --source include/have_debug_sync.inc
             
            CREATE TABLE t1 (a INT, b VARCHAR(10)) ENGINE=InnoDB
            PARTITION BY RANGE(a)
            (PARTITION pa VALUES LESS THAN (3),
            PARTITION pb VALUES LESS THAN (5));
             
            INSERT INTO t1 VALUES(2,'two'),(2,'two'),(4,'four');
             
            connect ddl,localhost,root,,test;
            SET DEBUG_SYNC = 'inplace_after_index_build SIGNAL go WAIT_FOR done';
            send ALTER TABLE t1 ADD UNIQUE KEY (a,b(3));
             
            connection default;
            SET DEBUG_SYNC = 'now WAIT_FOR go';
            BEGIN;
            SELECT * FROM t1 FOR UPDATE;
            SET DEBUG_SYNC = 'now SIGNAL done';
             
            connection ddl;
            --error ER_DUP_ENTRY
            reap;
             
            connection default;
            DELETE FROM t1;
            disconnect ddl;
             
            SET DEBUG_SYNC = 'RESET';
             
            CHECK TABLE t1;
            DROP TABLE t1;
            

            marko Marko Mäkelä added a comment - My test would not cover the assertion failure, because the assertion would only be executed if there is a column prefix index. The assertion is present in 10.0, and col->ord_part  holds when the assertion is executed there: 10.1 xtradb 7b9486d2eb3876d55edc05173235e6ccad2e6ae3 #0 row_build_index_entry_low (row=0x7fffc001ecf8, ext=0x0, index=0x7fffb4017c58, heap=0x7fffc00280f0) at /mariadb/10.0/storage/xtradb/row/row0row.cc:135 #1 0x0000555556013971 in row_build_index_entry (row=0x7fffc001ecf8, ext=0x0, index=0x7fffb4017c58, heap=0x7fffc00280f0) at /mariadb/10.0/storage/xtradb/include/row0row.ic:129 #2 0x0000555556016d2b in row_upd_sec_index_entry (node=0x7fffc0035a78, thr=0x7fffc0035d28) at /mariadb/10.0/storage/xtradb/row/row0upd.cc:1673 #3 0x000055555601746d in row_upd_sec_step (node=0x7fffc0035a78, thr=0x7fffc0035d28) at /mariadb/10.0/storage/xtradb/row/row0upd.cc:1863 #4 0x0000555556018d9f in row_upd (node=0x7fffc0035a78, thr=0x7fffc0035d28) at /mariadb/10.0/storage/xtradb/row/row0upd.cc:2586 #5 0x0000555556019089 in row_upd_step (thr=0x7fffc0035d28) at /mariadb/10.0/storage/xtradb/row/row0upd.cc:2703 #6 0x0000555555fdc7d6 in row_update_for_mysql ( mysql_rec=0x7fffc00075a8 "\374\004", prebuilt=0x7fffc0035048) at /mariadb/10.0/storage/xtradb/row/row0mysql.cc:1814 #7 0x0000555555ee3097 in ha_innobase::delete_row (this=0x7fffc00255e0, record=0x7fffc00075a8 "\374\004") at /mariadb/10.0/storage/xtradb/handler/ha_innodb.cc:8579 #8 0x0000555555bd3045 in handler::ha_delete_row (this=0x7fffc00255e0, buf=0x7fffc00075a8 "\374\004") at /mariadb/10.0/sql/handler.cc:6094 #9 0x000055555617f327 in ha_partition::delete_row (this=0x7fffc0024790, buf=0x7fffc00075a8 "\374\004") at /mariadb/10.0/sql/ha_partition.cc:4428 #10 0x0000555555bd2fff in handler::ha_delete_row (this=0x7fffc0024790, buf=0x7fffc00075a8 "\374\004") at /mariadb/10.0/sql/handler.cc:6094 #11 0x0000555555d1e2d2 in mysql_delete (thd=0x555557b8a108, table_list=0x7fffc0012338, conds=0x0, order_list=0x555557b8e3f8, limit=18446744073709551613, options=0, result=0x7fffc0012920) at /mariadb/10.0/sql/sql_delete.cc:570 #12 0x00005555559dbec8 in mysql_execute_command (thd=0x555557b8a108) at /mariadb/10.0/sql/sql_parse.cc:3599 #13 0x00005555559e3e19 in mysql_parse (thd=0x555557b8a108, rawbuf=0x7fffc0012270 "DELETE FROM t1", length=14, parser_state=0x7ffff023a650) at /mariadb/10.0/sql/sql_parse.cc:6573 #14 0x00005555559d6778 in dispatch_command (command=COM_QUERY, thd=0x555557b8a108, packet=0x555557b8fa59 "DELETE FROM t1", packet_length=14) at /mariadb/10.0/sql/sql_parse.cc:1296 The revised test: --source include/have_innodb.inc --source include/have_partition.inc --source include/have_debug.inc --source include/have_debug_sync.inc   CREATE TABLE t1 (a INT , b VARCHAR (10)) ENGINE=InnoDB PARTITION BY RANGE(a) (PARTITION pa VALUES LESS THAN (3), PARTITION pb VALUES LESS THAN (5));   INSERT INTO t1 VALUES (2, 'two' ),(2, 'two' ),(4, 'four' );   connect ddl,localhost,root,,test; SET DEBUG_SYNC = 'inplace_after_index_build SIGNAL go WAIT_FOR done' ; send ALTER TABLE t1 ADD UNIQUE KEY (a,b(3));   connection default ; SET DEBUG_SYNC = 'now WAIT_FOR go' ; BEGIN ; SELECT * FROM t1 FOR UPDATE ; SET DEBUG_SYNC = 'now SIGNAL done' ;   connection ddl; --error ER_DUP_ENTRY reap;   connection default ; DELETE FROM t1; disconnect ddl;   SET DEBUG_SYNC = 'RESET' ;   CHECK TABLE t1; DROP TABLE t1;

            The assertion does fail in MariaDB 10.2. There are a few changes to ord_part assignments in 5.7, and also some in 10.2, including this one in MariaDB 10.2.4.
            I believe that the correct action is to skip the UPDATE or DELETE operations on uncommitted indexes whose creation has failed. Updating the indexes is only merely wasting resources, but should not cause any further corruption outside the already corrupted or unusable index.

            marko Marko Mäkelä added a comment - The assertion does fail in MariaDB 10.2. There are a few changes to ord_part  assignments in 5.7, and also some in 10.2, including this one in MariaDB 10.2.4 . I believe that the correct action is to skip the UPDATE or DELETE operations on uncommitted indexes whose creation has failed. Updating the indexes is only merely wasting resources, but should not cause any further corruption outside the already corrupted or unusable index.

            A separate bug report for the duplicate key error has been created, MDEV-16102.

            elenst Elena Stepanova added a comment - A separate bug report for the duplicate key error has been created, MDEV-16102 .

            People

              marko Marko Mäkelä
              elenst Elena Stepanova
              Votes:
              0 Vote for this issue
              Watchers:
              2 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.