|
I easily repeated a crash with 10.3 and 10.4, but not 10.5 or 10.9. Possibly we can thank MDEV-16678 in 10.5 for this.
A small but important change that I applied to the test was to prevent MDEV-11369:
ALTER TABLE t ADD f INT, FORCE, ALGORITHM=INPLACE;
|
Alternative:
./mtr --mysqld=--innodb-instant-alter-column-allowed=never
|
The crash:
|
10.3 e928fdbff1369036694320ee13b99d13fe6a3b60
|
mysqltest: At line 10: query 'ALTER TABLE t ADD f INT, FORCE, ALGORITHM=INPLACE' failed: 2013: Lost connection to MySQL server during query
|
…
|
#7 0x00007f5ed9be0212 in __GI___assert_fail (assertion=0x5575b5be4778 "index->table->persistent_autoinc", file=0x5575b5be3d20 "/mariadb/10.3/storage/innobase/btr/btr0btr.cc", line=1338, function=0x5575b5be4748 "ib_uint64_t btr_read_autoinc(dict_index_t*)") at assert.c:101
|
#8 0x00005575b5669f18 in btr_read_autoinc (index=index@entry=0x7f5e840126f0) at /mariadb/10.3/storage/innobase/btr/btr0btr.cc:1338
|
#9 0x00005575b544b90b in prepare_inplace_alter_table_dict (ha_alter_info=ha_alter_info@entry=0x7f5eceb57200, altered_table=altered_table@entry=0x7f5e7013c668, old_table=<optimized out>, table_name=<optimized out>, flags=<optimized out>, flags2=<optimized out>, fts_doc_id_col=<optimized out>, add_fts_doc_id=<optimized out>, add_fts_doc_id_idx=<optimized out>) at /mariadb/10.3/storage/innobase/handler/handler0alter.cc:5773
|
#10 0x00005575b5450bca in ha_innobase::prepare_inplace_alter_table (this=0x7f5e8c00cc40, altered_table=<optimized out>, ha_alter_info=<optimized out>) at /mariadb/10.3/storage/innobase/handler/handler0alter.cc:7012
|
…
|
The table definition had been loaded by purge, but the auto-increment counter had not been initialized at that time:
#0 dict_load_table_low (name=@0x7ff9c4af9480: {m_name = 0x7ff9e000a090 "test/t"}, rec=rec@entry=0x7ff9e765c352 "test/t", table=table@entry=0x7ff9c4af8c78)
|
at /mariadb/10.3/storage/innobase/dict/dict0load.cc:2645
|
#1 0x0000564b778c2596 in dict_load_table_one (name=@0x7ff9c4af9480: {m_name = 0x7ff9e000a090 "test/t"}, ignore_err=ignore_err@entry=DICT_ERR_IGNORE_FK_NOKEY, fk_tables=std::deque with 0 elements)
|
at /mariadb/10.3/storage/innobase/dict/dict0load.cc:2927
|
#2 0x0000564b778ba9a4 in dict_load_table (name=0x7ff9e000a090 "test/t", ignore_err=ignore_err@entry=DICT_ERR_IGNORE_FK_NOKEY) at /mariadb/10.3/storage/innobase/dict/dict0load.cc:2746
|
#3 0x0000564b778c4103 in dict_load_table_on_id (table_id=table_id@entry=20, ignore_err=ignore_err@entry=DICT_ERR_IGNORE_FK_NOKEY) at /mariadb/10.3/storage/innobase/dict/dict0load.cc:3185
|
#4 0x0000564b7789e790 in dict_table_open_on_id_low (table_id=table_id@entry=20, ignore_err=DICT_ERR_IGNORE_FK_NOKEY, open_only_if_in_cache=0) at /mariadb/10.3/storage/innobase/include/dict0priv.inl:90
|
#5 0x0000564b778a683f in dict_table_open_on_id (table_id=20, dict_locked=dict_locked@entry=0, table_op=table_op@entry=DICT_TABLE_OP_NORMAL) at /mariadb/10.3/storage/innobase/dict/dict0dict.cc:824
|
#6 0x0000564b7770dabf in row_purge_parse_undo_rec (node=node@entry=0x564b792e8018, undo_rec=undo_rec@entry=0x7ff9d4011540 "", updated_extern=updated_extern@entry=0x7ff9c4af9c3f, thr=thr@entry=0x564b792e7f58)
|
at /mariadb/10.3/storage/innobase/row/row0purge.cc:1069
|
Indexed virtual columns play a role here because ha_innobase::open() would normally invoke initialize_auto_increment(). Here it did not:
#0 ha_innobase::open (this=0x7ff9dc00d1a0, name=<optimized out>) at /mariadb/10.3/storage/innobase/handler/ha_innodb.cc:6428
|
#1 0x0000564b7734266a in handler::ha_open (this=0x7ff9dc00d1a0, table_arg=table_arg@entry=0x7ff9dc00c5c8, name=0x7ff9dc00a020 "./test/t", mode=2, test_if_locked=test_if_locked@entry=18,
|
mem_root=mem_root@entry=0x0, partitions_to_open=0x0) at /mariadb/10.3/sql/handler.cc:2767
|
#2 0x0000564b771b8ae7 in open_table_from_share (thd=thd@entry=0x7ff9dc0011c8, share=share@entry=0x7ff9dc009ae0, alias=alias@entry=0x7ff9dc0090d8, db_stat=db_stat@entry=33, prgflag=prgflag@entry=8,
|
ha_open_flags=18, outparam=0x7ff9dc00c5c8, is_create_table=false, partitions_to_open=0x0) at /mariadb/10.3/sql/table.cc:3592
|
#3 0x0000564b77057d9b in open_table (thd=thd@entry=0x7ff9dc0011c8, table_list=table_list@entry=0x7ff9dc009090, ot_ctx=ot_ctx@entry=0x7ff9c54fa580) at /mariadb/10.3/sql/sql_base.cc:1992
|
#4 0x0000564b770798af in open_purge_table (thd=thd@entry=0x7ff9dc0011c8, db=db@entry=0x7ff9c54fa620 "test", dblen=4, tb=tb@entry=0x7ff9c54fa7c0 "t", tblen=1) at /mariadb/10.3/sql/sql_class.cc:4772
|
#5 0x0000564b7756c736 in innodb_acquire_mdl (thd=thd@entry=0x7ff9dc0011c8, table=table@entry=0x7ff9e00123f0) at /mariadb/10.3/storage/innobase/handler/ha_innodb.cc:20874
|
#6 0x0000564b7756ca72 in innodb_find_table_for_vc (thd=0x7ff9dc0011c8, table=table@entry=0x7ff9e00123f0) at /mariadb/10.3/storage/innobase/handler/ha_innodb.cc:20948
|
#7 0x0000564b7758c0e0 in innobase_init_vc_templ (table=0x7ff9e00123f0) at /mariadb/10.3/storage/innobase/handler/ha_innodb.cc:20986
|
#8 0x0000564b7770ded2 in row_purge_parse_undo_rec (node=node@entry=0x564b792e8650, undo_rec=undo_rec@entry=0x7ff9d40134a8 "", updated_extern=updated_extern@entry=0x7ff9c54fac3f, thr=thr@entry=0x564b792e81d0)
|
at /mariadb/10.3/storage/innobase/row/row0purge.cc:1108
|
Here, for_vc_purge holds and the call will be skipped:
const my_bool for_vc_purge = THDVAR(thd, background_thread);
|
|
if (for_vc_purge || !m_prebuilt->table
|
|| m_prebuilt->table->is_temporary()
|
|| m_prebuilt->table->persistent_autoinc
|
|| !m_prebuilt->table->is_readable()) {
|
} else if (const Field* ai = table->found_next_number_field) {
|
initialize_auto_increment(m_prebuilt->table, ai);
|
}
|
This condition was added in MDEV-25664 in order to avoid a hang during purge.
In the trace of 10.9 that I tested, the table is likewise opened by purge:
#0 dict_load_table_on_id (table_id=table_id@entry=18,
|
ignore_err=DICT_ERR_IGNORE_FK_NOKEY)
|
at /mariadb/10.9/storage/innobase/dict/dict0load.cc:2487
|
#1 0x000055baa9cff89d in dict_table_open_on_id (table_id=18,
|
dict_locked=dict_locked@entry=false,
|
table_op=table_op@entry=DICT_TABLE_OP_NORMAL, thd=0x55baac9c2668,
|
mdl=mdl@entry=0x55baacb07728)
|
at /mariadb/10.9/storage/innobase/dict/dict0dict.cc:851
|
#2 0x000055baa9ba7ee5 in row_purge_parse_undo_rec (
|
But, the purge did not invoke ha_innobase::open() for this table. The first ha_innobase::open() call was for the ALTER TABLE, which is when the dict_table_t::persistent_autoinc was correctly initialized:
#0 initialize_auto_increment (table=0x7f6a9000f518, field=0x7f6a8402ef60) at /mariadb/10.9/storage/innobase/handler/ha_innodb.cc:5841
|
#1 0x000055baa9a134e0 in ha_innobase::open (this=0x7f6a84016640, name=<optimized out>) at /mariadb/10.9/storage/innobase/handler/ha_innodb.cc:6107
|
#2 0x000055baa9680788 in handler::ha_open (this=0x7f6a84016640, table_arg=table_arg@entry=0x7f6a84030c38, name=0x7f6a8403abd8 "./test/t", mode=2, test_if_locked=test_if_locked@entry=8210,
|
mem_root=mem_root@entry=0x0, partitions_to_open=0x0) at /mariadb/10.9/sql/handler.cc:3310
|
#3 0x000055baa94a699e in open_table_from_share (thd=thd@entry=0x7f6a84001ab8, share=share@entry=0x7f6a8403a630, alias=alias@entry=0x7f6a840178b0, db_stat=db_stat@entry=33, prgflag=prgflag@entry=8,
|
ha_open_flags=8210, outparam=0x7f6a84030c38, is_create_table=false, partitions_to_open=0x0) at /mariadb/10.9/sql/table.cc:4337
|
#4 0x000055baa92e8f71 in open_table (thd=thd@entry=0x7f6a84001ab8, table_list=table_list@entry=0x7f6a84017868, ot_ctx=ot_ctx@entry=0x7f6aa8054230) at /mariadb/10.9/sql/sql_base.cc:2003
|
#5 0x000055baa92ea6c5 in open_and_process_table (thd=thd@entry=0x7f6a84001ab8, tables=tables@entry=0x7f6a84017868, counter=counter@entry=0x7f6aa8054334, flags=flags@entry=0,
|
prelocking_strategy=prelocking_strategy@entry=0x7f6aa8054358, has_prelocking_list=has_prelocking_list@entry=false, ot_ctx=0x7f6aa8054230) at /mariadb/10.9/sql/sql_base.cc:3809
|
#6 0x000055baa92ec5c0 in open_tables (thd=thd@entry=0x7f6a84001ab8, options=@0x7f6a840073c8: {m_options = DDL_options_st::OPT_NONE}, start=start@entry=0x7f6aa8054318, counter=counter@entry=0x7f6aa8054334,
|
flags=flags@entry=0, prelocking_strategy=prelocking_strategy@entry=0x7f6aa8054358) at /mariadb/10.9/sql/sql_base.cc:4292
|
#7 0x000055baa946a537 in open_tables (prelocking_strategy=0x7f6aa8054358, flags=0, counter=0x7f6aa8054334, tables=0x7f6aa8054318, thd=0x7f6a84001ab8) at /mariadb/10.9/sql/sql_base.h:265
|
#8 mysql_alter_table (thd=thd@entry=0x7f6a84001ab8, new_db=new_db@entry=0x7f6a84006760, new_name=0x7f6a84006b78, create_info=create_info@entry=0x7f6aa8056570, table_list=<optimized out>,
|
table_list@entry=0x7f6a84017868, alter_info=alter_info@entry=0x7f6aa8056480, order_num=0, order=0x0, ignore=false, if_exists=false) at /mariadb/10.9/sql/sql_table.cc:9889
|
#9 0x000055baa94f27ea in Sql_cmd_alter_table::execute (this=<optimized out>, thd=0x7f6a84001ab8) at /mariadb/10.9/sql/sql_alter.cc:547
|
#10 0x000055baa9380fdc in mysql_execute_command (thd=thd@entry=0x7f6a84001ab8, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /mariadb/10.9/sql/sql_parse.cc:5988
|
#11 0x000055baa938236d in mysql_parse (thd=thd@entry=0x7f6a84001ab8, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x7f6aa80573c0) at /mariadb/10.9/sql/sql_parse.cc:8027
|
#12 0x000055baa9384a53 in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x7f6a84001ab8, packet=packet@entry=0x7f6a8400bd69 "ALTER TABLE t ADD f INT, FORCE, ALGORITHM=INPLACE",
|
packet_length=packet_length@entry=49, blocking=blocking@entry=true) at /mariadb/10.9/sql/sql_parse.cc:1894
|
Here is a slightly better test that I used, to ensure that nothing will be purged before the server is restarted:
--source include/have_innodb.inc
|
|
--let $restart_parameters=--innodb-force-recovery=2
|
--source include/restart_mysqld.inc
|
|
CREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY, a VARCHAR(8), b INT, c INT AS (b), KEY(a,c)) ENGINE=InnoDB;
|
INSERT INTO t (a) VALUES ('foo');
|
UPDATE t SET a = 'bar';
|
|
--let $restart_parameters=
|
--source include/restart_mysqld.inc
|
--sleep 1
|
|
ALTER TABLE t ADD f INT, FORCE, ALGORITHM=INPLACE;
|
|
# Cleanup
|
DROP TABLE t;
|
The sleep could still be replaced with wait_all_purged.inc.
I am reassigning this to thiru because he worked on MDEV-16678 as well as some earlier fixes in this area.
|