Commit a49f5cae authored by unknown's avatar unknown
Browse files

Bug#4118: multi-table UPDATE takes WRITE lock on read table

  Ensures that WRITE lock is not obtained on all tables referenced.


mysql-test/r/lock_multi.result:
  Bug#4118
    New test for multi-update locking
mysql-test/r/multi_update.result:
  Bug#4118
    Fix test
mysql-test/t/lock_multi.test:
  Bug#4118
    New test for multi-update locking
mysql-test/t/multi_update.test:
  Bug#4118
    Fix test
sql/sql_parse.cc:
  Bug#4118
    Split multi-update to its own case statement in sql_parse.cc
sql/sql_update.cc:
  Bug#4118
    Overview of locking checking:    
      1. Open and acquire READ lock
      2. Check to see which tables need WRITE lock
      3. Unlock tables and relock
sql/sql_yacc.yy:
  Bug#4118
    Split multi-update to its own case statement in sql_parse.cc
parent 79950521
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -17,6 +17,18 @@ unlock tables;
n
1
drop table t1;
create table t1 (a int, b int);
create table t2 (c int, d int);
insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t2 values(1,2);
lock table t1 read;
 update t1,t2 set c=a where b=d;
select c from t2;
c
2
drop table t1;
drop table t2;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
+0 −1
Original line number Diff line number Diff line
@@ -151,7 +151,6 @@ Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
Table 't2' was locked with a READ lock and can't be updated
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
+24 −0
Original line number Diff line number Diff line
@@ -50,6 +50,30 @@ connection reader;
reap;
drop table t1;

#
# Test problem when using locks with multi-updates
# It should not block when multi-update is reading on a read-locked table
#

connection locker;
create table t1 (a int, b int);
create table t2 (c int, d int);
insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t2 values(1,2);
lock table t1 read;
connection writer;
--sleep 2
send update t1,t2 set c=a where b=d;
connection reader;
--sleep 2
select c from t2;
connection writer;
reap;
connection locker;
drop table t1;
drop table t2;

#
# Test problem when using locks on many tables and droping a table that
# is to-be-locked by another thread
+0 −2
Original line number Diff line number Diff line
@@ -151,8 +151,6 @@ LOCK TABLES t1 write, t2 read;
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
--error 1099
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
# The following should be fixed to not give an error
--error 1099
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
unlock tables;
LOCK TABLES t1 write, t2 write;
+17 −12
Original line number Diff line number Diff line
@@ -1927,8 +1927,6 @@ mysql_execute_command(void)
      send_error(&thd->net,ER_WRONG_VALUE_COUNT);
      DBUG_VOID_RETURN;
    }
    if (select_lex->table_list.elements == 1)
    {
    if (check_one_table_access(thd, UPDATE_ACL, tables, 0))
      goto error; /* purecov: inspected */

@@ -1940,8 +1938,15 @@ mysql_execute_command(void)
		      (ORDER *) select_lex->order_list.first,
		      select_lex->select_limit,
		      lex->duplicates);
    break;
  case SQLCOM_MULTI_UPDATE:
    if (check_db_used(thd,tables))
      goto error;
    if (select_lex->item_list.elements != lex->value_list.elements)
    {
      send_error(&thd->net,ER_WRONG_VALUE_COUNT);
      DBUG_VOID_RETURN;
    }
    else
    {
      const char *msg= 0;
      TABLE_LIST *table;
Loading