Commit 6472c5c0 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-15890 Strange error message if you try to FLUSH TABLES <view> after LOCK TABLES <view>.

LOCK view WRITE shouldn't block FLUSH view.
So we set the view's mdl_request type to it's tables.
parent 1a893563
...@@ -508,7 +508,6 @@ ERROR HY000: Table 't1' was locked with a READ lock and can't be updated ...@@ -508,7 +508,6 @@ ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
UNLOCK TABLES; UNLOCK TABLES;
LOCK TABLES v1 WRITE; LOCK TABLES v1 WRITE;
FLUSH TABLES v1; FLUSH TABLES v1;
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
UNLOCK TABLES; UNLOCK TABLES;
LOCK TABLES v1 READ; LOCK TABLES v1 READ;
FLUSH TABLES t1; FLUSH TABLES t1;
......
...@@ -136,7 +136,7 @@ select * from t1; ...@@ -136,7 +136,7 @@ select * from t1;
ERROR HY000: Table 't1' was not locked with LOCK TABLES ERROR HY000: Table 't1' was not locked with LOCK TABLES
unlock tables; unlock tables;
create or replace view v_bug5719 as select * from t1; create or replace view v_bug5719 as select * from t1;
lock tables v_bug5719 write; lock tables v_bug5719 read;
select * from v_bug5719; select * from v_bug5719;
a a
...@@ -299,7 +299,7 @@ create table t2 (j int); ...@@ -299,7 +299,7 @@ create table t2 (j int);
# #
# Try to perform DDL on table which is locked through view. # Try to perform DDL on table which is locked through view.
create view v1 as select * from t2; create view v1 as select * from t2;
lock tables t1 write, v1 write; lock tables t1 write, v1 read;
flush table t2; flush table t2;
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
drop table t2; drop table t2;
......
...@@ -276,15 +276,14 @@ DROP VIEW IF EXISTS v1; ...@@ -276,15 +276,14 @@ DROP VIEW IF EXISTS v1;
# #
# Test 1: LOCK TABLES v1 WRITE, t1 READ; # Test 1: LOCK TABLES v1 WRITE, t1 READ;
# #
# Thanks to the fact that we no longer allow DDL on tables
# which are locked for write implicitly, the exact scenario
# in which assert was failing is no longer repeatable.
CREATE TABLE t1 ( f1 integer ); CREATE TABLE t1 ( f1 integer );
CREATE VIEW v1 AS SELECT f1 FROM t1 ; CREATE VIEW v1 AS SELECT f1 FROM t1 ;
# Connection 2
LOCK TABLES v1 WRITE, t1 READ; LOCK TABLES v1 WRITE, t1 READ;
FLUSH TABLE t1; FLUSH TABLE t1;
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated # Connection 1
UNLOCK TABLES; LOCK TABLES t1 WRITE;
FLUSH TABLE t1;
DROP TABLE t1; DROP TABLE t1;
DROP VIEW v1; DROP VIEW v1;
# #
......
...@@ -648,9 +648,6 @@ set debug_sync= 'RESET'; ...@@ -648,9 +648,6 @@ set debug_sync= 'RESET';
set @old_general_log = @@global.general_log; set @old_general_log = @@global.general_log;
set @@global.general_log= OFF; set @@global.general_log= OFF;
create table t1 (i int) engine=InnoDB; create table t1 (i int) engine=InnoDB;
# We have to use view in order to make LOCK TABLES avoid
# acquiring SNRW metadata lock on table.
create view v1 as select * from t1;
insert into t1 values (1); insert into t1 values (1);
# Prepare user lock which will be used for resuming execution of # Prepare user lock which will be used for resuming execution of
# the first statement after it acquires TL_WRITE_ALLOW_WRITE lock. # the first statement after it acquires TL_WRITE_ALLOW_WRITE lock.
...@@ -673,7 +670,7 @@ select count(*) > 0 from t1 as a, t1 as b for update;; ...@@ -673,7 +670,7 @@ select count(*) > 0 from t1 as a, t1 as b for update;;
# acquiring lock for the the first instance of 't1'. # acquiring lock for the the first instance of 't1'.
set debug_sync= 'now WAIT_FOR parked'; set debug_sync= 'now WAIT_FOR parked';
# Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1': # Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1':
lock table v1 write;; lock table t1 write concurrent;;
# Switch to connection 'default'. # Switch to connection 'default'.
# Wait until this LOCK TABLES statement starts waiting for table lock. # Wait until this LOCK TABLES statement starts waiting for table lock.
# Allow SELECT ... FOR UPDATE to resume. # Allow SELECT ... FOR UPDATE to resume.
...@@ -703,7 +700,6 @@ unlock tables; ...@@ -703,7 +700,6 @@ unlock tables;
# Do clean-up. # Do clean-up.
set debug_sync= 'RESET'; set debug_sync= 'RESET';
set @@global.general_log= @old_general_log; set @@global.general_log= @old_general_log;
drop view v1;
drop table t1; drop table t1;
# #
# Bug#50821 Deadlock between LOCK TABLES and ALTER TABLE # Bug#50821 Deadlock between LOCK TABLES and ALTER TABLE
......
...@@ -13,7 +13,7 @@ INSERT INTO t1 VALUES('3','1','1'); ...@@ -13,7 +13,7 @@ INSERT INTO t1 VALUES('3','1','1');
INSERT INTO t1 VALUES('4','1','1'); INSERT INTO t1 VALUES('4','1','1');
INSERT INTO t1 VALUES('5','1','1'); INSERT INTO t1 VALUES('5','1','1');
INSERT INTO t1 VALUES('6','1','1'); INSERT INTO t1 VALUES('6','1','1');
LOCK TABLE v1 WRITE; LOCK TABLE v1 READ;
** Connection con1 ** ** Connection con1 **
INSERT DELAYED INTO t1 VALUES('7','1','1'); INSERT DELAYED INTO t1 VALUES('7','1','1');
INSERT DELAYED INTO t1 VALUES('8','1','1'); INSERT DELAYED INTO t1 VALUES('8','1','1');
...@@ -82,7 +82,7 @@ INSERT INTO t1 VALUES('3'); ...@@ -82,7 +82,7 @@ INSERT INTO t1 VALUES('3');
INSERT INTO t1 VALUES('4'); INSERT INTO t1 VALUES('4');
INSERT INTO t1 VALUES('5'); INSERT INTO t1 VALUES('5');
INSERT INTO t1 VALUES('6'); INSERT INTO t1 VALUES('6');
LOCK TABLE v1 WRITE; LOCK TABLE v1 READ;
** Connection con1 ** ** Connection con1 **
Asynchronous execute Asynchronous execute
INSERT DELAYED INTO t1 VALUES('7'); INSERT DELAYED INTO t1 VALUES('7');
......
...@@ -20,7 +20,7 @@ INSERT INTO t1 VALUES('3'); ...@@ -20,7 +20,7 @@ INSERT INTO t1 VALUES('3');
INSERT INTO t1 VALUES('4'); INSERT INTO t1 VALUES('4');
INSERT INTO t1 VALUES('5'); INSERT INTO t1 VALUES('5');
INSERT INTO t1 VALUES('6'); INSERT INTO t1 VALUES('6');
LOCK TABLE v1 WRITE; LOCK TABLE v1 WRITE CONCURRENT;
** Connection con1 ** ** Connection con1 **
** Asynchronous Execution ** ** Asynchronous Execution **
UPDATE t1 SET a = CONCAT(a,"-updated");| UPDATE t1 SET a = CONCAT(a,"-updated");|
...@@ -56,7 +56,7 @@ INSERT INTO t1 VALUES('3'); ...@@ -56,7 +56,7 @@ INSERT INTO t1 VALUES('3');
INSERT INTO t1 VALUES('4'); INSERT INTO t1 VALUES('4');
INSERT INTO t1 VALUES('5'); INSERT INTO t1 VALUES('5');
INSERT INTO t1 VALUES('6'); INSERT INTO t1 VALUES('6');
LOCK TABLE v1 WRITE; LOCK TABLE v1 READ;
** Connection con1 ** ** Connection con1 **
** Asynchronous Execution ** ** Asynchronous Execution **
UPDATE t1 SET a = CONCAT(a,"-updated");| UPDATE t1 SET a = CONCAT(a,"-updated");|
......
...@@ -61,7 +61,7 @@ INSERT INTO t1 VALUES('4','1','1'); ...@@ -61,7 +61,7 @@ INSERT INTO t1 VALUES('4','1','1');
INSERT INTO t1 VALUES('5','1','1'); INSERT INTO t1 VALUES('5','1','1');
INSERT INTO t1 VALUES('6','1','1'); INSERT INTO t1 VALUES('6','1','1');
LOCK TABLE v1 WRITE; LOCK TABLE v1 READ;
--echo ** Connection con1 ** --echo ** Connection con1 **
connection con1; connection con1;
...@@ -110,9 +110,8 @@ delimiter ;| ...@@ -110,9 +110,8 @@ delimiter ;|
--echo ** Connection con0 ** --echo ** Connection con0 **
connection con0; connection con0;
let $wait_condition= let $wait_condition=
SELECT variable_value > @@global.delayed_insert_limit SELECT COUNT(*) = 1 FROM information_schema.processlist
FROM information_schema.global_status WHERE state = 'Waiting for table level lock' AND user='delayed';
WHERE variable_name like 'Not_flushed_delayed_rows';
--source include/wait_condition.inc --source include/wait_condition.inc
let $my_select= SELECT COUNT(*) FROM t1; let $my_select= SELECT COUNT(*) FROM t1;
send; send;
...@@ -137,13 +136,6 @@ connection con0; ...@@ -137,13 +136,6 @@ connection con0;
--echo Asynchronous "reap" result --echo Asynchronous "reap" result
--echo The next result suffers from --echo The next result suffers from
--echo '# Bug#35386 insert delayed inserts 1 + limit rows instead of just limit rows' --echo '# Bug#35386 insert delayed inserts 1 + limit rows instead of just limit rows'
#
# on UNLOCK TABLES both SELECT in the con0 and delayed insert thread in the
# con1 were awaken. There's no FIFO for TL_WRITE_DELAYED and TL_READ,
# so either the first delayed_insert_limit rows will be inserted
# before select (which will see 21 row) or select will go first (and see 6 rows)
#
--replace_result 6 21
reap; reap;
--echo ** Connection default ** --echo ** Connection default **
...@@ -173,7 +165,7 @@ INSERT INTO t1 VALUES('4'); ...@@ -173,7 +165,7 @@ INSERT INTO t1 VALUES('4');
INSERT INTO t1 VALUES('5'); INSERT INTO t1 VALUES('5');
INSERT INTO t1 VALUES('6'); INSERT INTO t1 VALUES('6');
LOCK TABLE v1 WRITE; LOCK TABLE v1 READ;
--echo ** Connection con1 ** --echo ** Connection con1 **
connection con1; connection con1;
...@@ -204,8 +196,8 @@ delimiter ;| ...@@ -204,8 +196,8 @@ delimiter ;|
--echo ** Connection con0 ** --echo ** Connection con0 **
connection con0; connection con0;
let $wait_condition= let $wait_condition=
SELECT variable_value > 0 FROM information_schema.global_status SELECT COUNT(*) = 1 FROM information_schema.processlist
WHERE variable_name like 'Not_flushed_delayed_rows'; WHERE state = 'Waiting for table level lock' AND user='delayed';
--source include/wait_condition.inc --source include/wait_condition.inc
--echo Asynchronous execute --echo Asynchronous execute
# Due to performance and server behaveiour the test observes values between 6 and 22. # Due to performance and server behaveiour the test observes values between 6 and 22.
......
...@@ -70,7 +70,7 @@ INSERT INTO t1 VALUES('4'); ...@@ -70,7 +70,7 @@ INSERT INTO t1 VALUES('4');
INSERT INTO t1 VALUES('5'); INSERT INTO t1 VALUES('5');
INSERT INTO t1 VALUES('6'); INSERT INTO t1 VALUES('6');
LOCK TABLE v1 WRITE; LOCK TABLE v1 WRITE CONCURRENT;
--echo ** Connection con1 ** --echo ** Connection con1 **
connection con1; connection con1;
...@@ -144,7 +144,7 @@ INSERT INTO t1 VALUES('4'); ...@@ -144,7 +144,7 @@ INSERT INTO t1 VALUES('4');
INSERT INTO t1 VALUES('5'); INSERT INTO t1 VALUES('5');
INSERT INTO t1 VALUES('6'); INSERT INTO t1 VALUES('6');
LOCK TABLE v1 WRITE; LOCK TABLE v1 READ;
--echo ** Connection con1 ** --echo ** Connection con1 **
connection con1; connection con1;
......
...@@ -724,7 +724,6 @@ FLUSH TABLES v1; ...@@ -724,7 +724,6 @@ FLUSH TABLES v1;
UNLOCK TABLES; UNLOCK TABLES;
LOCK TABLES v1 WRITE; LOCK TABLES v1 WRITE;
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
FLUSH TABLES v1; FLUSH TABLES v1;
UNLOCK TABLES; UNLOCK TABLES;
......
...@@ -192,7 +192,7 @@ drop view v_bug5719; ...@@ -192,7 +192,7 @@ drop view v_bug5719;
select * from t1; select * from t1;
unlock tables; unlock tables;
create or replace view v_bug5719 as select * from t1; create or replace view v_bug5719 as select * from t1;
lock tables v_bug5719 write; lock tables v_bug5719 read;
select * from v_bug5719; select * from v_bug5719;
--echo --echo
--echo Allowed to use an underlying table under LOCK TABLES <view> --echo Allowed to use an underlying table under LOCK TABLES <view>
...@@ -370,7 +370,7 @@ create table t2 (j int); ...@@ -370,7 +370,7 @@ create table t2 (j int);
--echo # --echo #
--echo # Try to perform DDL on table which is locked through view. --echo # Try to perform DDL on table which is locked through view.
create view v1 as select * from t2; create view v1 as select * from t2;
lock tables t1 write, v1 write; lock tables t1 write, v1 read;
--error ER_TABLE_NOT_LOCKED_FOR_WRITE --error ER_TABLE_NOT_LOCKED_FOR_WRITE
flush table t2; flush table t2;
--error ER_TABLE_NOT_LOCKED_FOR_WRITE --error ER_TABLE_NOT_LOCKED_FOR_WRITE
......
...@@ -771,17 +771,21 @@ DROP VIEW IF EXISTS v1; ...@@ -771,17 +771,21 @@ DROP VIEW IF EXISTS v1;
--echo # --echo #
--echo # Test 1: LOCK TABLES v1 WRITE, t1 READ; --echo # Test 1: LOCK TABLES v1 WRITE, t1 READ;
--echo # --echo #
--echo # Thanks to the fact that we no longer allow DDL on tables
--echo # which are locked for write implicitly, the exact scenario
--echo # in which assert was failing is no longer repeatable.
CREATE TABLE t1 ( f1 integer ); CREATE TABLE t1 ( f1 integer );
CREATE VIEW v1 AS SELECT f1 FROM t1 ; CREATE VIEW v1 AS SELECT f1 FROM t1 ;
--echo # Connection 2
connect (con2,localhost,root);
LOCK TABLES v1 WRITE, t1 READ; LOCK TABLES v1 WRITE, t1 READ;
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
FLUSH TABLE t1; FLUSH TABLE t1;
UNLOCK TABLES; disconnect con2;
--source include/wait_until_disconnected.inc
--echo # Connection 1
connection default;
LOCK TABLES t1 WRITE;
FLUSH TABLE t1; # Assertion happened here
# Cleanup # Cleanup
DROP TABLE t1; DROP TABLE t1;
......
...@@ -909,9 +909,6 @@ set @old_general_log = @@global.general_log; ...@@ -909,9 +909,6 @@ set @old_general_log = @@global.general_log;
set @@global.general_log= OFF; set @@global.general_log= OFF;
create table t1 (i int) engine=InnoDB; create table t1 (i int) engine=InnoDB;
--echo # We have to use view in order to make LOCK TABLES avoid
--echo # acquiring SNRW metadata lock on table.
create view v1 as select * from t1;
insert into t1 values (1); insert into t1 values (1);
--echo # Prepare user lock which will be used for resuming execution of --echo # Prepare user lock which will be used for resuming execution of
--echo # the first statement after it acquires TL_WRITE_ALLOW_WRITE lock. --echo # the first statement after it acquires TL_WRITE_ALLOW_WRITE lock.
...@@ -942,14 +939,14 @@ connection con_bug45143_3; ...@@ -942,14 +939,14 @@ connection con_bug45143_3;
--echo # acquiring lock for the the first instance of 't1'. --echo # acquiring lock for the the first instance of 't1'.
set debug_sync= 'now WAIT_FOR parked'; set debug_sync= 'now WAIT_FOR parked';
--echo # Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1': --echo # Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1':
--send lock table v1 write; --send lock table t1 write concurrent;
--echo # Switch to connection 'default'. --echo # Switch to connection 'default'.
connection default; connection default;
--echo # Wait until this LOCK TABLES statement starts waiting for table lock. --echo # Wait until this LOCK TABLES statement starts waiting for table lock.
let $wait_condition= select count(*)= 1 from information_schema.processlist let $wait_condition= select count(*)= 1 from information_schema.processlist
where state= 'Waiting for table level lock' and where state= 'Waiting for table level lock' and
info='lock table v1 write'; info='lock table t1 write concurrent';
--source include/wait_condition.inc --source include/wait_condition.inc
--echo # Allow SELECT ... FOR UPDATE to resume. --echo # Allow SELECT ... FOR UPDATE to resume.
--echo # Since it already has TL_WRITE_ALLOW_WRITE lock on the first instance --echo # Since it already has TL_WRITE_ALLOW_WRITE lock on the first instance
...@@ -993,7 +990,6 @@ disconnect con_bug45143_2; ...@@ -993,7 +990,6 @@ disconnect con_bug45143_2;
disconnect con_bug45143_3; disconnect con_bug45143_3;
set debug_sync= 'RESET'; set debug_sync= 'RESET';
set @@global.general_log= @old_general_log; set @@global.general_log= @old_general_log;
drop view v1;
drop table t1; drop table t1;
......
...@@ -1534,8 +1534,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, ...@@ -1534,8 +1534,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local) for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
{ {
tbl->lock_type= table->lock_type; tbl->lock_type= table->lock_type;
tbl->mdl_request.set_type((tbl->lock_type >= TL_WRITE_ALLOW_WRITE) ? tbl->mdl_request.set_type(table->mdl_request.type);
MDL_SHARED_WRITE : MDL_SHARED_READ);
} }
/* /*
If the view is mergeable, we might want to If the view is mergeable, we might want to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment