1--source include/count_sessions.inc 2 3call mtr.add_suppression("Table 't1' is marked as crashed and should be repaired"); 4 5set @save_table_definition_cache=@@table_definition_cache; 6 7--echo # 8--echo # Tests for corrupted MyISAM tables and MyISAMMRG tables with corrupted 9--echo # children.. 10--echo # 11--echo # Run with --myisam-recover=force option. 12--echo # 13--echo # Preparation: we need to make sure that the merge parent 14--echo # is never left in the table cache when closed, since this may 15--echo # have effect on merge children. 16--echo # For that, we set the table cache to minimal size and populate it 17--echo # in a concurrent connection. 18connect(con1,localhost,root,,test,,); 19connection con1; 20--echo # 21--echo # Minimal values. 22--echo # 23 24call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); 25call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table"); 26call mtr.add_suppression(" '\..test.t1'"); 27 28set @save_table_open_cache=@@table_open_cache; 29set global table_open_cache=256; 30set global table_definition_cache=400; 31--disable_warnings 32drop procedure if exists p_create; 33--enable_warnings 34delimiter |; 35create procedure p_create() 36begin 37 declare i int default 1; 38 set @lock_table_stmt="lock table "; 39 set @drop_table_stmt="drop table "; 40 while i < @@global.table_definition_cache + 1 do 41 set @table_name=concat("t_", i); 42 set @opt_comma=if(i=1, "", ", "); 43 set @lock_table_stmt=concat(@lock_table_stmt, @opt_comma, 44 @table_name, " read"); 45 set @drop_table_stmt=concat(@drop_table_stmt, @opt_comma, @table_name); 46 set @create_table_stmt=concat("create table if not exists ", 47 @table_name, " (a int)"); 48 prepare stmt from @create_table_stmt; 49 execute stmt; 50 deallocate prepare stmt; 51 set i= i+1; 52 end while; 53end| 54delimiter ;| 55call p_create(); 56drop procedure p_create; 57--disable_query_log 58let $lock=`select @lock_table_stmt`; 59eval $lock; 60--enable_query_log 61connection default; 62--echo # 63--echo # We have to disable the ps-protocol, to avoid 64--echo # "Prepared statement needs to be re-prepared" errors 65--echo # -- table def versions change all the time with full table cache. 66--echo # 67--disable_ps_protocol 68--disable_warnings 69drop table if exists t1, t1_mrg, t1_copy; 70--enable_warnings 71let $MYSQLD_DATADIR=`select @@datadir`; 72--echo # 73--echo # Prepare a MERGE engine table, that refers to a corrupted 74--echo # child. 75--echo # 76create table t1 (a int, key(a)) engine=myisam; 77create table t1_mrg (a int) union (t1) engine=merge; 78--echo # 79--echo # Create a table with a corrupted index file: 80--echo # save an old index file, insert more rows, 81--echo # overwrite the new index file with the old one. 82--echo # 83insert into t1 (a) values (1), (2), (3); 84flush table t1; 85--copy_file $MYSQLD_DATADIR/test/t1.MYI $MYSQLD_DATADIR/test/t1_copy.MYI 86insert into t1 (a) values (4), (5), (6); 87flush table t1; 88--remove_file $MYSQLD_DATADIR/test/t1.MYI 89--copy_file $MYSQLD_DATADIR/test/t1_copy.MYI $MYSQLD_DATADIR/test/t1.MYI 90--remove_file $MYSQLD_DATADIR/test/t1_copy.MYI 91--echo # check table is needed to mark the table as crashed. 92check table t1; 93--echo # 94--echo # At this point we have a merge table t1_mrg pointing to t1, 95--echo # and t1 is corrupted, and will be auto-repaired at open. 96--echo # Check that this doesn't lead to memory corruption. 97--echo # 98--replace_regex /'.*[\/\\]/'/ 99select * from t1_mrg; 100--echo # 101--echo # Cleanup 102--echo # 103drop table t1, t1_mrg; 104connection con1; 105unlock tables; 106prepare stmt from @drop_table_stmt; 107execute stmt; 108deallocate prepare stmt; 109set @@global.table_open_cache=@save_table_open_cache; 110disconnect con1; 111connection default; 112--enable_ps_protocol 113set @@global.table_definition_cache=@save_table_definition_cache; 114 115--echo # 116--echo # 18075170 - sql node restart required to avoid deadlock after 117--echo # restore 118--echo # 119--echo # Check that auto-repair for MyISAM tables can now happen in the 120--echo # middle of transaction, without aborting it. 121--enable_prepare_warnings 122 123connection default; 124 125create table t1 (a int, key(a)) engine=myisam; 126create table t2 (a int); 127insert into t2 values (1); 128 129--echo # Create a table with a corrupted index file: 130--echo # save an old index file, insert more rows, 131--echo # overwrite the new index file with the old one. 132insert into t1 (a) values (1); 133flush table t1; 134--copy_file $MYSQLD_DATADIR/test/t1.MYI $MYSQLD_DATADIR/test/t1_copy.MYI 135insert into t1 (a) values (4); 136flush table t1; 137--remove_file $MYSQLD_DATADIR/test/t1.MYI 138--copy_file $MYSQLD_DATADIR/test/t1_copy.MYI $MYSQLD_DATADIR/test/t1.MYI 139--remove_file $MYSQLD_DATADIR/test/t1_copy.MYI 140 141--echo # Check table is needed to mark the table as crashed. 142check table t1; 143 144--echo # At this point we have a corrupt t1 145set autocommit = 0; 146select * from t2; 147--echo # Without fix select from t1 will break the transaction. After the fix 148--echo # transaction should be active and should hold lock on table t2. Alter 149--echo # table from con2 will wait only if the transaction is not broken. 150--replace_regex /'.*[\/\\]/'/ 151select * from t1; 152 153connect(con2, localhost, root); 154--SEND ALTER TABLE t2 ADD val INT 155 156connection default; 157--echo # With fix we should have alter table waiting for t2 lock here. 158let $wait_condition= 159 SELECT count(*) = 1 FROM information_schema.processlist WHERE state 160 LIKE "Waiting%" AND info = "ALTER TABLE t2 ADD val INT"; 161 162--source include/wait_condition.inc 163ROLLBACK; 164SET autocommit = 1; 165 166connection con2; 167--REAP 168 169connection default; 170disconnect con2; 171 172--echo # Cleanup 173drop table t1, t2; 174 175# Wait till all disconnects are completed 176-- source include/wait_until_count_sessions.inc 177