Commit db6864b2 authored by Konstantin Osipov's avatar Konstantin Osipov

Merge with next-4284.

parents 2e73ea7e 1b5f2b90
/*
* Generated by dheadgen(1).
*/
#ifndef _PROBES_MYSQL_D
#define _PROBES_MYSQL_D
#ifdef __cplusplus
extern "C" {
#endif
#define MYSQL_CONNECTION_START(arg0, arg1, arg2)
#define MYSQL_CONNECTION_START_ENABLED() (0)
#define MYSQL_CONNECTION_DONE(arg0, arg1)
#define MYSQL_CONNECTION_DONE_ENABLED() (0)
#define MYSQL_COMMAND_START(arg0, arg1, arg2, arg3)
#define MYSQL_COMMAND_START_ENABLED() (0)
#define MYSQL_COMMAND_DONE(arg0)
#define MYSQL_COMMAND_DONE_ENABLED() (0)
#define MYSQL_QUERY_START(arg0, arg1, arg2, arg3, arg4)
#define MYSQL_QUERY_START_ENABLED() (0)
#define MYSQL_QUERY_DONE(arg0)
#define MYSQL_QUERY_DONE_ENABLED() (0)
#define MYSQL_QUERY_PARSE_START(arg0)
#define MYSQL_QUERY_PARSE_START_ENABLED() (0)
#define MYSQL_QUERY_PARSE_DONE(arg0)
#define MYSQL_QUERY_PARSE_DONE_ENABLED() (0)
#define MYSQL_QUERY_CACHE_HIT(arg0, arg1)
#define MYSQL_QUERY_CACHE_HIT_ENABLED() (0)
#define MYSQL_QUERY_CACHE_MISS(arg0)
#define MYSQL_QUERY_CACHE_MISS_ENABLED() (0)
#define MYSQL_QUERY_EXEC_START(arg0, arg1, arg2, arg3, arg4, arg5)
#define MYSQL_QUERY_EXEC_START_ENABLED() (0)
#define MYSQL_QUERY_EXEC_DONE(arg0)
#define MYSQL_QUERY_EXEC_DONE_ENABLED() (0)
#define MYSQL_INSERT_ROW_START(arg0, arg1)
#define MYSQL_INSERT_ROW_START_ENABLED() (0)
#define MYSQL_INSERT_ROW_DONE(arg0)
#define MYSQL_INSERT_ROW_DONE_ENABLED() (0)
#define MYSQL_UPDATE_ROW_START(arg0, arg1)
#define MYSQL_UPDATE_ROW_START_ENABLED() (0)
#define MYSQL_UPDATE_ROW_DONE(arg0)
#define MYSQL_UPDATE_ROW_DONE_ENABLED() (0)
#define MYSQL_DELETE_ROW_START(arg0, arg1)
#define MYSQL_DELETE_ROW_START_ENABLED() (0)
#define MYSQL_DELETE_ROW_DONE(arg0)
#define MYSQL_DELETE_ROW_DONE_ENABLED() (0)
#define MYSQL_READ_ROW_START(arg0, arg1, arg2)
#define MYSQL_READ_ROW_START_ENABLED() (0)
#define MYSQL_READ_ROW_DONE(arg0)
#define MYSQL_READ_ROW_DONE_ENABLED() (0)
#define MYSQL_INDEX_READ_ROW_START(arg0, arg1)
#define MYSQL_INDEX_READ_ROW_START_ENABLED() (0)
#define MYSQL_INDEX_READ_ROW_DONE(arg0)
#define MYSQL_INDEX_READ_ROW_DONE_ENABLED() (0)
#define MYSQL_HANDLER_RDLOCK_START(arg0, arg1)
#define MYSQL_HANDLER_RDLOCK_START_ENABLED() (0)
#define MYSQL_HANDLER_WRLOCK_START(arg0, arg1)
#define MYSQL_HANDLER_WRLOCK_START_ENABLED() (0)
#define MYSQL_HANDLER_UNLOCK_START(arg0, arg1)
#define MYSQL_HANDLER_UNLOCK_START_ENABLED() (0)
#define MYSQL_HANDLER_RDLOCK_DONE(arg0)
#define MYSQL_HANDLER_RDLOCK_DONE_ENABLED() (0)
#define MYSQL_HANDLER_WRLOCK_DONE(arg0)
#define MYSQL_HANDLER_WRLOCK_DONE_ENABLED() (0)
#define MYSQL_HANDLER_UNLOCK_DONE(arg0)
#define MYSQL_HANDLER_UNLOCK_DONE_ENABLED() (0)
#define MYSQL_FILESORT_START(arg0, arg1)
#define MYSQL_FILESORT_START_ENABLED() (0)
#define MYSQL_FILESORT_DONE(arg0, arg1)
#define MYSQL_FILESORT_DONE_ENABLED() (0)
#define MYSQL_SELECT_START(arg0)
#define MYSQL_SELECT_START_ENABLED() (0)
#define MYSQL_SELECT_DONE(arg0, arg1)
#define MYSQL_SELECT_DONE_ENABLED() (0)
#define MYSQL_INSERT_START(arg0)
#define MYSQL_INSERT_START_ENABLED() (0)
#define MYSQL_INSERT_DONE(arg0, arg1)
#define MYSQL_INSERT_DONE_ENABLED() (0)
#define MYSQL_INSERT_SELECT_START(arg0)
#define MYSQL_INSERT_SELECT_START_ENABLED() (0)
#define MYSQL_INSERT_SELECT_DONE(arg0, arg1)
#define MYSQL_INSERT_SELECT_DONE_ENABLED() (0)
#define MYSQL_UPDATE_START(arg0)
#define MYSQL_UPDATE_START_ENABLED() (0)
#define MYSQL_UPDATE_DONE(arg0, arg1, arg2)
#define MYSQL_UPDATE_DONE_ENABLED() (0)
#define MYSQL_MULTI_UPDATE_START(arg0)
#define MYSQL_MULTI_UPDATE_START_ENABLED() (0)
#define MYSQL_MULTI_UPDATE_DONE(arg0, arg1, arg2)
#define MYSQL_MULTI_UPDATE_DONE_ENABLED() (0)
#define MYSQL_DELETE_START(arg0)
#define MYSQL_DELETE_START_ENABLED() (0)
#define MYSQL_DELETE_DONE(arg0, arg1)
#define MYSQL_DELETE_DONE_ENABLED() (0)
#define MYSQL_MULTI_DELETE_START(arg0)
#define MYSQL_MULTI_DELETE_START_ENABLED() (0)
#define MYSQL_MULTI_DELETE_DONE(arg0, arg1)
#define MYSQL_MULTI_DELETE_DONE_ENABLED() (0)
#define MYSQL_NET_READ_START()
#define MYSQL_NET_READ_START_ENABLED() (0)
#define MYSQL_NET_READ_DONE(arg0, arg1)
#define MYSQL_NET_READ_DONE_ENABLED() (0)
#define MYSQL_NET_WRITE_START(arg0)
#define MYSQL_NET_WRITE_START_ENABLED() (0)
#define MYSQL_NET_WRITE_DONE(arg0)
#define MYSQL_NET_WRITE_DONE_ENABLED() (0)
#define MYSQL_KEYCACHE_READ_START(arg0, arg1, arg2, arg3)
#define MYSQL_KEYCACHE_READ_START_ENABLED() (0)
#define MYSQL_KEYCACHE_READ_BLOCK(arg0)
#define MYSQL_KEYCACHE_READ_BLOCK_ENABLED() (0)
#define MYSQL_KEYCACHE_READ_HIT()
#define MYSQL_KEYCACHE_READ_HIT_ENABLED() (0)
#define MYSQL_KEYCACHE_READ_MISS()
#define MYSQL_KEYCACHE_READ_MISS_ENABLED() (0)
#define MYSQL_KEYCACHE_READ_DONE(arg0, arg1)
#define MYSQL_KEYCACHE_READ_DONE_ENABLED() (0)
#define MYSQL_KEYCACHE_WRITE_START(arg0, arg1, arg2, arg3)
#define MYSQL_KEYCACHE_WRITE_START_ENABLED() (0)
#define MYSQL_KEYCACHE_WRITE_BLOCK(arg0)
#define MYSQL_KEYCACHE_WRITE_BLOCK_ENABLED() (0)
#define MYSQL_KEYCACHE_WRITE_DONE(arg0, arg1)
#define MYSQL_KEYCACHE_WRITE_DONE_ENABLED() (0)
#ifdef __cplusplus
}
#endif
#endif /* _PROBES_MYSQL_D */
...@@ -186,6 +186,14 @@ INSERT INTO global_suppressions VALUES ...@@ -186,6 +186,14 @@ INSERT INTO global_suppressions VALUES
(": The MySQL server is running with the --secure-backup-file-priv option so it cannot execute this statement"), (": The MySQL server is running with the --secure-backup-file-priv option so it cannot execute this statement"),
("Slave: Unknown table 't1' Error_code: 1051"), ("Slave: Unknown table 't1' Error_code: 1051"),
/*
BUG#42147 - Concurrent DML and LOCK TABLE ... READ for InnoDB
table cause warnings in errlog
Note: This is a temporary suppression until Bug#42147 can be
fixed properly. See bug page for more information.
*/
("Found lock of type 6 that is write and read locked"),
("THE_LAST_SUPPRESSION")|| ("THE_LAST_SUPPRESSION")||
......
...@@ -376,6 +376,9 @@ sub mtr_report_stats ($) { ...@@ -376,6 +376,9 @@ sub mtr_report_stats ($) {
/Slave: Can't DROP 'c7'.* 1091/ or /Slave: Can't DROP 'c7'.* 1091/ or
/Slave: Key column 'c6'.* 1072/ or /Slave: Key column 'c6'.* 1072/ or
# Warnings generated until bug#42147 is properly resolved
/Found lock of type 6 that is write and read locked/ or
# rpl_idempotency.test produces warnings for the slave. # rpl_idempotency.test produces warnings for the slave.
($testname eq 'rpl.rpl_idempotency' and ($testname eq 'rpl.rpl_idempotency' and
(/Slave: Can\'t find record in \'t1\' Error_code: 1032/ or (/Slave: Can\'t find record in \'t1\' Error_code: 1032/ or
......
...@@ -1961,3 +1961,22 @@ END ;| ...@@ -1961,3 +1961,22 @@ END ;|
ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table' ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table'
DROP TABLE t1; DROP TABLE t1;
DROP TABLE B; DROP TABLE B;
#
# Bug #47107 assert in notify_shared_lock on incorrect
# CREATE TABLE , HANDLER
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 integer);
# The following CREATE TABLEs before gave an assert.
HANDLER t1 OPEN AS A;
CREATE TABLE t1 SELECT 1 AS f2;
ERROR 42S01: Table 't1' already exists
HANDLER t1 OPEN AS A;
CREATE TABLE t1(f1 integer);
ERROR 42S01: Table 't1' already exists
CREATE TABLE t2(f1 integer);
HANDLER t1 OPEN AS A;
CREATE TABLE t1 LIKE t2;
ERROR 42S01: Table 't1' already exists
DROP TABLE t2;
DROP TABLE t1;
...@@ -21,4 +21,36 @@ INSERT INTO t1 VALUES (2); ...@@ -21,4 +21,36 @@ INSERT INTO t1 VALUES (2);
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
# Cleanup # Cleanup
commit; commit;
set @@autocommit=1;
commit; commit;
set @@autocommit=1;
set @@autocommit=1;
#
# Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB
# table cause warnings in errlog
#
#
# Note that this test for now relies on a global suppression of
# the warning "Found lock of type 6 that is write and read locked"
# This suppression rule can be removed once Bug#42147 is properly
# fixed. See bug page for more info.
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (i INT) engine= innodb;
# Connection 2
# Get user-level lock
SELECT get_lock('bug42147_lock', 60);
get_lock('bug42147_lock', 60)
1
# Connection 1
INSERT INTO t1 SELECT get_lock('bug42147_lock', 60);
# Connection 2
LOCK TABLES t1 READ;
SELECT release_lock('bug42147_lock');
release_lock('bug42147_lock')
1
# Connection 1
# Connection 2
UNLOCK TABLES;
# Connection 1
DROP TABLE t1;
...@@ -41,7 +41,7 @@ lock tables t1 write; ...@@ -41,7 +41,7 @@ lock tables t1 write;
check table t2; check table t2;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t2 check Error Table 't2' was not locked with LOCK TABLES test.t2 check Error Table 't2' was not locked with LOCK TABLES
test.t2 check error Corrupt test.t2 check status Operation failed
insert into t1 select index1,nr from t1; insert into t1 select index1,nr 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;
......
...@@ -2502,4 +2502,34 @@ c1 ...@@ -2502,4 +2502,34 @@ c1
DROP TRIGGER t2_au; DROP TRIGGER t2_au;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP TABLE tm1, t1, t2, t3, t4, t5; DROP TABLE tm1, t1, t2, t3, t4, t5;
#
# Bug47098 assert in MDL_context::destroy on HANDLER
# <damaged merge table> OPEN
#
# Test that merge tables are closed correctly when opened using
# HANDLER ... OPEN.
# The general case.
DROP TABLE IF EXISTS t1, t2, t3;
# Connection con1.
CREATE TABLE t1 (c1 int);
CREATE TABLE t2 (c1 int);
CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
START TRANSACTION;
HANDLER t3 OPEN;
ERROR HY000: Table storage engine for 't3' doesn't have this option
DROP TABLE t1, t2, t3;
# Connection default.
# Disconnecting con1, all mdl_tickets must have been released.
# The bug-specific case.
# Connection con1.
CREATE TABLE t1 (c1 int);
CREATE TABLE t2 (c1 int);
CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
DROP TABLE t2;
START TRANSACTION;
HANDLER t3 OPEN;
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
DROP TABLE t1, t3;
# Connection default.
# Disconnecting con1, all mdl_tickets must have been released.
End of 6.0 tests End of 6.0 tests
...@@ -157,3 +157,15 @@ REPAIR TABLE tt1 USE_FRM; ...@@ -157,3 +157,15 @@ REPAIR TABLE tt1 USE_FRM;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
tt1 repair error Cannot repair temporary table from .frm file tt1 repair error Cannot repair temporary table from .frm file
DROP TABLE tt1; DROP TABLE tt1;
#
# Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INT);
LOCK TABLES t1 READ;
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair Error Table 't1' was locked with a READ lock and can't be updated
test.t1 repair status Operation failed
UNLOCK TABLES;
DROP TABLE t1;
...@@ -1955,15 +1955,15 @@ CHECK TABLE v1, v2, v3, v4, v5, v6; ...@@ -1955,15 +1955,15 @@ CHECK TABLE v1, v2, v3, v4, v5, v6;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.v1 check Error FUNCTION test.f1 does not exist test.v1 check Error FUNCTION test.f1 does not exist
test.v1 check Error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v1 check Error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
test.v1 check error Corrupt test.v1 check status Operation failed
test.v2 check status OK test.v2 check status OK
test.v3 check Error FUNCTION test.f1 does not exist test.v3 check Error FUNCTION test.f1 does not exist
test.v3 check Error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v3 check Error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
test.v3 check error Corrupt test.v3 check status Operation failed
test.v4 check status OK test.v4 check status OK
test.v5 check Error FUNCTION test.f1 does not exist test.v5 check Error FUNCTION test.f1 does not exist
test.v5 check Error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v5 check Error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
test.v5 check error Corrupt test.v5 check status Operation failed
test.v6 check status OK test.v6 check status OK
create function f1 () returns int return (select max(col1) from t1); create function f1 () returns int return (select max(col1) from t1);
DROP TABLE t1; DROP TABLE t1;
......
...@@ -1639,3 +1639,33 @@ END ;| ...@@ -1639,3 +1639,33 @@ END ;|
DROP TABLE t1; DROP TABLE t1;
DROP TABLE B; DROP TABLE B;
--echo #
--echo # Bug #47107 assert in notify_shared_lock on incorrect
--echo # CREATE TABLE , HANDLER
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(f1 integer);
--echo # The following CREATE TABLEs before gave an assert.
HANDLER t1 OPEN AS A;
--error ER_TABLE_EXISTS_ERROR
CREATE TABLE t1 SELECT 1 AS f2;
HANDLER t1 OPEN AS A;
--error ER_TABLE_EXISTS_ERROR
CREATE TABLE t1(f1 integer);
CREATE TABLE t2(f1 integer);
HANDLER t1 OPEN AS A;
--error ER_TABLE_EXISTS_ERROR
CREATE TABLE t1 LIKE t2;
DROP TABLE t2;
DROP TABLE t1;
-- source include/have_innodb.inc -- source include/have_innodb.inc
# Save the initial number of concurrent sessions.
--source include/count_sessions.inc
--echo # --echo #
--echo # Bug #22876 Four-way deadlock --echo # Bug #22876 Four-way deadlock
--echo # --echo #
...@@ -51,8 +54,68 @@ INSERT INTO t1 VALUES (2); ...@@ -51,8 +54,68 @@ INSERT INTO t1 VALUES (2);
connection con2; connection con2;
--reap --reap
commit; commit;
set @@autocommit=1;
connection con1; connection con1;
commit; commit;
set @@autocommit=1;
connection con3; connection con3;
--reap --reap
set @@autocommit=1;
connection default; connection default;
disconnect con1;
disconnect con3;
--echo #
--echo # Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB
--echo # table cause warnings in errlog
--echo #
--echo #
--echo # Note that this test for now relies on a global suppression of
--echo # the warning "Found lock of type 6 that is write and read locked"
--echo # This suppression rule can be removed once Bug#42147 is properly
--echo # fixed. See bug page for more info.
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (i INT) engine= innodb;
--echo # Connection 2
--echo # Get user-level lock
connection con2;
SELECT get_lock('bug42147_lock', 60);
--echo # Connection 1
connection default;
--send INSERT INTO t1 SELECT get_lock('bug42147_lock', 60)
--echo # Connection 2
connection con2;
let $wait_condition=
SELECT COUNT(*) > 0 FROM information_schema.processlist
WHERE state = 'User lock'
AND info = 'INSERT INTO t1 SELECT get_lock(\'bug42147_lock\', 60)';
--source include/wait_condition.inc
LOCK TABLES t1 READ;
SELECT release_lock('bug42147_lock');
--echo # Connection 1
connection default;
--reap
--echo # Connection 2
connection con2;
UNLOCK TABLES;
--echo # Connection 1
connection default;
disconnect con2;
DROP TABLE t1;
# 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.
--source include/wait_until_count_sessions.inc
...@@ -1985,6 +1985,43 @@ DROP TRIGGER t2_au; ...@@ -1985,6 +1985,43 @@ DROP TRIGGER t2_au;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP TABLE tm1, t1, t2, t3, t4, t5; DROP TABLE tm1, t1, t2, t3, t4, t5;
--echo #
--echo # Bug47098 assert in MDL_context::destroy on HANDLER
--echo # <damaged merge table> OPEN
--echo #
--echo # Test that merge tables are closed correctly when opened using
--echo # HANDLER ... OPEN.
--echo # The general case.
--disable_warnings
DROP TABLE IF EXISTS t1, t2, t3;
--enable_warnings
--echo # Connection con1.
connect (con1,localhost,root,,);
CREATE TABLE t1 (c1 int);
CREATE TABLE t2 (c1 int);
CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
START TRANSACTION;
--error ER_ILLEGAL_HA
HANDLER t3 OPEN;
DROP TABLE t1, t2, t3;
--echo # Connection default.
connection default;
--echo # Disconnecting con1, all mdl_tickets must have been released.
disconnect con1;
--echo # The bug-specific case.
--echo # Connection con1.
connect (con1,localhost,root,,);
CREATE TABLE t1 (c1 int);
CREATE TABLE t2 (c1 int);
CREATE TABLE t3 (c1 int) ENGINE = MERGE UNION (t1,t2);
DROP TABLE t2;
START TRANSACTION;
--error ER_WRONG_MRG_TABLE
HANDLER t3 OPEN;
DROP TABLE t1, t3;
--echo # Connection default.
connection default;
--echo # Disconnecting con1, all mdl_tickets must have been released.
disconnect con1;
--echo End of 6.0 tests --echo End of 6.0 tests
...@@ -158,3 +158,18 @@ CREATE TEMPORARY TABLE tt1 (c1 INT); ...@@ -158,3 +158,18 @@ CREATE TEMPORARY TABLE tt1 (c1 INT);
REPAIR TABLE tt1 USE_FRM; REPAIR TABLE tt1 USE_FRM;
DROP TABLE tt1; DROP TABLE tt1;
--echo #
--echo # Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(a INT);
LOCK TABLES t1 READ;
REPAIR TABLE t1;
UNLOCK TABLES;
DROP TABLE t1;
...@@ -540,13 +540,31 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, ...@@ -540,13 +540,31 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
/* Request for READ lock */ /* Request for READ lock */
if (lock->write.data) if (lock->write.data)
{ {
/* We can allow a read lock even if there is already a write lock /*
on the table in one the following cases: We can allow a read lock even if there is already a
- This thread alread have a write lock on the table write lock on the table if they are owned by the same
- The write lock is TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED thread or if they satisfy the following lock
and the read lock is TL_READ_HIGH_PRIORITY or TL_READ compatibility matrix:
- The write lock is TL_WRITE_CONCURRENT_INSERT or TL_WRITE_ALLOW_WRITE
and the read lock is not TL_READ_NO_INSERT Request
/-------
H|++++ WRITE_ALLOW_WRITE
e|+++- WRITE_ALLOW_READ
l|+++- WRITE_CONCURRENT_INSERT
d|++++ WRITE_DELAYED
||||
|||\= READ_NO_INSERT
||\ = READ_HIGH_PRIORITY
|\ = READ_WITH_SHARED_LOCKS
\ = READ
+ = Request can be satisified.
- = Request cannot be satisified.
READ_NO_INSERT and WRITE_ALLOW_WRITE should in principle
be incompatible. However this will cause starvation of
LOCK TABLE READ in InnoDB under high write load.
See Bug#42147 for more information.
*/ */
DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx",
......
...@@ -1099,6 +1099,19 @@ static volatile uint waiting_for_read_lock=0; ...@@ -1099,6 +1099,19 @@ static volatile uint waiting_for_read_lock=0;
#define GOT_GLOBAL_READ_LOCK 1 #define GOT_GLOBAL_READ_LOCK 1
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2 #define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
/**
Take global read lock, wait if there is protection against lock.
If the global read lock is already taken by this thread, then nothing is done.
See also "Handling of global read locks" above.
@param thd Reference to thread.
@retval False Success, global read lock set, commits are NOT blocked.
@retval True Failure, thread was killed.
*/
bool lock_global_read_lock(THD *thd) bool lock_global_read_lock(THD *thd)
{ {
DBUG_ENTER("lock_global_read_lock"); DBUG_ENTER("lock_global_read_lock");
...@@ -1165,6 +1178,16 @@ bool lock_global_read_lock(THD *thd) ...@@ -1165,6 +1178,16 @@ bool lock_global_read_lock(THD *thd)
} }
/**
Unlock global read lock.
Commits may or may not be blocked when this function is called.
See also "Handling of global read locks" above.
@param thd Reference to thread.
*/
void unlock_global_read_lock(THD *thd) void unlock_global_read_lock(THD *thd)
{ {
uint tmp; uint tmp;
...@@ -1191,6 +1214,25 @@ void unlock_global_read_lock(THD *thd) ...@@ -1191,6 +1214,25 @@ void unlock_global_read_lock(THD *thd)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/**
Wait if the global read lock is set, and optionally seek protection against
global read lock.
See also "Handling of global read locks" above.
@param thd Reference to thread.
@param abort_on_refresh If True, abort waiting if a refresh occurs,
do NOT seek protection against GRL.
If False, wait until the GRL is released and seek
protection against GRL.
@param is_not_commit If False, called from a commit operation,
wait only if commit blocking is also enabled.
@retval False Success, protection against global read lock is set
(if !abort_on_refresh)
@retval True Failure, wait was aborted or thread was killed.
*/
#define must_wait (global_read_lock && \ #define must_wait (global_read_lock && \
(is_not_commit || \ (is_not_commit || \
global_read_lock_blocks_commit)) global_read_lock_blocks_commit))
...@@ -1202,6 +1244,16 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, ...@@ -1202,6 +1244,16 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
bool result= 0, need_exit_cond; bool result= 0, need_exit_cond;
DBUG_ENTER("wait_if_global_read_lock"); DBUG_ENTER("wait_if_global_read_lock");
/*
If we already have protection against global read lock,
just increment the counter.
*/
if (unlikely(thd->global_read_lock_protection > 0))
{
if (!abort_on_refresh)
thd->global_read_lock_protection++;
DBUG_RETURN(FALSE);
}
/* /*
Assert that we do not own LOCK_open. If we would own it, other Assert that we do not own LOCK_open. If we would own it, other
threads could not close their tables. This would make a pretty threads could not close their tables. This would make a pretty
...@@ -1238,7 +1290,12 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, ...@@ -1238,7 +1290,12 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
result=1; result=1;
} }
if (!abort_on_refresh && !result) if (!abort_on_refresh && !result)
{
thd->global_read_lock_protection++;
protect_against_global_read_lock++; protect_against_global_read_lock++;
DBUG_PRINT("sql_lock", ("protect_against_global_read_lock incr: %u",
protect_against_global_read_lock));
}
/* /*
The following is only true in case of a global read locks (which is rare) The following is only true in case of a global read locks (which is rare)
and if old_message is set and if old_message is set
...@@ -1251,10 +1308,31 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, ...@@ -1251,10 +1308,31 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
} }
/**
Release protection against global read lock and restart
global read lock waiters.
Should only be called if we have protection against global read lock.
See also "Handling of global read locks" above.
@param thd Reference to thread.
*/
void start_waiting_global_read_lock(THD *thd) void start_waiting_global_read_lock(THD *thd)
{ {
bool tmp; bool tmp;
DBUG_ENTER("start_waiting_global_read_lock"); DBUG_ENTER("start_waiting_global_read_lock");
/*
Ignore request if we do not have protection against global read lock.
(Note that this is a violation of the interface contract, hence the assert).
*/
DBUG_ASSERT(thd->global_read_lock_protection > 0);
if (unlikely(thd->global_read_lock_protection == 0))
DBUG_VOID_RETURN;
/* Decrement local read lock protection counter, return if we still have it */
if (unlikely(--thd->global_read_lock_protection > 0))
DBUG_VOID_RETURN;
if (unlikely(thd->global_read_lock)) if (unlikely(thd->global_read_lock))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
(void) pthread_mutex_lock(&LOCK_global_read_lock); (void) pthread_mutex_lock(&LOCK_global_read_lock);
...@@ -1268,6 +1346,21 @@ void start_waiting_global_read_lock(THD *thd) ...@@ -1268,6 +1346,21 @@ void start_waiting_global_read_lock(THD *thd)
} }
/**
Make global read lock also block commits.
The scenario is:
- This thread has the global read lock.
- Global read lock blocking of commits is not set.
See also "Handling of global read locks" above.
@param thd Reference to thread.
@retval False Success, global read lock set, commits are blocked.
@retval True Failure, thread was killed.
*/
bool make_global_read_lock_block_commit(THD *thd) bool make_global_read_lock_block_commit(THD *thd)
{ {
bool error; bool error;
......
...@@ -452,6 +452,7 @@ THD::THD() ...@@ -452,6 +452,7 @@ THD::THD()
examined_row_count(0), examined_row_count(0),
warning_info(&main_warning_info), warning_info(&main_warning_info),
stmt_da(&main_da), stmt_da(&main_da),
global_read_lock_protection(0),
global_read_lock(0), global_read_lock(0),
is_fatal_error(0), is_fatal_error(0),
transaction_rollback_request(0), transaction_rollback_request(0),
......
...@@ -1874,6 +1874,7 @@ class THD :public Statement, ...@@ -1874,6 +1874,7 @@ class THD :public Statement,
ulong rand_saved_seed1, rand_saved_seed2; ulong rand_saved_seed1, rand_saved_seed2;
pthread_t real_id; /* For debugging */ pthread_t real_id; /* For debugging */
my_thread_id thread_id; my_thread_id thread_id;
uint global_read_lock_protection;// GRL protection count
uint tmp_table, global_read_lock; uint tmp_table, global_read_lock;
uint server_status,open_options; uint server_status,open_options;
enum enum_thread_type system_thread; enum enum_thread_type system_thread;
......
...@@ -321,6 +321,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) ...@@ -321,6 +321,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
can close a single table only. can close a single table only.
*/ */
close_thread_tables(thd); close_thread_tables(thd);
thd->mdl_context.release_all_locks();
my_error(ER_ILLEGAL_HA, MYF(0), hash_tables->alias); my_error(ER_ILLEGAL_HA, MYF(0), hash_tables->alias);
error= TRUE; error= TRUE;
} }
......
...@@ -1974,6 +1974,11 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) ...@@ -1974,6 +1974,11 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
} }
pthread_mutex_unlock(&di->mutex); pthread_mutex_unlock(&di->mutex);
thd_proc_info(thd, "got old table"); thd_proc_info(thd, "got old table");
if (thd->killed)
{
di->unlock();
goto end_create;
}
if (di->thd.killed) if (di->thd.killed)
{ {
if (di->thd.is_error()) if (di->thd.is_error())
...@@ -1981,20 +1986,19 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) ...@@ -1981,20 +1986,19 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
/* /*
Copy the error message. Note that we don't treat fatal Copy the error message. Note that we don't treat fatal
errors in the delayed thread as fatal errors in the errors in the delayed thread as fatal errors in the
main thread. Use of my_message will enable stored main thread. If delayed thread was killed, we don't
procedures continue handlers. want to send "Server shutdown in progress" in the
INSERT THREAD.
*/ */
my_message(di->thd.stmt_da->sql_errno(), di->thd.stmt_da->message(), if (di->thd.stmt_da->sql_errno() == ER_SERVER_SHUTDOWN)
MYF(0)); my_message(ER_QUERY_INTERRUPTED, ER(ER_QUERY_INTERRUPTED), MYF(0));
} else
di->unlock(); my_message(di->thd.stmt_da->sql_errno(), di->thd.stmt_da->message(),
MYF(0));
}
di->unlock();
goto end_create; goto end_create;
} }
if (thd->killed)
{
di->unlock();
goto end_create;
}
pthread_mutex_lock(&LOCK_delayed_insert); pthread_mutex_lock(&LOCK_delayed_insert);
delayed_threads.append(di); delayed_threads.append(di);
pthread_mutex_unlock(&LOCK_delayed_insert); pthread_mutex_unlock(&LOCK_delayed_insert);
...@@ -2061,7 +2065,11 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) ...@@ -2061,7 +2065,11 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
goto error; goto error;
if (dead) if (dead)
{ {
my_message(thd.stmt_da->sql_errno(), thd.stmt_da->message(), MYF(0)); /* Don't copy over "Server shutdown in progress". */
if (thd.stmt_da->sql_errno() == ER_SERVER_SHUTDOWN)
my_message(ER_QUERY_INTERRUPTED, ER(ER_QUERY_INTERRUPTED), MYF(0));
else
my_message(thd.stmt_da->sql_errno(), thd.stmt_da->message(), MYF(0));
goto error; goto error;
} }
} }
...@@ -2412,7 +2420,7 @@ pthread_handler_t handle_delayed_insert(void *arg) ...@@ -2412,7 +2420,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
for (;;) for (;;)
{ {
if (thd->killed == THD::KILL_CONNECTION) if (thd->killed)
{ {
uint lock_count; uint lock_count;
/* /*
...@@ -2474,7 +2482,7 @@ pthread_handler_t handle_delayed_insert(void *arg) ...@@ -2474,7 +2482,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
} }
thd_proc_info(&(di->thd), 0); thd_proc_info(&(di->thd), 0);
if (di->tables_in_use && ! thd->lock) if (di->tables_in_use && ! thd->lock && !thd->killed)
{ {
bool need_reopen; bool need_reopen;
/* /*
...@@ -2491,14 +2499,15 @@ pthread_handler_t handle_delayed_insert(void *arg) ...@@ -2491,14 +2499,15 @@ pthread_handler_t handle_delayed_insert(void *arg)
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK, MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK,
&need_reopen))) &need_reopen)))
{ {
if (need_reopen) if (need_reopen && !thd->killed)
{ {
/* /*
We were waiting to obtain TL_WRITE_DELAYED (probably due to We were waiting to obtain TL_WRITE_DELAYED (probably due to
someone having or requesting TL_WRITE_ALLOW_READ) and got someone having or requesting TL_WRITE_ALLOW_READ) and got
aborted. Try to reopen table and if it fails die. aborted. Try to reopen table and if it fails die.
*/ */
close_thread_tables(thd); TABLE_LIST *tl_ptr = &di->table_list;
close_tables_for_reopen(thd, &tl_ptr);
di->table= 0; di->table= 0;
if (di->open_and_lock_table()) if (di->open_and_lock_table())
{ {
......
This diff is collapsed.
...@@ -1780,16 +1780,16 @@ void write_bin_log(THD *thd, bool clear_error, ...@@ -1780,16 +1780,16 @@ void write_bin_log(THD *thd, bool clear_error,
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
my_bool drop_temporary) my_bool drop_temporary)
{ {
bool error= FALSE, need_start_waiting= FALSE; bool error;
Drop_table_error_handler err_handler(thd->get_internal_handler()); Drop_table_error_handler err_handler(thd->get_internal_handler());
DBUG_ENTER("mysql_rm_table"); DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */ /* mark for close and remove all cached entries */
if (!drop_temporary) if (!drop_temporary)
{ {
if (!thd->locked_tables_mode && if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
...@@ -1797,8 +1797,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, ...@@ -1797,8 +1797,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0); error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
thd->pop_internal_handler(); thd->pop_internal_handler();
if (thd->global_read_lock_protection > 0)
if (need_start_waiting)
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
if (error) if (error)
...@@ -4549,6 +4548,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -4549,6 +4548,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
char table_name[NAME_LEN*2+2]; char table_name[NAME_LEN*2+2];
char* db = table->db; char* db = table->db;
bool fatal_error=0; bool fatal_error=0;
bool open_error;
DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name)); DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options)); DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
...@@ -4576,12 +4576,22 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -4576,12 +4576,22 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (view_operator_func == NULL) if (view_operator_func == NULL)
table->required_type=FRMTYPE_TABLE; table->required_type=FRMTYPE_TABLE;
open_and_lock_tables_derived(thd, table, TRUE, open_error= open_and_lock_tables_derived(thd, table, TRUE,
MYSQL_OPEN_TAKE_UPGRADABLE_MDL); MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
thd->no_warnings_for_error= 0; thd->no_warnings_for_error= 0;
table->next_global= save_next_global; table->next_global= save_next_global;
table->next_local= save_next_local; table->next_local= save_next_local;
thd->open_options&= ~extra_open_options; thd->open_options&= ~extra_open_options;
/*
Under locked tables, we know that the table can be opened,
so any errors opening the table are logical errors.
In these cases it does not make sense to try to repair.
*/
if (open_error && thd->locked_tables_mode)
{
result_code= HA_ADMIN_FAILED;
goto send_result;
}
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->table) if (table->table)
{ {
......
...@@ -328,7 +328,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) ...@@ -328,7 +328,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
TABLE *table; TABLE *table;
bool result= TRUE; bool result= TRUE;
String stmt_query; String stmt_query;
bool need_start_waiting= FALSE;
bool lock_upgrade_done= FALSE; bool lock_upgrade_done= FALSE;
MDL_ticket *mdl_ticket= NULL; MDL_ticket *mdl_ticket= NULL;
...@@ -386,8 +385,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) ...@@ -386,8 +385,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
LOCK_open is not enough because global read lock is held without holding LOCK_open is not enough because global read lock is held without holding
LOCK_open). LOCK_open).
*/ */
if (!thd->locked_tables_mode && if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (!create) if (!create)
...@@ -521,7 +519,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) ...@@ -521,7 +519,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (thd->locked_tables_mode && tables && lock_upgrade_done) if (thd->locked_tables_mode && tables && lock_upgrade_done)
mdl_ticket->downgrade_exclusive_lock(); mdl_ticket->downgrade_exclusive_lock();
if (need_start_waiting) if (thd->global_read_lock_protection > 0)
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
if (!result) if (!result)
......
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