Bug #45035 | Altering table under LOCK TABLES results in "Error 1213 Deadlock found..." | ||
---|---|---|---|
Submitted: | 22 May 2009 12:27 | Modified: | 7 Mar 2010 12:44 |
Reporter: | Dmitry Lenev | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Locking | Severity: | S3 (Non-critical) |
Version: | 6.0.12-bzr, 5.4 | OS: | Any |
Assigned to: | Konstantin Osipov | CPU Architecture: | Any |
[22 May 2009 12:27]
Dmitry Lenev
[22 May 2009 12:59]
MySQL Verification Team
Thank you for the bug report. Verified as described: c:\dbs>c:\dbs\6.0\bin\mysql -uroot --port=3600 --prompt="mysql 6.0 > " Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 6.0.12-alpha-Win X64-log Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql 6.0 > use test Database changed mysql 6.0 > create table t1 (i int); Query OK, 0 rows affected (0.15 sec) mysql 6.0 > lock tables t1 write, t1 as a read, t1 as b read; Query OK, 0 rows affected (0.00 sec) mysql 6.0 > alter table t1 add column j int; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction mysql 6.0 > exit Bye c:\dbs>51c c:\dbs>c:\dbs\5.1\bin\mysql -uroot --port=3510 --prompt="mysql 5.1 >" Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.1.36-Win X64-log Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql 5.1 >use test Database changed mysql 5.1 >create table t1 (i int); Query OK, 0 rows affected (0.16 sec) mysql 5.1 >lock tables t1 write, t1 as a read, t1 as b read; Query OK, 0 rows affected (0.00 sec) mysql 5.1 >alter table t1 add column j int; Query OK, 0 rows affected (0.14 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql 5.1 >
[24 May 2009 10:32]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/74843 2781 Konstantin Osipov 2009-05-24 A fix and a test case for Bug#45035 "Altering table under LOCK TABLES results in "Error 1213 Deadlock found...". If a user had atable locked with LOCK TABLES both for READ and for WRITE in the same connection, ALTER TABLE could fail. Root cause analysis: If a connection issues LOCK TABLE t1 write, t1 a read, t1 b read; the new LOCK TABLES code in 6.0 (part of WL 3726) will create the following list of TABLE_LIST (thd->locked_tables_list->m_locked_tables) objects: t1 b tl_read_no_insert, t1 a tl_read_no_insert, t1 tl_write Later on, when we try to ALTER table t1, mysql_alter_table() closes all TABLE instances and releases its thr_lock locks, keeping only an exclusive metadata lock on t1. But when ALTER is finished, Locked_table_list::reopen_tables() tries to restore the original list of open and locked tables. Before this patch, it used to do so one by one: Open t1 b, get TL_READ_NO_INSERT lock, Open t1 a, get TL_READ_NO_INSERT lock Open t1, try to get TL_WRITE lock, deadlock. The cause of the deadlock is that thr_lock.c doesn't resolve the situation when the read list only consists of locks taken by the same thread, and then this very thread tries to take a WRITE lock. Indeed, since thr_lock_multi always gets a sorted list of locks, WRITE locks always preced READ locks in the list to lock. Don't try to fix thr_lock.c defeciency, keep it simple. Instead, try to take all thr_lock locks at once in ::reopen_tables(). modified: mysql-test/r/lock.result mysql-test/t/lock.test sql/sql_base.cc sql/sql_class.h
[24 May 2009 10:36]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/74844 2781 Konstantin Osipov 2009-05-24 A fix and a test case for Bug#45035 "Altering table under LOCK TABLES results in "Error 1213 Deadlock found...". If a user had a table locked with LOCK TABLES for READ and for WRITE in the same connection, ALTER TABLE could fail. Root cause analysis: If a connection issues LOCK TABLE t1 write, t1 a read, t1 b read; the new LOCK TABLES code in 6.0 (part of WL 3726) will create the following list of TABLE_LIST (thd->locked_tables_list->m_locked_tables) objects: t1 b tl_read_no_insert, t1 a tl_read_no_insert, t1 tl_write Later on, when we try to ALTER table t1, mysql_alter_table() closes all TABLE instances and releases its thr_lock locks, keeping only an exclusive metadata lock on t1. But when ALTER is finished, Locked_table_list::reopen_tables() tries to restore the original list of open and locked tables. Before this patch, it used to do so one by one: Open t1 b, get TL_READ_NO_INSERT lock, Open t1 a, get TL_READ_NO_INSERT lock Open t1, try to get TL_WRITE lock, deadlock. The cause of the deadlock is that thr_lock.c doesn't resolve the situation when the read list only consists of locks taken by the same thread, followed by this very thread trying to take a WRITE lock. Indeed, since thr_lock_multi always gets a sorted list of locks, WRITE locks always precede READ locks in the list to lock. Don't try to fix thr_lock.c deficiency, keep it simple. Instead, try to take all thr_lock locks at once in ::reopen_tables(). modified: mysql-test/r/lock.result mysql-test/t/lock.test sql/sql_base.cc sql/sql_class.h
[8 Jun 2009 6:39]
Dmitry Lenev
Hello! I have mentioned a couple of issues with the patch worth looking into in my review which was sent by e-mail.
[3 Aug 2009 15:15]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/79892 2838 Konstantin Osipov 2009-08-03 A fix and a test case for Bug#45035 "Altering table under LOCK TABLES results in "Error 1213 Deadlock found...". If a user had a table locked with LOCK TABLES for READ and for WRITE in the same connection, ALTER TABLE could fail. Root cause analysis: If a connection issues LOCK TABLE t1 write, t1 a read, t1 b read; the new LOCK TABLES code in 6.0 (part of WL 3726) will create the following list of TABLE_LIST objects (thd->locked_tables_list->m_locked_tables): {"t1" "b" tl_read_no_insert}, {"t1" "a" tl_read_no_insert}, {"t1" "t1" tl_write } Later on, when we try to ALTER table t1, mysql_alter_table() closes all TABLE instances and releases its thr_lock locks, keeping only an exclusive metadata lock on t1. But when ALTER is finished, Locked_table_list::reopen_tables() tries to restore the original list of open and locked tables. Before this patch, it used to do so one by one: Open t1 b, get TL_READ_NO_INSERT lock, Open t1 a, get TL_READ_NO_INSERT lock Open t1, try to get TL_WRITE lock, deadlock. The cause of the deadlock is that thr_lock.c doesn't resolve the situation when the read list only consists of locks taken by the same thread, followed by this very thread trying to take a WRITE lock. Indeed, since thr_lock_multi always gets a sorted list of locks, WRITE locks always precede READ locks in the list to lock. Don't try to fix thr_lock.c deficiency, keep this code simple. Instead, try to take all thr_lock locks at once in ::reopen_tables(). @ mysql-test/r/lock.result Update results: test case for Bug#45035 @ mysql-test/t/lock.test Add a test case for Bug#45035 @ sql/sql_base.cc Take all thr_lock locks at once in Locked_tables_list::reopen_tables(). @ sql/sql_class.h Add a helper array to store tables for mysql_lock_tables() in reopen_tables() @ sql/sql_table.cc Update unlink_all_closed_tables() to the new signature.
[3 Aug 2009 15:26]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/79899 2838 Konstantin Osipov 2009-08-03 A fix and a test case for Bug#45035 "Altering table under LOCK TABLES results in "Error 1213 Deadlock found...". If a user had a table locked with LOCK TABLES for READ and for WRITE in the same connection, ALTER TABLE could fail. Root cause analysis: If a connection issues LOCK TABLE t1 write, t1 a read, t1 b read; the new LOCK TABLES code in 6.0 (part of WL 3726) will create the following list of TABLE_LIST objects (thd->locked_tables_list->m_locked_tables): {"t1" "b" tl_read_no_insert}, {"t1" "a" tl_read_no_insert}, {"t1" "t1" tl_write } Later on, when we try to ALTER table t1, mysql_alter_table() closes all TABLE instances and releases its thr_lock locks, keeping only an exclusive metadata lock on t1. But when ALTER is finished, Locked_table_list::reopen_tables() tries to restore the original list of open and locked tables. Before this patch, it used to do so one by one: Open t1 b, get TL_READ_NO_INSERT lock, Open t1 a, get TL_READ_NO_INSERT lock Open t1, try to get TL_WRITE lock, deadlock. The cause of the deadlock is that thr_lock.c doesn't resolve the situation when the read list only consists of locks taken by the same thread, followed by this very thread trying to take a WRITE lock. Indeed, since thr_lock_multi always gets a sorted list of locks, WRITE locks always precede READ locks in the list to lock. Don't try to fix thr_lock.c deficiency, keep this code simple. Instead, try to take all thr_lock locks at once in ::reopen_tables(). @ mysql-test/r/lock.result Update results: test case for Bug#45035 @ mysql-test/t/lock.test Add a test case for Bug#45035 @ sql/sql_base.cc Take all thr_lock locks at once in Locked_tables_list::reopen_tables(). @ sql/sql_class.h Add a helper array to store tables for mysql_lock_tables() in reopen_tables(). @ sql/sql_table.cc Update unlink_all_closed_tables() to the new signature.
[3 Aug 2009 15:27]
Konstantin Osipov
Pushed into 5.4.4.
[24 Aug 2009 13:53]
Bugs System
Pushed into 5.4.4-alpha (revid:alik@sun.com-20090824135126-2rngffvth14a8bpj) (version source revid:kostja@sun.com-20090803152604-apwh4116zit8boyu) (merge vers: 5.4.4-alpha) (pib:11)
[28 Aug 2009 2:12]
Paul DuBois
Noted in 5.4.4 changelog. If a session had a table locked with LOCK TABLES for both READ and WRITE, ALTER TABLE could fail.
[8 Dec 2009 8:39]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/93120 2999 Konstantin Osipov 2009-12-08 Backport of: ---------------------------------------------------------- revno: 2617.69.2 committer: Konstantin Osipov <kostja@sun.com> branch nick: 5.4-azalea-bugfixing timestamp: Mon 2009-08-03 19:26:04 +0400 message: A fix and a test case for Bug#45035 "Altering table under LOCK TABLES results in "Error 1213 Deadlock found...". If a user had a table locked with LOCK TABLES for READ and for WRITE in the same connection, ALTER TABLE could fail. Root cause analysis: If a connection issues LOCK TABLE t1 write, t1 a read, t1 b read; the new LOCK TABLES code in 6.0 (part of WL 3726) will create the following list of TABLE_LIST objects (thd->locked_tables_list->m_locked_tables): {"t1" "b" tl_read_no_insert}, {"t1" "a" tl_read_no_insert}, {"t1" "t1" tl_write } Later on, when we try to ALTER table t1, mysql_alter_table() closes all TABLE instances and releases its thr_lock locks, keeping only an exclusive metadata lock on t1. But when ALTER is finished, Locked_table_list::reopen_tables() tries to restore the original list of open and locked tables. Before this patch, it used to do so one by one: Open t1 b, get TL_READ_NO_INSERT lock, Open t1 a, get TL_READ_NO_INSERT lock Open t1, try to get TL_WRITE lock, deadlock. The cause of the deadlock is that thr_lock.c doesn't resolve the situation when the read list only consists of locks taken by the same thread, followed by this very thread trying to take a WRITE lock. Indeed, since thr_lock_multi always gets a sorted list of locks, WRITE locks always precede READ locks in the list to lock. Don't try to fix thr_lock.c deficiency, keep this code simple. Instead, try to take all thr_lock locks at once in ::reopen_tables(). @ mysql-test/r/lock.result Update results: test case for Bug#45035. @ mysql-test/t/lock.test Add a test case for Bug#45035. @ sql/sql_base.cc Take all thr_lock locks at once in Locked_tables_list::reopen_tables(). @ sql/sql_class.h Add a helper array to store tables for mysql_lock_tables() in reopen_tables(). @ sql/sql_table.cc Update unlink_all_closed_tables() to the new signature.
[16 Feb 2010 16:48]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100216101445-2ofzkh48aq2e0e8o) (version source revid:kostja@sun.com-20091211154405-c9yhiewr9o5d20rq) (merge vers: 6.0.14-alpha) (pib:16)
[16 Feb 2010 16:57]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100216101208-33qkfwdr0tep3pf2) (version source revid:kostja@sun.com-20091208083845-kzlpva8tonby909l) (pib:16)
[16 Feb 2010 18:34]
Dmitry Lenev
Closing this bug as it is not repeatable in publicly available trees with versions < 6.0.
[6 Mar 2010 11:07]
Bugs System
Pushed into 5.5.3-m3 (revid:alik@sun.com-20100306103849-hha31z2enhh7jwt3) (version source revid:vvaintroub@mysql.com-20100216221947-luyhph0txl2c5tc8) (merge vers: 5.5.99-m3) (pib:16)
[7 Mar 2010 12:44]
Paul DuBois
No changelog entry needed.