From 9b30e2e29c975687ad356a7a9722c3b84993765a Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Wed, 9 Mar 2011 16:06:13 +0100 Subject: [PATCH 1/3] Bug#11815600 [ERROR] INNODB COULD NOT FIND INDEX PRIMARY KEY NO 0 FOR TABLE IN ERROR LOG With the changes made by the patches for Bug#11751388 and Bug#11784056, concurrent reads are allowed while secondary indexes are created in InnoDB. This means that the metadata lock on the affected table is not upgraded to exclusive until the .FRM is updated at the end of ALTER TABLE processing. The problem was that if this lock upgrade failed for some reason (e.g. timeout), the index information in the server and inside InnoDB would be out of sync. This would happen since the add index operation already was committed inside InnoDB but the table metadata inside the server had not been updated yet. This patch fixes the problem by (for now) reverting the effects of the patches for Bug#11751388 and Bug#11784056. Concurrent reads will now again be blocked during creation of secondary indexes in InnoDB. Test case added to innodb_mysql_lock.test. --- mysql-test/r/innodb_mysql_lock.result | 22 +++ mysql-test/r/innodb_mysql_sync.result | 64 +------- mysql-test/t/innodb_mysql_lock.test | 32 ++++ mysql-test/t/innodb_mysql_sync.test | 227 +++++++++++++------------- storage/innobase/handler/ha_innodb.cc | 1 - 5 files changed, 171 insertions(+), 175 deletions(-) diff --git a/mysql-test/r/innodb_mysql_lock.result b/mysql-test/r/innodb_mysql_lock.result index bf1c3a89f40..cd9487721b6 100644 --- a/mysql-test/r/innodb_mysql_lock.result +++ b/mysql-test/r/innodb_mysql_lock.result @@ -148,3 +148,25 @@ COMMIT; # Connection default DROP TABLE t1, t2; DROP VIEW v1; +# +# Bug#11815600 [ERROR] INNODB COULD NOT FIND INDEX PRIMARY +# KEY NO 0 FOR TABLE IN ERROR LOG +# +DROP TABLE IF EXISTS t1; +# Connection default +CREATE TABLE t1 (id INT PRIMARY KEY, value INT) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1, 12345); +START TRANSACTION; +SELECT * FROM t1; +id value +1 12345 +# Connection con1 +SET lock_wait_timeout=1; +ALTER TABLE t1 ADD INDEX idx(value); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Connection default +SELECT * FROM t1; +id value +1 12345 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/r/innodb_mysql_sync.result b/mysql-test/r/innodb_mysql_sync.result index 58948835f66..71f567a4ad2 100644 --- a/mysql-test/r/innodb_mysql_sync.result +++ b/mysql-test/r/innodb_mysql_sync.result @@ -94,64 +94,6 @@ SET DEBUG_SYNC= 'RESET'; # Bug#42230 during add index, cannot do queries on storage engines # that implement add_index # -DROP DATABASE IF EXISTS db1; -DROP TABLE IF EXISTS t1; -# Test 1: Secondary index, should not block reads (original test case). -# Connection default -CREATE DATABASE db1; -CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb; -INSERT INTO db1.t1(value) VALUES (1), (2); -SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; -# Sending: -ALTER TABLE db1.t1 ADD INDEX(value); -# Connection con1 -SET DEBUG_SYNC= "now WAIT_FOR manage"; -USE db1; -SELECT * FROM t1; -id value -1 1 -2 2 -SET DEBUG_SYNC= "now SIGNAL query"; -# Connection default -# Reaping: ALTER TABLE db1.t1 ADD INDEX(value) -DROP DATABASE db1; -# Test 2: Primary index (implicit), should block reads. -CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb; -SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; -# Sending: -ALTER TABLE t1 ADD UNIQUE INDEX(a); -# Connection con1 -SET DEBUG_SYNC= "now WAIT_FOR manage"; -USE test; -# Sending: -SELECT * FROM t1; -# Connection con2 -# Waiting for SELECT to be blocked by the metadata lock on t1 -SET DEBUG_SYNC= "now SIGNAL query"; -# Connection default -# Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a) -# Connection con1 -# Reaping: SELECT * FROM t1 -a b -# Test 3: Primary index (explicit), should block reads. -# Connection default -ALTER TABLE t1 DROP INDEX a; -SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; -# Sending: -ALTER TABLE t1 ADD PRIMARY KEY (a); -# Connection con1 -SET DEBUG_SYNC= "now WAIT_FOR manage"; -# Sending: -SELECT * FROM t1; -# Connection con2 -# Waiting for SELECT to be blocked by the metadata lock on t1 -SET DEBUG_SYNC= "now SIGNAL query"; -# Connection default -# Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a) -# Connection con1 -# Reaping: SELECT * FROM t1 -a b -# Test 4: Secondary unique index, should not block reads. -# Connection default -SET DEBUG_SYNC= "RESET"; -DROP TABLE t1; +# +# DISABLED due to Bug#11815600 +# diff --git a/mysql-test/t/innodb_mysql_lock.test b/mysql-test/t/innodb_mysql_lock.test index 975444a44b1..f1dc0d52484 100644 --- a/mysql-test/t/innodb_mysql_lock.test +++ b/mysql-test/t/innodb_mysql_lock.test @@ -279,6 +279,38 @@ disconnect con2; disconnect con3; +--echo # +--echo # Bug#11815600 [ERROR] INNODB COULD NOT FIND INDEX PRIMARY +--echo # KEY NO 0 FOR TABLE IN ERROR LOG +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--connect (con1,localhost,root) + +--echo # Connection default +connection default; +CREATE TABLE t1 (id INT PRIMARY KEY, value INT) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1, 12345); +START TRANSACTION; +SELECT * FROM t1; + +--echo # Connection con1 +--connection con1 +SET lock_wait_timeout=1; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE t1 ADD INDEX idx(value); + +--echo # Connection default +--connection default +SELECT * FROM t1; +COMMIT; +DROP TABLE t1; +disconnect con1; + + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/innodb_mysql_sync.test b/mysql-test/t/innodb_mysql_sync.test index a8925306c70..13c854d6b61 100644 --- a/mysql-test/t/innodb_mysql_sync.test +++ b/mysql-test/t/innodb_mysql_sync.test @@ -152,132 +152,133 @@ disconnect con1; --echo # that implement add_index --echo # ---disable_warnings -DROP DATABASE IF EXISTS db1; -DROP TABLE IF EXISTS t1; ---enable_warnings +--echo # +--echo # DISABLED due to Bug#11815600 +--echo # -connect(con1,localhost,root); -connect(con2,localhost,root); - ---echo # Test 1: Secondary index, should not block reads (original test case). - ---echo # Connection default -connection default; -CREATE DATABASE db1; -CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb; -INSERT INTO db1.t1(value) VALUES (1), (2); -SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; ---echo # Sending: ---send ALTER TABLE db1.t1 ADD INDEX(value) - ---echo # Connection con1 -connection con1; -SET DEBUG_SYNC= "now WAIT_FOR manage"; -# Neither of these two statements should be blocked -USE db1; -SELECT * FROM t1; -SET DEBUG_SYNC= "now SIGNAL query"; - ---echo # Connection default -connection default; ---echo # Reaping: ALTER TABLE db1.t1 ADD INDEX(value) ---reap -DROP DATABASE db1; - ---echo # Test 2: Primary index (implicit), should block reads. - -CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb; -SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; ---echo # Sending: ---send ALTER TABLE t1 ADD UNIQUE INDEX(a) - ---echo # Connection con1 -connection con1; -SET DEBUG_SYNC= "now WAIT_FOR manage"; -USE test; ---echo # Sending: ---send SELECT * FROM t1 - ---echo # Connection con2 -connection con2; ---echo # Waiting for SELECT to be blocked by the metadata lock on t1 -let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist - WHERE state= 'Waiting for table metadata lock' - AND info='SELECT * FROM t1'; ---source include/wait_condition.inc -SET DEBUG_SYNC= "now SIGNAL query"; - ---echo # Connection default -connection default; ---echo # Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a) ---reap - ---echo # Connection con1 -connection con1; ---echo # Reaping: SELECT * FROM t1 ---reap - ---echo # Test 3: Primary index (explicit), should block reads. - ---echo # Connection default -connection default; -ALTER TABLE t1 DROP INDEX a; -SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; ---echo # Sending: ---send ALTER TABLE t1 ADD PRIMARY KEY (a) - ---echo # Connection con1 -connection con1; -SET DEBUG_SYNC= "now WAIT_FOR manage"; ---echo # Sending: ---send SELECT * FROM t1 - ---echo # Connection con2 -connection con2; ---echo # Waiting for SELECT to be blocked by the metadata lock on t1 -let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist - WHERE state= 'Waiting for table metadata lock' - AND info='SELECT * FROM t1'; ---source include/wait_condition.inc -SET DEBUG_SYNC= "now SIGNAL query"; - ---echo # Connection default -connection default; ---echo # Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a) ---reap - ---echo # Connection con1 -connection con1; ---echo # Reaping: SELECT * FROM t1 ---reap - ---echo # Test 4: Secondary unique index, should not block reads. -# This requires HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE to be supported -# by InnoDB. Adding this flag currently introduces a regression so -# this test is disabled until the regression has been fixed. - ---echo # Connection default -connection default; +#--disable_warnings +#DROP DATABASE IF EXISTS db1; +#DROP TABLE IF EXISTS t1; +#--enable_warnings +# +#connect(con1,localhost,root); +#connect(con2,localhost,root); +# +#--echo # Test 1: Secondary index, should not block reads (original test case). +# +#--echo # Connection default +#connection default; +#CREATE DATABASE db1; +#CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb; +#INSERT INTO db1.t1(value) VALUES (1), (2); +#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; +#--echo # Sending: +#--send ALTER TABLE db1.t1 ADD INDEX(value) +# +#--echo # Connection con1 +#connection con1; +#SET DEBUG_SYNC= "now WAIT_FOR manage"; +# # Neither of these two statements should be blocked +#USE db1; +#SELECT * FROM t1; +#SET DEBUG_SYNC= "now SIGNAL query"; +# +#--echo # Connection default +#connection default; +#--echo # Reaping: ALTER TABLE db1.t1 ADD INDEX(value) +#--reap +#DROP DATABASE db1; +# +#--echo # Test 2: Primary index (implicit), should block reads. +# +#CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb; +#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; +#--echo # Sending: +#--send ALTER TABLE t1 ADD UNIQUE INDEX(a) +# +#--echo # Connection con1 +#connection con1; +#SET DEBUG_SYNC= "now WAIT_FOR manage"; +#USE test; +#--echo # Sending: +#--send SELECT * FROM t1 +# +#--echo # Connection con2 +#connection con2; +#--echo # Waiting for SELECT to be blocked by the metadata lock on t1 +#let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist +# WHERE state= 'Waiting for table metadata lock' +# AND info='SELECT * FROM t1'; +#--source include/wait_condition.inc +#SET DEBUG_SYNC= "now SIGNAL query"; +# +#--echo # Connection default +#connection default; +#--echo # Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a) +#--reap +# +#--echo # Connection con1 +#connection con1; +#--echo # Reaping: SELECT * FROM t1 +#--reap +# +#--echo # Test 3: Primary index (explicit), should block reads. +# +#--echo # Connection default +#connection default; +#ALTER TABLE t1 DROP INDEX a; +#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; +#--echo # Sending: +#--send ALTER TABLE t1 ADD PRIMARY KEY (a) +# +#--echo # Connection con1 +#connection con1; +#SET DEBUG_SYNC= "now WAIT_FOR manage"; +#--echo # Sending: +#--send SELECT * FROM t1 +# +#--echo # Connection con2 +#connection con2; +#--echo # Waiting for SELECT to be blocked by the metadata lock on t1 +#let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist +# WHERE state= 'Waiting for table metadata lock' +# AND info='SELECT * FROM t1'; +#--source include/wait_condition.inc +#SET DEBUG_SYNC= "now SIGNAL query"; +# +#--echo # Connection default +#connection default; +#--echo # Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a) +#--reap +# +#--echo # Connection con1 +#connection con1; +#--echo # Reaping: SELECT * FROM t1 +#--reap +# +#--echo # Test 4: Secondary unique index, should not block reads. +# +#--echo # Connection default +#connection default; #SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query"; #--echo # Sending: #--send ALTER TABLE t1 ADD UNIQUE (b) - +# #--echo # Connection con1 #connection con1; #SET DEBUG_SYNC= "now WAIT_FOR manage"; #SELECT * FROM t1; #SET DEBUG_SYNC= "now SIGNAL query"; - +# #--echo # Connection default #connection default; #--echo # Reaping: ALTER TABLE t1 ADD UNIQUE (b) #--reap - -disconnect con1; -disconnect con2; -SET DEBUG_SYNC= "RESET"; -DROP TABLE t1; +# +#disconnect con1; +#disconnect con2; +#SET DEBUG_SYNC= "RESET"; +#DROP TABLE t1; # Check that all connections opened by test cases in this file are really diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index daeaca90aec..8f128806054 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2594,7 +2594,6 @@ innobase_alter_table_flags( uint flags) { return(HA_INPLACE_ADD_INDEX_NO_READ_WRITE - | HA_INPLACE_ADD_INDEX_NO_WRITE | HA_INPLACE_DROP_INDEX_NO_READ_WRITE | HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE | HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE From a12b2a2e454a3990b2e0c00cf2979aaabf9f1928 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Mar 2011 16:52:03 +0100 Subject: [PATCH 2/3] Per Jon Olav, change needed for Bug#11784056 --- storage/innobase/handler/ha_innodb.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e9909237897..85999cf3e59 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2596,7 +2596,6 @@ innobase_alter_table_flags( return(HA_INPLACE_ADD_INDEX_NO_READ_WRITE | HA_INPLACE_DROP_INDEX_NO_READ_WRITE | HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE - | HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE | HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE | HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE); } From 9fddc97e6d3bac740200da53a02a617d6754fa57 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 31 Mar 2011 16:08:31 +0300 Subject: [PATCH 3/3] Merged the fix for bug #11936829 to 5.5.11 release Bug #11936829: DIFF. BETWEEN MYSQL.USER (AUTHENTICATION_STRING) IN FRESH AND UPGRADED 5.5.11 There was no modification for pre 5.5.11 builds that had authentication_string. Thus the column was not upgraded by mysql_upgrade. Fixed by adding an ALTER TABLE MODIFY to update an existing column to the latest type version. Test suite added. --- mysql-test/r/plugin_auth.result | 47 +++++++++++++++++++++++++++++ mysql-test/t/plugin_auth.test | 22 ++++++++++++++ scripts/mysql_system_tables_fix.sql | 1 + 3 files changed, 70 insertions(+) diff --git a/mysql-test/r/plugin_auth.result b/mysql-test/r/plugin_auth.result index 591a403a0c5..91a5d2d8478 100644 --- a/mysql-test/r/plugin_auth.result +++ b/mysql-test/r/plugin_auth.result @@ -400,4 +400,51 @@ ORDER BY COLUMN_NAME; IS_NULLABLE COLUMN_NAME YES authentication_string YES plugin +# +# Bug #11936829: diff. between mysql.user (authentication_string) +# in fresh and upgraded 5.5.11 +# +SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_SCHEMA= 'mysql' AND TABLE_NAME= 'user' AND +COLUMN_NAME IN ('plugin', 'authentication_string') +ORDER BY COLUMN_NAME; +IS_NULLABLE COLUMN_NAME +YES authentication_string +YES plugin +ALTER TABLE mysql.user MODIFY plugin char(64) DEFAULT '' NOT NULL; +ALTER TABLE mysql.user MODIFY authentication_string TEXT NOT NULL; +Run mysql_upgrade on a 5.5.10 external authentication column layout +mtr.global_suppressions OK +mtr.test_suppressions OK +mysql.columns_priv OK +mysql.db OK +mysql.event OK +mysql.func OK +mysql.general_log OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.host OK +mysql.ndb_binlog_index OK +mysql.plugin OK +mysql.proc OK +mysql.procs_priv OK +mysql.proxies_priv OK +mysql.servers OK +mysql.slow_log OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.user OK +SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_SCHEMA= 'mysql' AND TABLE_NAME= 'user' AND +COLUMN_NAME IN ('plugin', 'authentication_string') +ORDER BY COLUMN_NAME; +IS_NULLABLE COLUMN_NAME +YES authentication_string +YES plugin End of 5.5 tests diff --git a/mysql-test/t/plugin_auth.test b/mysql-test/t/plugin_auth.test index 1e65f503ee3..a81cf4e4783 100644 --- a/mysql-test/t/plugin_auth.test +++ b/mysql-test/t/plugin_auth.test @@ -490,4 +490,26 @@ SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='mysql' ORDER BY COLUMN_NAME; + +--echo # +--echo # Bug #11936829: diff. between mysql.user (authentication_string) +--echo # in fresh and upgraded 5.5.11 +--echo # + +SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA= 'mysql' AND TABLE_NAME= 'user' AND + COLUMN_NAME IN ('plugin', 'authentication_string') + ORDER BY COLUMN_NAME; +ALTER TABLE mysql.user MODIFY plugin char(64) DEFAULT '' NOT NULL; +ALTER TABLE mysql.user MODIFY authentication_string TEXT NOT NULL; + +--echo Run mysql_upgrade on a 5.5.10 external authentication column layout +--exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 + +SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA= 'mysql' AND TABLE_NAME= 'user' AND + COLUMN_NAME IN ('plugin', 'authentication_string') + ORDER BY COLUMN_NAME; + + --echo End of 5.5 tests diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index c57b3be5fae..7e6ffb466a9 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -642,6 +642,7 @@ drop procedure mysql.die; ALTER TABLE user ADD plugin char(64) DEFAULT '', ADD authentication_string TEXT; ALTER TABLE user MODIFY plugin char(64) DEFAULT ''; +ALTER TABLE user MODIFY authentication_string TEXT; -- Need to pre-fill mysql.proxies_priv with access for root even when upgrading from -- older versions