summaryrefslogtreecommitdiff
path: root/sql/lock.cc
diff options
context:
space:
mode:
authordavi@moksha.local <>2007-08-27 10:13:54 -0300
committerdavi@moksha.local <>2007-08-27 10:13:54 -0300
commit91e1cc2195988b4fa5bae66914e12c9dc9da8187 (patch)
tree1313fec2c43e8201aa5432ef88db4b13e2b4757e /sql/lock.cc
parent7a1942d2e1954a3641287cf1514d7dd77aa2351a (diff)
downloadmariadb-git-91e1cc2195988b4fa5bae66914e12c9dc9da8187.tar.gz
Bug#25164 create table `a` as select * from `A` hangs
The problem from a user's perspective: user creates table A, and then tries to CREATE TABLE a SELECT from A - and this causes a deadlock error, a hang, or fails with a debug assert, but only if the storage engine is InnoDB. The origin of the problem: InnoDB uses case-insensitive collation (system_charset_info) when looking up the internal table share, thus returning the same share for 'a' and 'A'. Cause of the user-visible behavior: since the same share is returned to SQL locking subsystem, it assumes that the same table is first locked (within the same session) for WRITE, and then for READ, and returns a deadlock error. However, the code is wrong in not properly cleaning up upon an error, leaving external locks in place, which leads to assertion failures and hangs. Fix that has been implemented: the SQL layer should properly propagate the deadlock error, cleaning up and freeing all resources. Further work towards a more complete solution: InnoDB should not use case insensitive collation for table share hash if table names on disk honor the case.
Diffstat (limited to 'sql/lock.cc')
-rw-r--r--sql/lock.cc2
1 files changed, 2 insertions, 0 deletions
diff --git a/sql/lock.cc b/sql/lock.cc
index 0036d0aef77..cf06be5f95f 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -172,6 +172,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
thd->lock_id)];
if (rc > 1) /* a timeout or a deadlock */
{
+ if (sql_lock->table_count)
+ VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
my_error(rc, MYF(0));
my_free((gptr) sql_lock,MYF(0));
sql_lock= 0;