mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 06:44:16 +01:00
e219979e7d
``FLUSH TABLES WITH READ LOCK'' Concurrent execution of 1) multitable update with a NATURAL/USING join and 2) a such query as "FLUSH TABLES WITH READ LOCK" or "ALTER TABLE" of updating table led to a server crash. The mysql_multi_update_prepare() function call is optimized to lock updating tables only, so it postpones locking to the last, and if locking fails, it does cleanup of modified syntax structures and repeats a query analysis. However, that cleanup procedure was incomplete for NATURAL/USING join syntax data: 1) some Field_item items pointed into freed table structures, and 2) the TABLE_LIST::join_columns fields was not reset. Major change: short-living Field *Natural_join_column::table_field has been replaced with long-living Item*.
403 lines
8 KiB
Text
403 lines
8 KiB
Text
-- source include/not_embedded.inc
|
|
--disable_warnings
|
|
drop table if exists t1,t2;
|
|
--enable_warnings
|
|
|
|
# Test to see if select will get the lock ahead of low priority update
|
|
|
|
connect (locker,localhost,root,,);
|
|
connect (reader,localhost,root,,);
|
|
connect (writer,localhost,root,,);
|
|
|
|
connection locker;
|
|
create table t1(n int);
|
|
insert into t1 values (1);
|
|
lock tables t1 write;
|
|
connection writer;
|
|
send update low_priority t1 set n = 4;
|
|
connection reader;
|
|
--sleep 2
|
|
send select n from t1;
|
|
connection locker;
|
|
--sleep 2
|
|
unlock tables;
|
|
connection writer;
|
|
reap;
|
|
connection reader;
|
|
reap;
|
|
drop table t1;
|
|
|
|
connection locker;
|
|
create table t1(n int);
|
|
insert into t1 values (1);
|
|
lock tables t1 read;
|
|
connection writer;
|
|
send update low_priority t1 set n = 4;
|
|
connection reader;
|
|
--sleep 2
|
|
send select n from t1;
|
|
connection locker;
|
|
--sleep 2
|
|
unlock tables;
|
|
connection writer;
|
|
reap;
|
|
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
|
|
#
|
|
|
|
connection locker;
|
|
create table t1 (a int);
|
|
create table t2 (a int);
|
|
lock table t1 write, t2 write;
|
|
connection reader;
|
|
send insert t1 select * from t2;
|
|
connection locker;
|
|
drop table t2;
|
|
connection reader;
|
|
--error 1146
|
|
reap;
|
|
connection locker;
|
|
drop table t1;
|
|
|
|
# End of 4.1 tests
|
|
|
|
#
|
|
# BUG#9998 - MySQL client hangs on USE "database"
|
|
#
|
|
create table t1(a int);
|
|
lock tables t1 write;
|
|
connection reader;
|
|
show columns from t1;
|
|
connection locker;
|
|
unlock tables;
|
|
drop table t1;
|
|
|
|
#
|
|
# Bug#19815 - CREATE/RENAME/DROP DATABASE can deadlock on a global read lock
|
|
#
|
|
connect (con1,localhost,root,,);
|
|
connect (con2,localhost,root,,);
|
|
#
|
|
connection con1;
|
|
CREATE DATABASE mysqltest_1;
|
|
FLUSH TABLES WITH READ LOCK;
|
|
#
|
|
# With bug in place: acquire LOCK_mysql_create_table and
|
|
# wait in wait_if_global_read_lock().
|
|
connection con2;
|
|
send DROP DATABASE mysqltest_1;
|
|
--sleep 1
|
|
#
|
|
# With bug in place: try to acquire LOCK_mysql_create_table...
|
|
# When fixed: Reject dropping db because of the read lock.
|
|
connection con1;
|
|
--error ER_CANT_UPDATE_WITH_READLOCK
|
|
DROP DATABASE mysqltest_1;
|
|
UNLOCK TABLES;
|
|
#
|
|
connection con2;
|
|
reap;
|
|
#
|
|
connection default;
|
|
disconnect con1;
|
|
disconnect con2;
|
|
# This must have been dropped by connection 2 already,
|
|
# which waited until the global read lock was released.
|
|
--error ER_DB_DROP_EXISTS
|
|
DROP DATABASE mysqltest_1;
|
|
|
|
#
|
|
# Bug#16986 - Deadlock condition with MyISAM tables
|
|
#
|
|
|
|
# Need a matching user in mysql.user for multi-table select
|
|
--source include/add_anonymous_users.inc
|
|
|
|
connection locker;
|
|
use mysql;
|
|
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
|
|
FLUSH TABLES;
|
|
--sleep 1
|
|
#
|
|
connection reader;
|
|
use mysql;
|
|
#NOTE: This must be a multi-table select, otherwise the deadlock will not occur
|
|
send SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
|
|
--sleep 1
|
|
#
|
|
connection locker;
|
|
# Make test case independent from earlier grants.
|
|
--replace_result "Table is already up to date" "OK"
|
|
OPTIMIZE TABLES columns_priv, db, host, user;
|
|
UNLOCK TABLES;
|
|
#
|
|
connection reader;
|
|
reap;
|
|
use test;
|
|
#
|
|
connection locker;
|
|
use test;
|
|
#
|
|
connection default;
|
|
#
|
|
# Test if CREATE TABLE with LOCK TABLE deadlocks.
|
|
#
|
|
connection writer;
|
|
CREATE TABLE t1 (c1 int);
|
|
LOCK TABLE t1 WRITE;
|
|
#
|
|
# This waits until t1 is unlocked.
|
|
connection locker;
|
|
send FLUSH TABLES WITH READ LOCK;
|
|
--sleep 1
|
|
#
|
|
# This must not block.
|
|
connection writer;
|
|
CREATE TABLE t2 (c1 int);
|
|
UNLOCK TABLES;
|
|
#
|
|
# This awakes now.
|
|
connection locker;
|
|
reap;
|
|
UNLOCK TABLES;
|
|
#
|
|
connection default;
|
|
DROP TABLE t1, t2;
|
|
#
|
|
# Test if CREATE TABLE SELECT with LOCK TABLE deadlocks.
|
|
#
|
|
connection writer;
|
|
CREATE TABLE t1 (c1 int);
|
|
LOCK TABLE t1 WRITE;
|
|
#
|
|
# This waits until t1 is unlocked.
|
|
connection locker;
|
|
send FLUSH TABLES WITH READ LOCK;
|
|
--sleep 1
|
|
#
|
|
# This must not block.
|
|
connection writer;
|
|
--error 1100
|
|
CREATE TABLE t2 AS SELECT * FROM t1;
|
|
UNLOCK TABLES;
|
|
#
|
|
# This awakes now.
|
|
connection locker;
|
|
reap;
|
|
UNLOCK TABLES;
|
|
#
|
|
connection default;
|
|
DROP TABLE t1;
|
|
|
|
--source include/delete_anonymous_users.inc
|
|
|
|
#
|
|
# Bug #17264: MySQL Server freeze
|
|
#
|
|
connection locker;
|
|
# Disable warnings to allow test to run also without InnoDB
|
|
--disable_warnings
|
|
create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
|
|
--enable_warnings
|
|
lock tables t1 write;
|
|
connection writer;
|
|
--sleep 2
|
|
delimiter //;
|
|
send alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
|
|
delimiter ;//
|
|
connection reader;
|
|
--sleep 2
|
|
delimiter //;
|
|
send alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
|
|
delimiter ;//
|
|
connection locker;
|
|
--sleep 2
|
|
unlock tables;
|
|
connection writer;
|
|
reap;
|
|
connection reader;
|
|
reap;
|
|
connection locker;
|
|
drop table t1;
|
|
|
|
#
|
|
# Bug#31479 Bad lock interaction if CREATE TABLE LIKE is killed
|
|
#
|
|
|
|
--disable_warnings
|
|
drop table if exists t1;
|
|
--enable_warnings
|
|
create table t1 (a int);
|
|
--echo connection: locker
|
|
connection locker;
|
|
lock tables t1 read;
|
|
--echo connection: writer
|
|
connection writer;
|
|
let $ID= `select connection_id()`;
|
|
--send create table t2 like t1;
|
|
--echo connection: default
|
|
connection default;
|
|
let $show_type= open tables where in_use=2 and name_locked=1;
|
|
let $show_pattern= '%t1%2%1';
|
|
--source include/wait_show_pattern.inc
|
|
--echo kill query
|
|
disable_query_log;
|
|
eval kill query $ID;
|
|
enable_query_log;
|
|
connection writer;
|
|
--error ER_QUERY_INTERRUPTED
|
|
--reap
|
|
connection locker;
|
|
unlock tables;
|
|
connection default;
|
|
drop table t1;
|
|
|
|
#
|
|
# Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
|
|
# ``FLUSH TABLES WITH READ LOCK''
|
|
#
|
|
|
|
--connection default
|
|
CREATE TABLE t1 (
|
|
a int(11) unsigned default NULL,
|
|
b varchar(255) default NULL,
|
|
UNIQUE KEY a (a),
|
|
KEY b (b)
|
|
);
|
|
|
|
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
|
CREATE TABLE t2 SELECT * FROM t1;
|
|
CREATE TABLE t3 SELECT * FROM t1;
|
|
|
|
--echo # test altering of columns that multiupdate doesn't use
|
|
|
|
--echo # normal mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a)
|
|
SET a = NULL WHERE t1.b <> t2.b;
|
|
|
|
--connection locker
|
|
ALTER TABLE t2 ADD COLUMN (c INT);
|
|
ALTER TABLE t2 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
|
|
--echo # PS mode
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a)
|
|
SET a = NULL WHERE t1.b <> t2.b';
|
|
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
ALTER TABLE t2 ADD COLUMN (c INT);
|
|
ALTER TABLE t2 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
|
|
--echo # test altering of columns that multiupdate uses
|
|
|
|
--echo # normal mode
|
|
|
|
--connection default
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,1060
|
|
ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL;
|
|
UPDATE t2 SET a=b;
|
|
|
|
--connection writer
|
|
--send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b
|
|
|
|
--connection locker
|
|
--error 0,1091
|
|
ALTER TABLE t2 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,1054
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
--echo # PS mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,1060
|
|
ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL;
|
|
UPDATE t2 SET a=b;
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b';
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
--error 0,1091
|
|
ALTER TABLE t2 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,1054
|
|
--reap
|
|
|
|
}
|
|
--enable_query_log
|
|
--connection default
|
|
DROP TABLE t1, t2, t3;
|
|
|
|
# End of 5.0 tests
|