mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge with next-4284.
This commit is contained in:
@@ -254,3 +254,38 @@ commit;
|
|||||||
# Switching to connection 'default'.
|
# Switching to connection 'default'.
|
||||||
# Clean-up
|
# Clean-up
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# Bug#48210 FLUSH TABLES WITH READ LOCK deadlocks
|
||||||
|
# against concurrent CREATE PROCEDURE
|
||||||
|
#
|
||||||
|
# Test 1: CREATE PROCEDURE
|
||||||
|
# Connection 1
|
||||||
|
# Start CREATE PROCEDURE and open mysql.proc
|
||||||
|
SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait';
|
||||||
|
CREATE PROCEDURE p1() SELECT 1;
|
||||||
|
# Connection 2
|
||||||
|
SET DEBUG_SYNC= 'now WAIT_FOR table_opened';
|
||||||
|
# Check that FLUSH must wait to get the GRL
|
||||||
|
# and let CREATE PROCEDURE continue
|
||||||
|
SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL grlwait';
|
||||||
|
FLUSH TABLES WITH READ LOCK;
|
||||||
|
# Connection 1
|
||||||
|
# Connection 2
|
||||||
|
UNLOCK TABLES;
|
||||||
|
# Connection 1
|
||||||
|
SET DEBUG_SYNC= 'RESET';
|
||||||
|
# Test 2: DROP PROCEDURE
|
||||||
|
# Start DROP PROCEDURE and open tables
|
||||||
|
SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait';
|
||||||
|
DROP PROCEDURE p1;
|
||||||
|
# Connection 2
|
||||||
|
SET DEBUG_SYNC= 'now WAIT_FOR table_opened';
|
||||||
|
# Check that FLUSH must wait to get the GRL
|
||||||
|
# and let DROP PROCEDURE continue
|
||||||
|
SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL grlwait';
|
||||||
|
FLUSH TABLES WITH READ LOCK;
|
||||||
|
# Connection 1
|
||||||
|
# Connection 2
|
||||||
|
UNLOCK TABLES;
|
||||||
|
# Connection 1
|
||||||
|
SET DEBUG_SYNC= 'RESET';
|
||||||
|
@@ -65,6 +65,15 @@ show indexes from t1;
|
|||||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||||
t1 1 a 1 a A 1 NULL NULL YES BTREE
|
t1 1 a 1 a A 1 NULL NULL YES BTREE
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (a int)
|
||||||
|
partition by hash (a);
|
||||||
|
create index i on t1 (a);
|
||||||
|
insert into t1 values (1);
|
||||||
|
insert into t1 select * from t1;
|
||||||
|
create index i on t1 (a);
|
||||||
|
ERROR 42000: Duplicate key name 'i'
|
||||||
|
create index i2 on t1 (a);
|
||||||
|
drop table t1;
|
||||||
CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a))
|
CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a))
|
||||||
ENGINE=MyISAM
|
ENGINE=MyISAM
|
||||||
PARTITION BY HASH (a);
|
PARTITION BY HASH (a);
|
||||||
|
@@ -1,2 +1,57 @@
|
|||||||
# Disabled until Bug#46654 False deadlock on concurrent DML/DDL
|
#
|
||||||
# with partitions, inconsistent behavior is backported
|
# Bug #43867 ALTER TABLE on a partitioned table
|
||||||
|
# causes unnecessary deadlocks
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a int) PARTITION BY RANGE (a)
|
||||||
|
(PARTITION p0 VALUES LESS THAN (1),
|
||||||
|
PARTITION p1 VALUES LESS THAN (2));
|
||||||
|
INSERT INTO t1 VALUES (0),(1);
|
||||||
|
# Connection 2
|
||||||
|
BEGIN;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# Connection 1
|
||||||
|
ALTER TABLE t1 DROP PARTITION p3;
|
||||||
|
ERROR HY000: Error in list of partitions to DROP
|
||||||
|
# Connection 2
|
||||||
|
# This failed with deadlock and should not do so.
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# Connection 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Bug #46654 False deadlock on concurrent DML/DDL
|
||||||
|
# with partitions, inconsistent behavior
|
||||||
|
#
|
||||||
|
DROP TABLE IF EXISTS tbl_with_partitions;
|
||||||
|
CREATE TABLE tbl_with_partitions ( i INT )
|
||||||
|
PARTITION BY HASH(i);
|
||||||
|
INSERT INTO tbl_with_partitions VALUES (1);
|
||||||
|
# Connection 3
|
||||||
|
LOCK TABLE tbl_with_partitions READ;
|
||||||
|
# Connection 1
|
||||||
|
# Access table with disabled autocommit
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
SELECT * FROM tbl_with_partitions;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
# Connection 2
|
||||||
|
# Alter table, abort after prepare
|
||||||
|
set session debug="+d,abort_copy_table";
|
||||||
|
ALTER TABLE tbl_with_partitions ADD COLUMN f INT;
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
# Connection 1
|
||||||
|
# Try accessing the table after Alter aborted.
|
||||||
|
# This used to give ER_LOCK_DEADLOCK.
|
||||||
|
SELECT * FROM tbl_with_partitions;
|
||||||
|
i
|
||||||
|
1
|
||||||
|
# Connection 3
|
||||||
|
UNLOCK TABLES;
|
||||||
|
# Connection 1
|
||||||
|
# Cleanup
|
||||||
|
DROP TABLE tbl_with_partitions;
|
||||||
|
@@ -1687,6 +1687,17 @@ NULL
|
|||||||
SELECT non_existent (a) FROM t1 WHERE b = 999999;
|
SELECT non_existent (a) FROM t1 WHERE b = 999999;
|
||||||
ERROR 42000: FUNCTION test.non_existent does not exist
|
ERROR 42000: FUNCTION test.non_existent does not exist
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 ( f2 INTEGER, f3 INTEGER );
|
||||||
|
INSERT INTO t1 VALUES ( 1, 1 );
|
||||||
|
CREATE FUNCTION func_1 () RETURNS INTEGER
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO t1 SELECT * FROM t1 ;
|
||||||
|
RETURN 1 ;
|
||||||
|
END|
|
||||||
|
INSERT INTO t1 SELECT * FROM (SELECT 2 AS f1, 2 AS f2) AS A WHERE func_1() = 5;
|
||||||
|
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
|
||||||
|
DROP FUNCTION func_1;
|
||||||
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
|
# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
|
||||||
# SP + MERGE + ALTER
|
# SP + MERGE + ALTER
|
||||||
|
@@ -475,6 +475,73 @@ disconnect con46673;
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#48210 FLUSH TABLES WITH READ LOCK deadlocks
|
||||||
|
--echo # against concurrent CREATE PROCEDURE
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
connect (con2, localhost, root);
|
||||||
|
|
||||||
|
--echo # Test 1: CREATE PROCEDURE
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
connection default;
|
||||||
|
--echo # Start CREATE PROCEDURE and open mysql.proc
|
||||||
|
SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait';
|
||||||
|
--send CREATE PROCEDURE p1() SELECT 1
|
||||||
|
|
||||||
|
--echo # Connection 2
|
||||||
|
connection con2;
|
||||||
|
SET DEBUG_SYNC= 'now WAIT_FOR table_opened';
|
||||||
|
--echo # Check that FLUSH must wait to get the GRL
|
||||||
|
--echo # and let CREATE PROCEDURE continue
|
||||||
|
SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL grlwait';
|
||||||
|
--send FLUSH TABLES WITH READ LOCK
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
|
||||||
|
--echo # Connection 2
|
||||||
|
connection con2;
|
||||||
|
--reap
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC= 'RESET';
|
||||||
|
|
||||||
|
--echo # Test 2: DROP PROCEDURE
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
--echo # Start DROP PROCEDURE and open tables
|
||||||
|
SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait';
|
||||||
|
--send DROP PROCEDURE p1
|
||||||
|
|
||||||
|
--echo # Connection 2
|
||||||
|
connection con2;
|
||||||
|
SET DEBUG_SYNC= 'now WAIT_FOR table_opened';
|
||||||
|
--echo # Check that FLUSH must wait to get the GRL
|
||||||
|
--echo # and let DROP PROCEDURE continue
|
||||||
|
SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL grlwait';
|
||||||
|
--send FLUSH TABLES WITH READ LOCK
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
|
||||||
|
--echo # Connection 2
|
||||||
|
connection con2;
|
||||||
|
--reap
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC= 'RESET';
|
||||||
|
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
|
||||||
# Check that all connections opened by test cases in this file are really
|
# Check that all connections opened by test cases in this file are really
|
||||||
# gone so execution of other tests won't be affected by their presence.
|
# gone so execution of other tests won't be affected by their presence.
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
@@ -74,6 +74,19 @@ analyze table t1;
|
|||||||
show indexes from t1;
|
show indexes from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#40181: hang if create index
|
||||||
|
#
|
||||||
|
create table t1 (a int)
|
||||||
|
partition by hash (a);
|
||||||
|
create index i on t1 (a);
|
||||||
|
insert into t1 values (1);
|
||||||
|
insert into t1 select * from t1;
|
||||||
|
--error ER_DUP_KEYNAME
|
||||||
|
create index i on t1 (a);
|
||||||
|
create index i2 on t1 (a);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug#36001: Partitions: spelling and using some error messages
|
# Bug#36001: Partitions: spelling and using some error messages
|
||||||
#
|
#
|
||||||
|
@@ -1,42 +1,91 @@
|
|||||||
--source include/have_partition.inc
|
--source include/have_partition.inc
|
||||||
|
--source include/have_debug.inc
|
||||||
# Save the initial number of concurrent sessions.
|
# Save the initial number of concurrent sessions.
|
||||||
--source include/count_sessions.inc
|
--source include/count_sessions.inc
|
||||||
|
|
||||||
--echo # Disabled until Bug#46654 False deadlock on concurrent DML/DDL
|
--echo #
|
||||||
--echo # with partitions, inconsistent behavior is backported
|
--echo # Bug #43867 ALTER TABLE on a partitioned table
|
||||||
|
--echo # causes unnecessary deadlocks
|
||||||
|
--echo #
|
||||||
|
|
||||||
#--echo #
|
CREATE TABLE t1 (a int) PARTITION BY RANGE (a)
|
||||||
#--echo # Bug #43867 ALTER TABLE on a partitioned table
|
(PARTITION p0 VALUES LESS THAN (1),
|
||||||
#--echo # causes unnecessary deadlocks
|
PARTITION p1 VALUES LESS THAN (2));
|
||||||
#--echo #
|
|
||||||
#
|
INSERT INTO t1 VALUES (0),(1);
|
||||||
#CREATE TABLE t1 (a int) PARTITION BY RANGE (a)
|
|
||||||
#(PARTITION p0 VALUES LESS THAN (1),
|
connect(con1,localhost,root);
|
||||||
# PARTITION p1 VALUES LESS THAN (2));
|
|
||||||
#
|
--echo # Connection 2
|
||||||
#INSERT INTO t1 VALUES (0),(1);
|
connection con1;
|
||||||
#
|
BEGIN;
|
||||||
#connect(con1,localhost,root);
|
SELECT * FROM t1;
|
||||||
#
|
|
||||||
#--echo # Connection 2
|
--echo # Connection 1
|
||||||
#connection con1;
|
connection default;
|
||||||
#BEGIN;
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
#SELECT * FROM t1;
|
ALTER TABLE t1 DROP PARTITION p3;
|
||||||
#
|
|
||||||
#--echo # Connection 1
|
--echo # Connection 2
|
||||||
#connection default;
|
connection con1;
|
||||||
#--error ER_DROP_PARTITION_NON_EXISTENT
|
--echo # This failed with deadlock and should not do so.
|
||||||
#ALTER TABLE t1 DROP PARTITION p3;
|
SELECT * FROM t1;
|
||||||
#
|
|
||||||
#--echo # Connection 2
|
--echo # Connection 1
|
||||||
#connection con1;
|
connection default;
|
||||||
#--echo # This failed with deadlock and should not do so.
|
disconnect con1;
|
||||||
#SELECT * FROM t1;
|
DROP TABLE t1;
|
||||||
#
|
|
||||||
#--echo # Connection 1
|
|
||||||
#connection default;
|
--echo #
|
||||||
#disconnect con1;
|
--echo # Bug #46654 False deadlock on concurrent DML/DDL
|
||||||
#DROP TABLE t1;
|
--echo # with partitions, inconsistent behavior
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS tbl_with_partitions;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE tbl_with_partitions ( i INT )
|
||||||
|
PARTITION BY HASH(i);
|
||||||
|
INSERT INTO tbl_with_partitions VALUES (1);
|
||||||
|
|
||||||
|
connect(con2,localhost,root);
|
||||||
|
connect(con3,localhost,root);
|
||||||
|
|
||||||
|
--echo # Connection 3
|
||||||
|
connection con3;
|
||||||
|
LOCK TABLE tbl_with_partitions READ;
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
--echo # Access table with disabled autocommit
|
||||||
|
connection default;
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
SELECT * FROM tbl_with_partitions;
|
||||||
|
|
||||||
|
--echo # Connection 2
|
||||||
|
--echo # Alter table, abort after prepare
|
||||||
|
connection con2;
|
||||||
|
set session debug="+d,abort_copy_table";
|
||||||
|
--error ER_LOCK_WAIT_TIMEOUT
|
||||||
|
ALTER TABLE tbl_with_partitions ADD COLUMN f INT;
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
--echo # Try accessing the table after Alter aborted.
|
||||||
|
--echo # This used to give ER_LOCK_DEADLOCK.
|
||||||
|
connection default;
|
||||||
|
SELECT * FROM tbl_with_partitions;
|
||||||
|
|
||||||
|
--echo # Connection 3
|
||||||
|
connection con3;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--echo # Connection 1
|
||||||
|
--echo # Cleanup
|
||||||
|
connection default;
|
||||||
|
disconnect con2;
|
||||||
|
disconnect con3;
|
||||||
|
DROP TABLE tbl_with_partitions;
|
||||||
|
|
||||||
|
|
||||||
# Check that all connections opened by test cases in this file are really
|
# Check that all connections opened by test cases in this file are really
|
||||||
|
@@ -2490,6 +2490,35 @@ SELECT AVG (a) FROM t1 WHERE b = 999999;
|
|||||||
SELECT non_existent (a) FROM t1 WHERE b = 999999;
|
SELECT non_existent (a) FROM t1 WHERE b = 999999;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #46374 crash, INSERT INTO t1 uses function, function modifies t1
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 ( f2 INTEGER, f3 INTEGER );
|
||||||
|
INSERT INTO t1 VALUES ( 1, 1 );
|
||||||
|
|
||||||
|
delimiter |;
|
||||||
|
|
||||||
|
CREATE FUNCTION func_1 () RETURNS INTEGER
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO t1 SELECT * FROM t1 ;
|
||||||
|
RETURN 1 ;
|
||||||
|
END|
|
||||||
|
|
||||||
|
delimiter ;|
|
||||||
|
|
||||||
|
# The bug caused the following INSERT statement to trigger
|
||||||
|
# an assertion. Error 1442 is the correct response
|
||||||
|
#
|
||||||
|
--error 1442
|
||||||
|
INSERT INTO t1 SELECT * FROM (SELECT 2 AS f1, 2 AS f2) AS A WHERE func_1() = 5;
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
DROP FUNCTION func_1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
|
--echo # Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
|
||||||
--echo # SP + MERGE + ALTER
|
--echo # SP + MERGE + ALTER
|
||||||
@@ -2513,3 +2542,4 @@ DROP VIEW v1;
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
|
||||||
|
27
sql/lock.cc
27
sql/lock.cc
@@ -74,6 +74,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
|
#include "debug_sync.h"
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -1125,9 +1126,33 @@ bool lock_global_read_lock(THD *thd)
|
|||||||
if (!thd->global_read_lock)
|
if (!thd->global_read_lock)
|
||||||
{
|
{
|
||||||
const char *old_message;
|
const char *old_message;
|
||||||
|
const char *new_message= "Waiting to get readlock";
|
||||||
(void) pthread_mutex_lock(&LOCK_global_read_lock);
|
(void) pthread_mutex_lock(&LOCK_global_read_lock);
|
||||||
|
|
||||||
|
#if defined(ENABLED_DEBUG_SYNC)
|
||||||
|
/*
|
||||||
|
The below sync point fires if we have to wait for
|
||||||
|
protect_against_global_read_lock.
|
||||||
|
|
||||||
|
WARNING: Beware to use WAIT_FOR with this sync point. We hold
|
||||||
|
LOCK_global_read_lock here.
|
||||||
|
|
||||||
|
Call the sync point before calling enter_cond() as it does use
|
||||||
|
enter_cond() and exit_cond() itself if a WAIT_FOR action is
|
||||||
|
executed in spite of the above warning.
|
||||||
|
|
||||||
|
Pre-set proc_info so that it is available immediately after the
|
||||||
|
sync point sends a SIGNAL. This makes tests more reliable.
|
||||||
|
*/
|
||||||
|
if (protect_against_global_read_lock)
|
||||||
|
{
|
||||||
|
thd_proc_info(thd, new_message);
|
||||||
|
DEBUG_SYNC(thd, "wait_lock_global_read_lock");
|
||||||
|
}
|
||||||
|
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
||||||
|
|
||||||
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
|
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
|
||||||
"Waiting to get readlock");
|
new_message);
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
("waiting_for: %d protect_against: %d",
|
("waiting_for: %d protect_against: %d",
|
||||||
waiting_for_read_lock, protect_against_global_read_lock));
|
waiting_for_read_lock, protect_against_global_read_lock));
|
||||||
|
@@ -1534,8 +1534,8 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
|
|||||||
*table_ptr=table->next;
|
*table_ptr=table->next;
|
||||||
|
|
||||||
table->mdl_ticket= NULL;
|
table->mdl_ticket= NULL;
|
||||||
if (table->needs_reopen() ||
|
if (table->s->needs_reopen() ||
|
||||||
thd->version != refresh_version || !table->db_stat ||
|
thd->version != refresh_version || table->needs_reopen() ||
|
||||||
table_def_shutdown_in_progress)
|
table_def_shutdown_in_progress)
|
||||||
{
|
{
|
||||||
free_cache_entry(table);
|
free_cache_entry(table);
|
||||||
@@ -2844,7 +2844,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
|||||||
table exists now we should downgrade our exclusive metadata
|
table exists now we should downgrade our exclusive metadata
|
||||||
lock on this table to shared metadata lock.
|
lock on this table to shared metadata lock.
|
||||||
*/
|
*/
|
||||||
if (table_list->lock_strategy == TABLE_LIST::EXCLUSIVE_DOWNGRADABLE_MDL)
|
if (table_list->lock_strategy == TABLE_LIST::EXCLUSIVE_DOWNGRADABLE_MDL &&
|
||||||
|
!(flags & MYSQL_OPEN_HAS_MDL_LOCK))
|
||||||
mdl_ticket->downgrade_exclusive_lock();
|
mdl_ticket->downgrade_exclusive_lock();
|
||||||
|
|
||||||
table->mdl_ticket= mdl_ticket;
|
table->mdl_ticket= mdl_ticket;
|
||||||
@@ -8190,13 +8191,13 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use)
|
|||||||
thd_table= thd_table->next)
|
thd_table= thd_table->next)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Check for TABLE::db_stat is needed since in some places we call
|
Check for TABLE::needs_reopen() is needed since in some places we call
|
||||||
handler::close() for table instance (and set TABLE::db_stat to 0)
|
handler::close() for table instance (and set TABLE::db_stat to 0)
|
||||||
and do not remove such instances from the THD::open_tables
|
and do not remove such instances from the THD::open_tables
|
||||||
for some time, during which other thread can see those instances
|
for some time, during which other thread can see those instances
|
||||||
(e.g. see partitioning code).
|
(e.g. see partitioning code).
|
||||||
*/
|
*/
|
||||||
if (thd_table->db_stat)
|
if (!thd_table->needs_reopen())
|
||||||
signalled|= mysql_lock_abort_for_thread(thd, thd_table);
|
signalled|= mysql_lock_abort_for_thread(thd, thd_table);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
|
@@ -3341,6 +3341,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
#define CF_DIAGNOSTIC_STMT (1U << 8)
|
#define CF_DIAGNOSTIC_STMT (1U << 8)
|
||||||
|
|
||||||
|
/**
|
||||||
|
SQL statements that must be protected against impending global read lock
|
||||||
|
to prevent deadlock. This deadlock could otherwise happen if the statement
|
||||||
|
starts waiting for the GRL to go away inside mysql_lock_tables while at the
|
||||||
|
same time having "old" opened tables. The thread holding the GRL can be
|
||||||
|
waiting for these "old" opened tables to be closed, causing a deadlock
|
||||||
|
(FLUSH TABLES WITH READ LOCK).
|
||||||
|
*/
|
||||||
|
#define CF_PROTECT_AGAINST_GRL (1U << 10)
|
||||||
|
|
||||||
/* Bits in server_command_flags */
|
/* Bits in server_command_flags */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -820,7 +820,7 @@ void mysql_ha_flush(THD *thd)
|
|||||||
if (hash_tables->table &&
|
if (hash_tables->table &&
|
||||||
(hash_tables->table->mdl_ticket &&
|
(hash_tables->table->mdl_ticket &&
|
||||||
hash_tables->table->mdl_ticket->has_pending_conflicting_lock() ||
|
hash_tables->table->mdl_ticket->has_pending_conflicting_lock() ||
|
||||||
hash_tables->table->needs_reopen()))
|
hash_tables->table->s->needs_reopen()))
|
||||||
mysql_ha_close_table(thd, hash_tables);
|
mysql_ha_close_table(thd, hash_tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2657,7 +2657,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
|
|
||||||
thd_proc_info(&thd, "insert");
|
thd_proc_info(&thd, "insert");
|
||||||
max_rows= delayed_insert_limit;
|
max_rows= delayed_insert_limit;
|
||||||
if (thd.killed || table->needs_reopen())
|
if (thd.killed || table->s->needs_reopen())
|
||||||
{
|
{
|
||||||
thd.killed= THD::KILL_CONNECTION;
|
thd.killed= THD::KILL_CONNECTION;
|
||||||
max_rows= ULONG_MAX; // Do as much as possible
|
max_rows= ULONG_MAX; // Do as much as possible
|
||||||
|
@@ -182,14 +182,15 @@ void init_update_queries(void)
|
|||||||
memset(sql_command_flags, 0, sizeof(sql_command_flags));
|
memset(sql_command_flags, 0, sizeof(sql_command_flags));
|
||||||
|
|
||||||
sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||||
CF_AUTO_COMMIT_TRANS;
|
CF_AUTO_COMMIT_TRANS | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
|
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
|
||||||
CF_AUTO_COMMIT_TRANS;
|
CF_AUTO_COMMIT_TRANS | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
|
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
|
||||||
CF_AUTO_COMMIT_TRANS;
|
CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
|
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||||
|
CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||||
sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||||
@@ -207,17 +208,17 @@ void init_update_queries(void)
|
|||||||
sql_command_flags[SQLCOM_DROP_TRIGGER]= CF_AUTO_COMMIT_TRANS;
|
sql_command_flags[SQLCOM_DROP_TRIGGER]= CF_AUTO_COMMIT_TRANS;
|
||||||
|
|
||||||
sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
CF_REEXECUTION_FRAGILE;
|
CF_REEXECUTION_FRAGILE;
|
||||||
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
|
||||||
@@ -276,20 +277,21 @@ void init_update_queries(void)
|
|||||||
CF_REEXECUTION_FRAGILE);
|
CF_REEXECUTION_FRAGILE);
|
||||||
|
|
||||||
|
|
||||||
sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA;
|
||||||
sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA;
|
||||||
|
sql_command_flags[SQLCOM_REVOKE_ALL]= CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_ALTER_DB]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_ALTER_DB]= CF_CHANGES_DATA;
|
||||||
sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA;
|
||||||
sql_command_flags[SQLCOM_DROP_FUNCTION]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_DROP_FUNCTION]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA;
|
||||||
sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_DROP_PROCEDURE]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_DROP_PROCEDURE]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_ALTER_PROCEDURE]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_ALTER_PROCEDURE]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_ALTER_FUNCTION]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_ALTER_FUNCTION]= CF_CHANGES_DATA | CF_PROTECT_AGAINST_GRL;
|
||||||
sql_command_flags[SQLCOM_INSTALL_PLUGIN]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_INSTALL_PLUGIN]= CF_CHANGES_DATA;
|
||||||
sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]= CF_CHANGES_DATA;
|
sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]= CF_CHANGES_DATA;
|
||||||
|
|
||||||
@@ -1969,6 +1971,17 @@ mysql_execute_command(THD *thd)
|
|||||||
thd->mdl_context.release_all_locks();
|
thd->mdl_context.release_all_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if this command needs protection against the global read lock
|
||||||
|
to avoid deadlock. See CF_PROTECT_AGAINST_GRL.
|
||||||
|
start_waiting_global_read_lock() is called at the end of
|
||||||
|
mysql_execute_command().
|
||||||
|
*/
|
||||||
|
if (((sql_command_flags[lex->sql_command] & CF_PROTECT_AGAINST_GRL) != 0) &&
|
||||||
|
!thd->locked_tables_mode)
|
||||||
|
if (wait_if_global_read_lock(thd, FALSE, TRUE))
|
||||||
|
goto error;
|
||||||
|
|
||||||
switch (lex->sql_command) {
|
switch (lex->sql_command) {
|
||||||
|
|
||||||
case SQLCOM_SHOW_EVENTS:
|
case SQLCOM_SHOW_EVENTS:
|
||||||
@@ -2309,12 +2322,9 @@ case SQLCOM_PREPARE:
|
|||||||
start_waiting_global_read_lock(). We protect the normal CREATE
|
start_waiting_global_read_lock(). We protect the normal CREATE
|
||||||
TABLE in the same way. That way we avoid that a new table is
|
TABLE in the same way. That way we avoid that a new table is
|
||||||
created during a global read lock.
|
created during a global read lock.
|
||||||
|
Protection against grl is covered by the CF_PROTECT_AGAINST_GRL flag.
|
||||||
*/
|
*/
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
goto end_with_restore_list;
|
|
||||||
}
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
{
|
{
|
||||||
partition_info *part_info= thd->lex->part_info;
|
partition_info *part_info= thd->lex->part_info;
|
||||||
@@ -2617,12 +2627,6 @@ end_with_restore_list:
|
|||||||
"INDEX DIRECTORY");
|
"INDEX DIRECTORY");
|
||||||
create_info.data_file_name= create_info.index_file_name= NULL;
|
create_info.data_file_name= create_info.index_file_name= NULL;
|
||||||
|
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= mysql_alter_table(thd, select_lex->db, lex->name.str,
|
res= mysql_alter_table(thd, select_lex->db, lex->name.str,
|
||||||
&create_info,
|
&create_info,
|
||||||
@@ -2852,8 +2856,6 @@ end_with_restore_list:
|
|||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if (update_precheck(thd, all_tables))
|
if (update_precheck(thd, all_tables))
|
||||||
break;
|
break;
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
goto error;
|
|
||||||
DBUG_ASSERT(select_lex->offset_limit == 0);
|
DBUG_ASSERT(select_lex->offset_limit == 0);
|
||||||
unit->set_limit(select_lex);
|
unit->set_limit(select_lex);
|
||||||
MYSQL_UPDATE_START(thd->query());
|
MYSQL_UPDATE_START(thd->query());
|
||||||
@@ -2884,15 +2886,6 @@ end_with_restore_list:
|
|||||||
else
|
else
|
||||||
res= 0;
|
res= 0;
|
||||||
|
|
||||||
/*
|
|
||||||
Protection might have already been risen if its a fall through
|
|
||||||
from the SQLCOM_UPDATE case above.
|
|
||||||
*/
|
|
||||||
if (!thd->locked_tables_mode &&
|
|
||||||
lex->sql_command == SQLCOM_UPDATE_MULTI &&
|
|
||||||
wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
res= mysql_multi_update_prepare(thd);
|
res= mysql_multi_update_prepare(thd);
|
||||||
|
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
@@ -2992,11 +2985,6 @@ end_with_restore_list:
|
|||||||
if ((res= insert_precheck(thd, all_tables)))
|
if ((res= insert_precheck(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MYSQL_INSERT_START(thd->query());
|
MYSQL_INSERT_START(thd->query());
|
||||||
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
||||||
lex->update_list, lex->value_list,
|
lex->update_list, lex->value_list,
|
||||||
@@ -3031,11 +3019,6 @@ end_with_restore_list:
|
|||||||
|
|
||||||
unit->set_limit(select_lex);
|
unit->set_limit(select_lex);
|
||||||
|
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!(res= open_and_lock_tables(thd, all_tables)))
|
if (!(res= open_and_lock_tables(thd, all_tables)))
|
||||||
{
|
{
|
||||||
MYSQL_INSERT_SELECT_START(thd->query());
|
MYSQL_INSERT_SELECT_START(thd->query());
|
||||||
@@ -3113,11 +3096,6 @@ end_with_restore_list:
|
|||||||
DBUG_ASSERT(select_lex->offset_limit == 0);
|
DBUG_ASSERT(select_lex->offset_limit == 0);
|
||||||
unit->set_limit(select_lex);
|
unit->set_limit(select_lex);
|
||||||
|
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MYSQL_DELETE_START(thd->query());
|
MYSQL_DELETE_START(thd->query());
|
||||||
res = mysql_delete(thd, all_tables, select_lex->where,
|
res = mysql_delete(thd, all_tables, select_lex->where,
|
||||||
&select_lex->order_list,
|
&select_lex->order_list,
|
||||||
@@ -3133,12 +3111,6 @@ end_with_restore_list:
|
|||||||
(TABLE_LIST *)thd->lex->auxiliary_table_list.first;
|
(TABLE_LIST *)thd->lex->auxiliary_table_list.first;
|
||||||
multi_delete *del_result;
|
multi_delete *del_result;
|
||||||
|
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res= multi_delete_precheck(thd, all_tables)))
|
if ((res= multi_delete_precheck(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3277,9 +3249,6 @@ end_with_restore_list:
|
|||||||
if (check_one_table_access(thd, privilege, all_tables))
|
if (check_one_table_access(thd, privilege, all_tables))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
|
res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
|
||||||
lex->update_list, lex->value_list, lex->duplicates,
|
lex->update_list, lex->value_list, lex->duplicates,
|
||||||
lex->ignore, (bool) lex->local_file);
|
lex->ignore, (bool) lex->local_file);
|
||||||
|
@@ -4183,13 +4183,13 @@ bool mysql_unpack_partition(THD *thd,
|
|||||||
We need to free any memory objects allocated on item_free_list
|
We need to free any memory objects allocated on item_free_list
|
||||||
by the parser since we are keeping the old info from the first
|
by the parser since we are keeping the old info from the first
|
||||||
parser call in CREATE TABLE.
|
parser call in CREATE TABLE.
|
||||||
We'll ensure that this object isn't put into table cache also
|
|
||||||
just to ensure we don't get into strange situations with the
|
This table object can not be used any more. However, since
|
||||||
item objects.
|
this is CREATE TABLE, we know that it will be destroyed by the
|
||||||
|
caller, and rely on that.
|
||||||
*/
|
*/
|
||||||
thd->free_items();
|
thd->free_items();
|
||||||
part_info= thd->work_part_info;
|
part_info= thd->work_part_info;
|
||||||
table->s->version= 0UL;
|
|
||||||
*work_part_info_used= true;
|
*work_part_info_used= true;
|
||||||
}
|
}
|
||||||
table->part_info= part_info;
|
table->part_info= part_info;
|
||||||
@@ -4482,12 +4482,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
We are going to manipulate the partition info on the table object
|
We are going to manipulate the partition info on the table object
|
||||||
so we need to ensure that the data structure of the table object
|
so we need to ensure that the table instance is removed from the
|
||||||
is freed by setting version to 0. table->s->version= 0 forces a
|
table cache.
|
||||||
flush of the table object in close_thread_tables().
|
|
||||||
*/
|
*/
|
||||||
if (table->part_info)
|
if (table->part_info)
|
||||||
table->s->version= 0L;
|
table->m_needs_reopen= TRUE;
|
||||||
|
|
||||||
thd->work_part_info= thd->lex->part_info;
|
thd->work_part_info= thd->lex->part_info;
|
||||||
if (thd->work_part_info &&
|
if (thd->work_part_info &&
|
||||||
@@ -6242,7 +6241,9 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
|
|||||||
alter_partition_lock_handling() and the table is closed
|
alter_partition_lock_handling() and the table is closed
|
||||||
by close_thread_tables() instead.
|
by close_thread_tables() instead.
|
||||||
*/
|
*/
|
||||||
table->s->version= 0;
|
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
|
||||||
|
table->s->db.str,
|
||||||
|
table->s->table_name.str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
|
@@ -11096,6 +11096,13 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
|||||||
fields);
|
fields);
|
||||||
rc= join->result->send_data(*columns_list);
|
rc= join->result->send_data(*columns_list);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
An error can happen when evaluating the conds
|
||||||
|
(the join condition and piece of where clause
|
||||||
|
relevant to this join table).
|
||||||
|
*/
|
||||||
|
if (join->thd->is_error())
|
||||||
|
error= NESTED_LOOP_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -7049,6 +7049,10 @@ view_err:
|
|||||||
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||||
new_table->next_number_field=new_table->found_next_number_field;
|
new_table->next_number_field=new_table->found_next_number_field;
|
||||||
thd_proc_info(thd, "copy to tmp table");
|
thd_proc_info(thd, "copy to tmp table");
|
||||||
|
DBUG_EXECUTE_IF("abort_copy_table", {
|
||||||
|
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
|
||||||
|
goto err_new_table_cleanup;
|
||||||
|
});
|
||||||
error= copy_data_between_tables(table, new_table,
|
error= copy_data_between_tables(table, new_table,
|
||||||
alter_info->create_list, ignore,
|
alter_info->create_list, ignore,
|
||||||
order_num, order, &copied, &deleted,
|
order_num, order, &copied, &deleted,
|
||||||
|
15
sql/table.h
15
sql/table.h
@@ -294,6 +294,8 @@ TABLE_CATEGORY get_table_category(const LEX_STRING *db,
|
|||||||
|
|
||||||
struct TABLE_share;
|
struct TABLE_share;
|
||||||
|
|
||||||
|
extern ulong refresh_version;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This structure is shared between different table objects. There is one
|
This structure is shared between different table objects. There is one
|
||||||
instance of table share per one table in the database.
|
instance of table share per one table in the database.
|
||||||
@@ -503,6 +505,14 @@ struct TABLE_SHARE
|
|||||||
return table_map_id;
|
return table_map_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Must all TABLEs be reopened?
|
||||||
|
*/
|
||||||
|
inline bool needs_reopen()
|
||||||
|
{
|
||||||
|
return version != refresh_version;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Convert unrelated members of TABLE_SHARE to one enum
|
Convert unrelated members of TABLE_SHARE to one enum
|
||||||
representing its type.
|
representing its type.
|
||||||
@@ -605,8 +615,6 @@ struct TABLE_SHARE
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern ulong refresh_version;
|
|
||||||
|
|
||||||
/* Information for one open table */
|
/* Information for one open table */
|
||||||
enum index_hint_type
|
enum index_hint_type
|
||||||
{
|
{
|
||||||
@@ -804,6 +812,7 @@ public:
|
|||||||
my_bool insert_or_update; /* Can be used by the handler */
|
my_bool insert_or_update; /* Can be used by the handler */
|
||||||
my_bool alias_name_used; /* true if table_name is alias */
|
my_bool alias_name_used; /* true if table_name is alias */
|
||||||
my_bool get_fields_in_item_tree; /* Signal to fix_field */
|
my_bool get_fields_in_item_tree; /* Signal to fix_field */
|
||||||
|
my_bool m_needs_reopen;
|
||||||
|
|
||||||
REGINFO reginfo; /* field connections */
|
REGINFO reginfo; /* field connections */
|
||||||
MEM_ROOT mem_root;
|
MEM_ROOT mem_root;
|
||||||
@@ -853,7 +862,7 @@ public:
|
|||||||
Is this instance of the table should be reopen?
|
Is this instance of the table should be reopen?
|
||||||
*/
|
*/
|
||||||
inline bool needs_reopen()
|
inline bool needs_reopen()
|
||||||
{ return s->version != refresh_version; }
|
{ return !db_stat || m_needs_reopen; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user