merge
This commit is contained in:
commit
01ee0f9677
@ -32,26 +32,32 @@ IF(DEFINED CMAKE_BUILD_TYPE)
|
||||
SET(HAVE_CMAKE_BUILD_TYPE TRUE)
|
||||
ENDIF()
|
||||
SET(CUSTOM_C_FLAGS $ENV{CFLAGS})
|
||||
IF(NOT CUSTOM_C_FLAGS)
|
||||
SET(CUSTOM_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
ENDIF()
|
||||
|
||||
OPTION(WITH_DEBUG "Use dbug" OFF)
|
||||
OPTION(WITH_DEBUG "Use dbug/safemutex" OFF)
|
||||
OPTION(WITH_DEBUG_FULL "Use dbug and safemalloc/safemutex. Slow" OFF)
|
||||
|
||||
IF(NOT HAVE_CMAKE_BUILD_TYPE)
|
||||
IF(BUILD_CONFIG OR NOT CUSTOM_C_FLAGS)
|
||||
IF(WITH_DEBUG)
|
||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Debug build" FORCE)
|
||||
ELSE()
|
||||
SET(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
|
||||
"RelWithDebInfo build" FORCE)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(WITH_DEBUG_FULL)
|
||||
SET(WITH_DEBUG ON CACHE BOOL "Use DBUG")
|
||||
# We choose to provide WITH_DEBUG as alias to standard CMAKE_BUILD_TYPE=Debug
|
||||
# which turns out to be not trivial, as this involves synchronization
|
||||
# between CMAKE_BUILD_TYPE and WITH_DEBUG. Besides, we have to deal with cases
|
||||
# where WITH_DEBUG is reset from ON to OFF and here we need to reset
|
||||
# CMAKE_BUILD_TYPE to either none or default RelWithDebInfo
|
||||
|
||||
SET(BUILDTYPE_DOCSTRING
|
||||
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
|
||||
CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel")
|
||||
|
||||
IF(WITH_DEBUG OR WITH_DEBUG_FULL)
|
||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING ${BUILDTYPE_DOCSTRING} FORCE)
|
||||
SET(OLD_WITH_DEBUG 1 CACHE INTERNAL "" FORCE)
|
||||
ELSEIF(NOT HAVE_CMAKE_BUILD_TYPE OR OLD_WITH_DEBUG)
|
||||
IF(CUSTOM_C_FLAGS)
|
||||
SET(CMAKE_BUILD_TYPE "" CACHE STRING ${BUILDTYPE_DOCSTRING} FORCE)
|
||||
ELSE(CMAKE_BUILD_TYPE MATCHES "Debug" OR NOT HAVE_CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
|
||||
${BUILDTYPE_DOCSTRING} FORCE)
|
||||
ENDIF()
|
||||
SET(OLD_WITH_DEBUG 0 CACHE INTERNAL "" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF(BUILD_CONFIG)
|
||||
|
@ -205,6 +205,7 @@
|
||||
#cmakedefine HAVE_PTHREAD_KEY_DELETE 1
|
||||
#cmakedefine HAVE_PTHREAD_KILL 1
|
||||
#cmakedefine HAVE_PTHREAD_RWLOCK_RDLOCK 1
|
||||
#cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1
|
||||
#cmakedefine HAVE_PTHREAD_SETPRIO_NP 1
|
||||
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM 1
|
||||
#cmakedefine HAVE_PTHREAD_SIGMASK 1
|
||||
|
@ -308,6 +308,7 @@ CHECK_FUNCTION_EXISTS (pthread_condattr_setclock HAVE_PTHREAD_CONDATTR_SETCLOCK)
|
||||
CHECK_FUNCTION_EXISTS (pthread_init HAVE_PTHREAD_INIT)
|
||||
CHECK_FUNCTION_EXISTS (pthread_key_delete HAVE_PTHREAD_KEY_DELETE)
|
||||
CHECK_FUNCTION_EXISTS (pthread_rwlock_rdlock HAVE_PTHREAD_RWLOCK_RDLOCK)
|
||||
CHECK_FUNCTION_EXISTS (pthread_rwlockattr_setkind_np HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
|
||||
CHECK_FUNCTION_EXISTS (pthread_sigmask HAVE_PTHREAD_SIGMASK)
|
||||
CHECK_FUNCTION_EXISTS (pthread_threadmask HAVE_PTHREAD_THREADMASK)
|
||||
CHECK_FUNCTION_EXISTS (pthread_yield_np HAVE_PTHREAD_YIELD_NP)
|
||||
|
@ -2266,7 +2266,8 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bsearch bzero \
|
||||
locking longjmp lrand48 madvise mallinfo memcpy memmove \
|
||||
mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \
|
||||
pthread_attr_getstacksize pthread_attr_setstacksize pthread_condattr_create \
|
||||
pthread_getsequence_np pthread_key_delete pthread_rwlock_rdlock pthread_sigmask \
|
||||
pthread_getsequence_np pthread_key_delete pthread_rwlock_rdlock \
|
||||
pthread_rwlockattr_setkind_np pthread_sigmask \
|
||||
readlink realpath rename rint rwlock_init setupterm \
|
||||
shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \
|
||||
sighold sigset sigthreadmask port_create sleep thr_yield \
|
||||
|
@ -600,30 +600,76 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp);
|
||||
#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0)
|
||||
#else
|
||||
/* Use our own version of read/write locks */
|
||||
typedef struct _my_rw_lock_t {
|
||||
pthread_mutex_t lock; /* lock for structure */
|
||||
pthread_cond_t readers; /* waiting readers */
|
||||
pthread_cond_t writers; /* waiting writers */
|
||||
int state; /* -1:writer,0:free,>0:readers */
|
||||
int waiters; /* number of waiting writers */
|
||||
} my_rw_lock_t;
|
||||
|
||||
#define NEED_MY_RW_LOCK 1
|
||||
#define rw_lock_t my_rw_lock_t
|
||||
#define my_rwlock_init(A,B) my_rw_init((A), 0)
|
||||
#define rw_rdlock(A) my_rw_rdlock((A))
|
||||
#define rw_wrlock(A) my_rw_wrlock((A))
|
||||
#define rw_tryrdlock(A) my_rw_tryrdlock((A))
|
||||
#define rw_trywrlock(A) my_rw_trywrlock((A))
|
||||
#define rw_unlock(A) my_rw_unlock((A))
|
||||
#define rwlock_destroy(A) my_rwlock_destroy((A))
|
||||
#define rwlock_destroy(A) my_rw_destroy((A))
|
||||
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
|
||||
|
||||
extern int my_rwlock_init(my_rw_lock_t *, void *);
|
||||
extern int my_rwlock_destroy(my_rw_lock_t *);
|
||||
|
||||
/*
|
||||
Portable read-write locks which prefer readers.
|
||||
|
||||
Required by some algorithms in order to provide correctness.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
|
||||
/*
|
||||
On systems which have a way to specify that readers should
|
||||
be preferred through attribute mechanism (e.g. Linux) we use
|
||||
system implementation of read/write locks.
|
||||
*/
|
||||
#define rw_pr_lock_t pthread_rwlock_t
|
||||
extern int rw_pr_init(rw_pr_lock_t *);
|
||||
#define rw_pr_rdlock(A) pthread_rwlock_rdlock(A)
|
||||
#define rw_pr_wrlock(A) pthread_rwlock_wrlock(A)
|
||||
#define rw_pr_tryrdlock(A) pthread_rwlock_tryrdlock(A)
|
||||
#define rw_pr_trywrlock(A) pthread_rwlock_trywrlock(A)
|
||||
#define rw_pr_unlock(A) pthread_rwlock_unlock(A)
|
||||
#define rw_pr_destroy(A) pthread_rwlock_destroy(A)
|
||||
#else
|
||||
/* Otherwise we have to use our own implementation of read/write locks. */
|
||||
#define NEED_MY_RW_LOCK 1
|
||||
struct st_my_rw_lock_t;
|
||||
#define rw_pr_lock_t my_rw_lock_t
|
||||
extern int rw_pr_init(struct st_my_rw_lock_t *);
|
||||
#define rw_pr_rdlock(A) my_rw_rdlock((A))
|
||||
#define rw_pr_wrlock(A) my_rw_wrlock((A))
|
||||
#define rw_pr_tryrdlock(A) my_rw_tryrdlock((A))
|
||||
#define rw_pr_trywrlock(A) my_rw_trywrlock((A))
|
||||
#define rw_pr_unlock(A) my_rw_unlock((A))
|
||||
#define rw_pr_destroy(A) my_rw_destroy((A))
|
||||
#endif /* defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) */
|
||||
|
||||
|
||||
#ifdef NEED_MY_RW_LOCK
|
||||
/*
|
||||
On systems which don't support native read/write locks, or don't support
|
||||
read/write locks which prefer readers we have to use own implementation.
|
||||
*/
|
||||
typedef struct st_my_rw_lock_t {
|
||||
pthread_mutex_t lock; /* lock for structure */
|
||||
pthread_cond_t readers; /* waiting readers */
|
||||
pthread_cond_t writers; /* waiting writers */
|
||||
int state; /* -1:writer,0:free,>0:readers */
|
||||
int waiters; /* number of waiting writers */
|
||||
my_bool prefer_readers;
|
||||
} my_rw_lock_t;
|
||||
|
||||
extern int my_rw_init(my_rw_lock_t *, my_bool *);
|
||||
extern int my_rw_destroy(my_rw_lock_t *);
|
||||
extern int my_rw_rdlock(my_rw_lock_t *);
|
||||
extern int my_rw_wrlock(my_rw_lock_t *);
|
||||
extern int my_rw_unlock(my_rw_lock_t *);
|
||||
extern int my_rw_tryrdlock(my_rw_lock_t *);
|
||||
extern int my_rw_trywrlock(my_rw_lock_t *);
|
||||
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
|
||||
#endif /* NEED_MY_RW_LOCK */
|
||||
|
||||
|
||||
#define GETHOSTBYADDR_BUFF_SIZE 2048
|
||||
|
||||
|
@ -111,3 +111,99 @@ commit;
|
||||
# which was already released by commit.
|
||||
unlock tables;
|
||||
drop tables t1, t2;
|
||||
#
|
||||
# Tests for WL#5000 FLUSH TABLES|TABLE table_list WITH READ LOCK
|
||||
#
|
||||
# I. Check the incompatible changes in the grammar.
|
||||
#
|
||||
flush tables with read lock, hosts;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' hosts' at line 1
|
||||
flush privileges, tables;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tables' at line 1
|
||||
flush privileges, tables with read lock;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tables with read lock' at line 1
|
||||
flush privileges, tables;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'tables' at line 1
|
||||
flush tables with read lock, tables;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' tables' at line 1
|
||||
show tables;
|
||||
Tables_in_test
|
||||
#
|
||||
# II. Check the allowed syntax.
|
||||
#
|
||||
drop table if exists t1, t2, t3;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
create table t3 (a int);
|
||||
lock table t1 read, t2 read;
|
||||
flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
unlock tables;
|
||||
flush tables with read lock;
|
||||
flush tables t1, t2 with read lock;
|
||||
flush tables t1, t2 with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
flush tables with read lock;
|
||||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
|
||||
select * from t1;
|
||||
a
|
||||
select * from t2;
|
||||
a
|
||||
select * from t3;
|
||||
ERROR HY000: Table 't3' was not locked with LOCK TABLES
|
||||
insert into t1 (a) values (1);
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
insert into t2 (a) values (1);
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
insert into t3 (a) values (1);
|
||||
ERROR HY000: Table 't3' was not locked with LOCK TABLES
|
||||
lock table no_such_table read;
|
||||
ERROR 42S02: Table 'test.no_such_table' doesn't exist
|
||||
#
|
||||
# We implicitly left the locked tables
|
||||
# mode but still have the read lock.
|
||||
#
|
||||
insert into t2 (a) values (1);
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
unlock tables;
|
||||
insert into t1 (a) values (1);
|
||||
insert into t2 (a) values (1);
|
||||
flush table t1, t2 with read lock;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
1
|
||||
select * from t3;
|
||||
ERROR HY000: Table 't3' was not locked with LOCK TABLES
|
||||
insert into t1 (a) values (2);
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
insert into t2 (a) values (2);
|
||||
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
||||
insert into t3 (a) values (2);
|
||||
ERROR HY000: Table 't3' was not locked with LOCK TABLES
|
||||
lock table no_such_table read;
|
||||
ERROR 42S02: Table 'test.no_such_table' doesn't exist
|
||||
insert into t3 (a) values (2);
|
||||
#
|
||||
# III. Concurrent tests.
|
||||
#
|
||||
# --> connection default
|
||||
#
|
||||
# Check that flush tables <list> with read lock
|
||||
# does not affect non-locked tables.
|
||||
#
|
||||
flush tables t1 with read lock;
|
||||
# --> connection con1;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
1
|
||||
insert into t2 (a) values (3);
|
||||
# --> connection default;
|
||||
unlock tables;
|
||||
# --> connection con1
|
||||
drop table t1, t2, t3;
|
||||
|
@ -115,6 +115,8 @@ select @@optimizer_prune_level;
|
||||
@@optimizer_prune_level
|
||||
1
|
||||
set optimizer_search_depth=63;
|
||||
Warnings:
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
select @@optimizer_search_depth;
|
||||
@@optimizer_search_depth
|
||||
63
|
||||
|
@ -396,8 +396,9 @@ The following options may be given as the first argument:
|
||||
relation result in faster optimization, but may produce
|
||||
very bad query plans. If set to 0, the system will
|
||||
automatically pick a reasonable value; if set to 63, the
|
||||
optimizer will switch to the original find_best
|
||||
search(used for testing/comparison)
|
||||
optimizer will switch to the original find_best search.
|
||||
NOTE: The value 63 and its associated behaviour is
|
||||
deprecated
|
||||
--optimizer-switch=name
|
||||
optimizer_switch=option=val[,option=val...], where option
|
||||
is one of {index_merge, index_merge_union,
|
||||
|
@ -396,8 +396,9 @@ The following options may be given as the first argument:
|
||||
relation result in faster optimization, but may produce
|
||||
very bad query plans. If set to 0, the system will
|
||||
automatically pick a reasonable value; if set to 63, the
|
||||
optimizer will switch to the original find_best
|
||||
search(used for testing/comparison)
|
||||
optimizer will switch to the original find_best search.
|
||||
NOTE: The value 63 and its associated behaviour is
|
||||
deprecated
|
||||
--optimizer-switch=name
|
||||
optimizer_switch=option=val[,option=val...], where option
|
||||
is one of {index_merge, index_merge_union,
|
||||
|
25
mysql-test/suite/large_tests/r/rpl_slave_net_timeout.result
Normal file
25
mysql-test/suite/large_tests/r/rpl_slave_net_timeout.result
Normal file
@ -0,0 +1,25 @@
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
set @save_general_log = @@global.general_log;
|
||||
set @save_log_output = @@global.log_output;
|
||||
set @save_slave_net_timeout = @@global.slave_net_timeout;
|
||||
set @@global.general_log = ON;
|
||||
set @@global.log_output = 'table,file';
|
||||
include/stop_slave.inc
|
||||
set @@global.slave_net_timeout = @@global.net_read_timeout * 2;
|
||||
change master to master_host = '127.0.0.1',master_port = MASTER_PORT,
|
||||
master_user = 'root', master_heartbeat_period = 0;
|
||||
include/start_slave.inc
|
||||
include/stop_slave.inc
|
||||
select event_time from (select event_time from mysql.general_log as t_1 where command_type like 'Connect' order by event_time desc limit 2) as t_2 order by event_time desc limit 1 into @ts_last;
|
||||
select event_time from (select event_time from mysql.general_log as t_1 where command_type like 'Connect' order by event_time desc limit 2) as t_2 order by event_time asc limit 1 into @ts_prev;
|
||||
select @result as 'Must be 1';
|
||||
Must be 1
|
||||
1
|
||||
set @@global.general_log = @save_general_log;
|
||||
set @@global.log_output = @save_log_output;
|
||||
set @@global.slave_net_timeout = @save_slave_net_timeout;
|
@ -0,0 +1 @@
|
||||
--net_read_timeout=5
|
81
mysql-test/suite/large_tests/t/rpl_slave_net_timeout.test
Normal file
81
mysql-test/suite/large_tests/t/rpl_slave_net_timeout.test
Normal file
@ -0,0 +1,81 @@
|
||||
#
|
||||
# Testing reconnecting by slave as specified by `slave_net_timeout'
|
||||
#
|
||||
# Bug #50296 Slave reconnects earlier than the prescribed slave_net_timeout value
|
||||
#
|
||||
--source include/have_csv.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
|
||||
# save global env
|
||||
connection master;
|
||||
set @save_general_log = @@global.general_log;
|
||||
set @save_log_output = @@global.log_output;
|
||||
|
||||
connection slave;
|
||||
set @save_slave_net_timeout = @@global.slave_net_timeout;
|
||||
|
||||
connection master;
|
||||
set @@global.general_log = ON;
|
||||
set @@global.log_output = 'table,file';
|
||||
|
||||
connection slave;
|
||||
--source include/stop_slave.inc
|
||||
--disable_warnings
|
||||
set @@global.slave_net_timeout = @@global.net_read_timeout * 2;
|
||||
--enable_warnings
|
||||
let $idle_time=`select @@global.slave_net_timeout * 2`;
|
||||
|
||||
#
|
||||
# if heartbeat is disabled then reconnecting to the idle master
|
||||
# should happen with `slave_net_timeout' period.
|
||||
# Since it's the real time that is measured, `slave_net_timeout'
|
||||
# merely guarantees that reconnecting can *not* happen earlier of a value specified.
|
||||
# That is there can't an exact estimate for how many time it will happen.
|
||||
#
|
||||
# The following lines verify that having idle master
|
||||
# for more than 2 * slave_net_timeout seconds and
|
||||
# slave.net_read_timeout < slave_net_timeout
|
||||
# won't cause reconnecting by the slave within at least
|
||||
# slave_net_timeout interval.
|
||||
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||
eval change master to master_host = '127.0.0.1',master_port = $MASTER_MYPORT,
|
||||
master_user = 'root', master_heartbeat_period = 0;
|
||||
|
||||
let $slave_net_timeout = `select @@global.slave_net_timeout`;
|
||||
|
||||
--source include/start_slave.inc
|
||||
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
eval select 'master is idle for ', sleep($idle_time);
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
|
||||
--source include/stop_slave.inc
|
||||
|
||||
# querying general-log
|
||||
|
||||
connection master;
|
||||
|
||||
# In particular the last reconnection timestamp must be greater or equal to
|
||||
# the previous one + slave_net_timeout
|
||||
|
||||
select event_time from (select event_time from mysql.general_log as t_1 where command_type like 'Connect' order by event_time desc limit 2) as t_2 order by event_time desc limit 1 into @ts_last;
|
||||
select event_time from (select event_time from mysql.general_log as t_1 where command_type like 'Connect' order by event_time desc limit 2) as t_2 order by event_time asc limit 1 into @ts_prev;
|
||||
|
||||
--disable_query_log
|
||||
eval select time_to_sec(@ts_last) - $slave_net_timeout >= time_to_sec(@ts_prev) into @result;
|
||||
--enable_query_log
|
||||
|
||||
select @result as 'Must be 1';
|
||||
|
||||
# cleanup
|
||||
|
||||
# restore global env
|
||||
connection master;
|
||||
set @@global.general_log = @save_general_log;
|
||||
set @@global.log_output = @save_log_output;
|
||||
connection slave;
|
||||
set @@global.slave_net_timeout = @save_slave_net_timeout;
|
||||
|
@ -11,3 +11,17 @@ create table test.t1 like performance_schema.EVENTS_WAITS_CURRENT;
|
||||
ERROR HY000: Invalid performance_schema usage.
|
||||
create table performance_schema.t1(a int);
|
||||
ERROR 42000: CREATE command denied to user 'root'@'localhost' for table 't1'
|
||||
drop table if exists test.ghost;
|
||||
create table test.ghost (a int, b int);
|
||||
alter table test.ghost add index index_a(a);
|
||||
alter table test.ghost add index index_b(b);
|
||||
insert into test.ghost values (1, 3);
|
||||
insert into test.ghost values (2, 4);
|
||||
select * from test.ghost;
|
||||
a b
|
||||
1 3
|
||||
2 4
|
||||
drop table test.ghost;
|
||||
select * from performance_schema.FILE_INSTANCES
|
||||
where file_name like "%ghost%";
|
||||
FILE_NAME EVENT_NAME OPEN_COUNT
|
||||
|
@ -55,3 +55,24 @@ create table test.t1 like performance_schema.EVENTS_WAITS_CURRENT;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
create table performance_schema.t1(a int);
|
||||
|
||||
#
|
||||
# Bug#51447 performance schema evil twin files
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists test.ghost;
|
||||
--enable_warnings
|
||||
|
||||
create table test.ghost (a int, b int);
|
||||
alter table test.ghost add index index_a(a);
|
||||
alter table test.ghost add index index_b(b);
|
||||
insert into test.ghost values (1, 3);
|
||||
insert into test.ghost values (2, 4);
|
||||
select * from test.ghost;
|
||||
|
||||
drop table test.ghost;
|
||||
|
||||
# Shoud return nothing
|
||||
select * from performance_schema.FILE_INSTANCES
|
||||
where file_name like "%ghost%";
|
||||
|
||||
|
@ -10,6 +10,7 @@ SELECT @start_session_value;
|
||||
SET @@global.optimizer_search_depth = 100;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect optimizer_search_depth value: '100'
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SET @@global.optimizer_search_depth = DEFAULT;
|
||||
SELECT @@global.optimizer_search_depth;
|
||||
@@global.optimizer_search_depth
|
||||
@ -17,6 +18,7 @@ SELECT @@global.optimizer_search_depth;
|
||||
SET @@session.optimizer_search_depth = 200;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect optimizer_search_depth value: '200'
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SET @@session.optimizer_search_depth = DEFAULT;
|
||||
SELECT @@session.optimizer_search_depth;
|
||||
@@session.optimizer_search_depth
|
||||
@ -44,6 +46,8 @@ SELECT @@global.optimizer_search_depth;
|
||||
@@global.optimizer_search_depth
|
||||
62
|
||||
SET @@global.optimizer_search_depth = 63;
|
||||
Warnings:
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SELECT @@global.optimizer_search_depth;
|
||||
@@global.optimizer_search_depth
|
||||
63
|
||||
@ -61,6 +65,8 @@ SELECT @@session.optimizer_search_depth;
|
||||
@@session.optimizer_search_depth
|
||||
62
|
||||
SET @@session.optimizer_search_depth = 63;
|
||||
Warnings:
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SELECT @@session.optimizer_search_depth;
|
||||
@@session.optimizer_search_depth
|
||||
63
|
||||
@ -68,6 +74,7 @@ SELECT @@session.optimizer_search_depth;
|
||||
SET @@global.optimizer_search_depth = 64;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect optimizer_search_depth value: '64'
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SELECT @@global.optimizer_search_depth;
|
||||
@@global.optimizer_search_depth
|
||||
63
|
||||
@ -80,6 +87,7 @@ SELECT @@global.optimizer_search_depth;
|
||||
SET @@global.optimizer_search_depth = 65536;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect optimizer_search_depth value: '65536'
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SELECT @@global.optimizer_search_depth;
|
||||
@@global.optimizer_search_depth
|
||||
63
|
||||
@ -96,6 +104,7 @@ SELECT @@global.optimizer_search_depth;
|
||||
SET @@session.optimizer_search_depth = 64;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect optimizer_search_depth value: '64'
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SELECT @@session.optimizer_search_depth;
|
||||
@@session.optimizer_search_depth
|
||||
63
|
||||
@ -110,6 +119,7 @@ ERROR 42000: Incorrect argument type to variable 'optimizer_search_depth'
|
||||
SET @@session.optimizer_search_depth = 65550;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect optimizer_search_depth value: '65550'
|
||||
Warning 1287 'optimizer-search-depth=63' is deprecated and will be removed in a future release. Please use a search depth less than 63 instead
|
||||
SELECT @@session.optimizer_search_depth;
|
||||
@@session.optimizer_search_depth
|
||||
63
|
||||
|
@ -224,3 +224,103 @@ commit;
|
||||
--echo # which was already released by commit.
|
||||
unlock tables;
|
||||
drop tables t1, t2;
|
||||
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Tests for WL#5000 FLUSH TABLES|TABLE table_list WITH READ LOCK
|
||||
--echo #
|
||||
--echo # I. Check the incompatible changes in the grammar.
|
||||
--echo #
|
||||
--error ER_PARSE_ERROR
|
||||
flush tables with read lock, hosts;
|
||||
--error ER_PARSE_ERROR
|
||||
flush privileges, tables;
|
||||
--error ER_PARSE_ERROR
|
||||
flush privileges, tables with read lock;
|
||||
--error ER_PARSE_ERROR
|
||||
flush privileges, tables;
|
||||
--error ER_PARSE_ERROR
|
||||
flush tables with read lock, tables;
|
||||
show tables;
|
||||
--echo #
|
||||
--echo # II. Check the allowed syntax.
|
||||
--echo #
|
||||
--disable_warnings
|
||||
drop table if exists t1, t2, t3;
|
||||
--enable_warnings
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
create table t3 (a int);
|
||||
lock table t1 read, t2 read;
|
||||
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
||||
flush tables with read lock;
|
||||
unlock tables;
|
||||
flush tables with read lock;
|
||||
flush tables t1, t2 with read lock;
|
||||
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
||||
flush tables t1, t2 with read lock;
|
||||
--error ER_LOCK_OR_ACTIVE_TRANSACTION
|
||||
flush tables with read lock;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
select * from t3;
|
||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||
insert into t1 (a) values (1);
|
||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||
insert into t2 (a) values (1);
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
insert into t3 (a) values (1);
|
||||
--error ER_NO_SUCH_TABLE
|
||||
lock table no_such_table read;
|
||||
--echo #
|
||||
--echo # We implicitly left the locked tables
|
||||
--echo # mode but still have the read lock.
|
||||
--echo #
|
||||
--error ER_CANT_UPDATE_WITH_READLOCK
|
||||
insert into t2 (a) values (1);
|
||||
unlock tables;
|
||||
insert into t1 (a) values (1);
|
||||
insert into t2 (a) values (1);
|
||||
flush table t1, t2 with read lock;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
select * from t3;
|
||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||
insert into t1 (a) values (2);
|
||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||
insert into t2 (a) values (2);
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
insert into t3 (a) values (2);
|
||||
--error ER_NO_SUCH_TABLE
|
||||
lock table no_such_table read;
|
||||
insert into t3 (a) values (2);
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # III. Concurrent tests.
|
||||
--echo #
|
||||
connect (con1,localhost,root,,);
|
||||
--echo # --> connection default
|
||||
--echo #
|
||||
--echo # Check that flush tables <list> with read lock
|
||||
--echo # does not affect non-locked tables.
|
||||
connection default;
|
||||
--echo #
|
||||
flush tables t1 with read lock;
|
||||
--echo # --> connection con1;
|
||||
connection con1;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
insert into t2 (a) values (3);
|
||||
--echo # --> connection default;
|
||||
connection default;
|
||||
unlock tables;
|
||||
--echo # --> connection con1
|
||||
connection con1;
|
||||
disconnect con1;
|
||||
--source include/wait_until_disconnected.inc
|
||||
connection default;
|
||||
drop table t1, t2, t3;
|
||||
|
@ -16,7 +16,8 @@
|
||||
/* Synchronization - readers / writer thread locks */
|
||||
|
||||
#include "mysys_priv.h"
|
||||
#if defined(THREAD) && !defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && !defined(HAVE_RWLOCK_INIT)
|
||||
#if defined(THREAD)
|
||||
#if defined(NEED_MY_RW_LOCK)
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
@ -58,7 +59,7 @@
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused)))
|
||||
int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
|
||||
{
|
||||
pthread_condattr_t cond_attr;
|
||||
|
||||
@ -70,12 +71,14 @@ int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused)))
|
||||
|
||||
rwp->state = 0;
|
||||
rwp->waiters = 0;
|
||||
/* If attribute argument is NULL use default value - prefer writers. */
|
||||
rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int my_rwlock_destroy(rw_lock_t *rwp)
|
||||
int my_rw_destroy(my_rw_lock_t *rwp)
|
||||
{
|
||||
pthread_mutex_destroy( &rwp->lock );
|
||||
pthread_cond_destroy( &rwp->readers );
|
||||
@ -84,12 +87,13 @@ int my_rwlock_destroy(rw_lock_t *rwp)
|
||||
}
|
||||
|
||||
|
||||
int my_rw_rdlock(rw_lock_t *rwp)
|
||||
int my_rw_rdlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
|
||||
/* active or queued writers */
|
||||
while (( rwp->state < 0 ) || rwp->waiters)
|
||||
while (( rwp->state < 0 ) ||
|
||||
(rwp->waiters && ! rwp->prefer_readers))
|
||||
pthread_cond_wait( &rwp->readers, &rwp->lock);
|
||||
|
||||
rwp->state++;
|
||||
@ -97,11 +101,12 @@ int my_rw_rdlock(rw_lock_t *rwp)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int my_rw_tryrdlock(rw_lock_t *rwp)
|
||||
int my_rw_tryrdlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
int res;
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
if ((rwp->state < 0 ) || rwp->waiters)
|
||||
if ((rwp->state < 0 ) ||
|
||||
(rwp->waiters && ! rwp->prefer_readers))
|
||||
res= EBUSY; /* Can't get lock */
|
||||
else
|
||||
{
|
||||
@ -113,7 +118,7 @@ int my_rw_tryrdlock(rw_lock_t *rwp)
|
||||
}
|
||||
|
||||
|
||||
int my_rw_wrlock(rw_lock_t *rwp)
|
||||
int my_rw_wrlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
rwp->waiters++; /* another writer queued */
|
||||
@ -127,7 +132,7 @@ int my_rw_wrlock(rw_lock_t *rwp)
|
||||
}
|
||||
|
||||
|
||||
int my_rw_trywrlock(rw_lock_t *rwp)
|
||||
int my_rw_trywrlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
int res;
|
||||
pthread_mutex_lock(&rwp->lock);
|
||||
@ -143,7 +148,7 @@ int my_rw_trywrlock(rw_lock_t *rwp)
|
||||
}
|
||||
|
||||
|
||||
int my_rw_unlock(rw_lock_t *rwp)
|
||||
int my_rw_unlock(my_rw_lock_t *rwp)
|
||||
{
|
||||
DBUG_PRINT("rw_unlock",
|
||||
("state: %d waiters: %d", rwp->state, rwp->waiters));
|
||||
@ -160,7 +165,8 @@ int my_rw_unlock(rw_lock_t *rwp)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( --rwp->state == 0 ) /* no more readers */
|
||||
if ( --rwp->state == 0 && /* no more readers */
|
||||
rwp->waiters)
|
||||
pthread_cond_signal( &rwp->writers );
|
||||
}
|
||||
|
||||
@ -168,4 +174,30 @@ int my_rw_unlock(rw_lock_t *rwp)
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int rw_pr_init(struct st_my_rw_lock_t *rwlock)
|
||||
{
|
||||
my_bool prefer_readers_attr= TRUE;
|
||||
return my_rw_init(rwlock, &prefer_readers_attr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
We are on system which has native read/write locks which support
|
||||
preferring of readers.
|
||||
*/
|
||||
|
||||
int rw_pr_init(rw_pr_lock_t *rwlock)
|
||||
{
|
||||
pthread_rwlockattr_t rwlock_attr;
|
||||
|
||||
pthread_rwlockattr_init(&rwlock_attr);
|
||||
pthread_rwlockattr_setkind_np(&rwlock_attr, PTHREAD_RWLOCK_PREFER_READER_NP);
|
||||
pthread_rwlock_init(rwlock, NULL);
|
||||
pthread_rwlockattr_destroy(&rwlock_attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(NEED_MY_RW_LOCK) */
|
||||
#endif /* defined(THREAD) */
|
||||
|
@ -56,6 +56,8 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory]
|
||||
-h, --host=# hostname for local server when connecting over TCP/IP
|
||||
-P, --port=# port to use when connecting to local server with TCP/IP
|
||||
-S, --socket=# socket to use when connecting to local server
|
||||
--old_server connect to old MySQL-server (before v5.5) which
|
||||
doesn't have FLUSH TABLES WITH READ LOCK fully implemented.
|
||||
|
||||
--allowold don\'t abort if target dir already exists (rename it _old)
|
||||
--addtodest don\'t rename target dir if it exists, just add files to it
|
||||
@ -103,6 +105,7 @@ GetOptions( \%opt,
|
||||
"password|p=s",
|
||||
"port|P=s",
|
||||
"socket|S=s",
|
||||
"old_server",
|
||||
"allowold!",
|
||||
"keepold!",
|
||||
"addtodest!",
|
||||
@ -441,21 +444,37 @@ if ( $opt{checkpoint} || $opt{record_log_pos} ) {
|
||||
my $hc_started = time; # count from time lock is granted
|
||||
|
||||
if ( $opt{dryrun} ) {
|
||||
print "LOCK TABLES $hc_locks\n";
|
||||
print "FLUSH TABLES /*!32323 $hc_tables */\n";
|
||||
if ( $opt{old_server} ) {
|
||||
print "LOCK TABLES $hc_locks\n";
|
||||
print "FLUSH TABLES /*!32323 $hc_tables */\n";
|
||||
}
|
||||
else {
|
||||
print "FLUSH TABLES $hc_tables WITH READ LOCK\n";
|
||||
}
|
||||
|
||||
print "FLUSH LOGS\n" if ( $opt{flushlog} );
|
||||
print "RESET MASTER\n" if ( $opt{resetmaster} );
|
||||
print "RESET SLAVE\n" if ( $opt{resetslave} );
|
||||
}
|
||||
else {
|
||||
my $start = time;
|
||||
$dbh->do("LOCK TABLES $hc_locks");
|
||||
printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet};
|
||||
$hc_started = time; # count from time lock is granted
|
||||
if ( $opt{old_server} ) {
|
||||
$dbh->do("LOCK TABLES $hc_locks");
|
||||
printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet};
|
||||
$hc_started = time; # count from time lock is granted
|
||||
|
||||
# flush tables to make on-disk copy up to date
|
||||
$start = time;
|
||||
$dbh->do("FLUSH TABLES /*!32323 $hc_tables */");
|
||||
# flush tables to make on-disk copy up to date
|
||||
$start = time;
|
||||
$dbh->do("FLUSH TABLES /*!32323 $hc_tables */");
|
||||
}
|
||||
else {
|
||||
$dbh->do("FLUSH TABLES $hc_tables WITH READ LOCK");
|
||||
printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet};
|
||||
$hc_started = time; # count from time lock is granted
|
||||
|
||||
# flush tables to make on-disk copy up to date
|
||||
$start = time;
|
||||
}
|
||||
printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet};
|
||||
$dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} );
|
||||
$dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} );
|
||||
@ -975,6 +994,10 @@ when using the --host option.
|
||||
|
||||
UNIX domain socket to use when connecting to local server.
|
||||
|
||||
=item --old_server
|
||||
|
||||
Use old server (pre v5.5) commands.
|
||||
|
||||
=item --noindices
|
||||
|
||||
Don\'t include index files in copy. Only up to the first 2048 bytes
|
||||
|
99
sql/mdl.cc
99
sql/mdl.cc
@ -148,10 +148,37 @@ public:
|
||||
/**
|
||||
Read-write lock protecting this lock context.
|
||||
|
||||
TODO/FIXME: Replace with RW-lock which will prefer readers
|
||||
on all platforms and not only on Linux.
|
||||
@note The fact that we use read-write lock prefers readers here is
|
||||
important as deadlock detector won't work correctly otherwise.
|
||||
|
||||
For example, imagine that we have following waiters graph:
|
||||
|
||||
ctxA -> obj1 -> ctxB -> obj1 -|
|
||||
^ |
|
||||
|----------------------------|
|
||||
|
||||
and both ctxA and ctxB start deadlock detection process:
|
||||
|
||||
ctxA read-locks obj1 ctxB read-locks obj2
|
||||
ctxA goes deeper ctxB goes deeper
|
||||
|
||||
Now ctxC comes in who wants to start waiting on obj1, also
|
||||
ctxD comes in who wants to start waiting on obj2.
|
||||
|
||||
ctxC tries to write-lock obj1 ctxD tries to write-lock obj2
|
||||
ctxC is blocked ctxD is blocked
|
||||
|
||||
Now ctxA and ctxB resume their search:
|
||||
|
||||
ctxA tries to read-lock obj2 ctxB tries to read-lock obj1
|
||||
|
||||
If m_rwlock prefers writes (or fair) both ctxA and ctxB would be
|
||||
blocked because of pending write locks from ctxD and ctxC
|
||||
correspondingly. Thus we will get a deadlock in deadlock detector.
|
||||
If m_wrlock prefers readers (actually ignoring pending writers is
|
||||
enough) ctxA and ctxB will continue and no deadlock will occur.
|
||||
*/
|
||||
rw_lock_t m_rwlock;
|
||||
rw_pr_lock_t m_rwlock;
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
@ -213,12 +240,12 @@ public:
|
||||
m_ref_release(0),
|
||||
m_is_destroyed(FALSE)
|
||||
{
|
||||
my_rwlock_init(&m_rwlock, NULL);
|
||||
rw_pr_init(&m_rwlock);
|
||||
}
|
||||
|
||||
virtual ~MDL_lock()
|
||||
{
|
||||
rwlock_destroy(&m_rwlock);
|
||||
rw_pr_destroy(&m_rwlock);
|
||||
}
|
||||
inline static void destroy(MDL_lock *lock);
|
||||
public:
|
||||
@ -480,7 +507,7 @@ bool MDL_map::move_from_hash_to_lock_mutex(MDL_lock *lock)
|
||||
lock->m_ref_usage++;
|
||||
mysql_mutex_unlock(&m_mutex);
|
||||
|
||||
rw_wrlock(&lock->m_rwlock);
|
||||
rw_pr_wrlock(&lock->m_rwlock);
|
||||
lock->m_ref_release++;
|
||||
if (unlikely(lock->m_is_destroyed))
|
||||
{
|
||||
@ -495,7 +522,7 @@ bool MDL_map::move_from_hash_to_lock_mutex(MDL_lock *lock)
|
||||
*/
|
||||
uint ref_usage= lock->m_ref_usage;
|
||||
uint ref_release= lock->m_ref_release;
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
if (ref_usage == ref_release)
|
||||
MDL_lock::destroy(lock);
|
||||
return TRUE;
|
||||
@ -538,7 +565,7 @@ void MDL_map::remove(MDL_lock *lock)
|
||||
lock->m_is_destroyed= TRUE;
|
||||
ref_usage= lock->m_ref_usage;
|
||||
ref_release= lock->m_ref_release;
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
mysql_mutex_unlock(&m_mutex);
|
||||
if (ref_usage == ref_release)
|
||||
MDL_lock::destroy(lock);
|
||||
@ -559,7 +586,7 @@ MDL_context::MDL_context()
|
||||
m_deadlock_weight(0),
|
||||
m_signal(NO_WAKE_UP)
|
||||
{
|
||||
my_rwlock_init(&m_waiting_for_lock, NULL);
|
||||
rw_pr_init(&m_waiting_for_lock);
|
||||
mysql_mutex_init(NULL /* pfs key */, &m_signal_lock, NULL);
|
||||
mysql_cond_init(NULL /* pfs key */, &m_signal_cond, NULL);
|
||||
}
|
||||
@ -581,7 +608,7 @@ void MDL_context::destroy()
|
||||
{
|
||||
DBUG_ASSERT(m_tickets.is_empty());
|
||||
|
||||
rwlock_destroy(&m_waiting_for_lock);
|
||||
rw_pr_destroy(&m_waiting_for_lock);
|
||||
mysql_mutex_destroy(&m_signal_lock);
|
||||
mysql_cond_destroy(&m_signal_cond);
|
||||
}
|
||||
@ -1071,7 +1098,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
|
||||
|
||||
void MDL_lock::remove_ticket(Ticket_list MDL_lock::*list, MDL_ticket *ticket)
|
||||
{
|
||||
rw_wrlock(&m_rwlock);
|
||||
rw_pr_wrlock(&m_rwlock);
|
||||
(this->*list).remove_ticket(ticket);
|
||||
if (is_empty())
|
||||
mdl_locks.remove(this);
|
||||
@ -1082,7 +1109,7 @@ void MDL_lock::remove_ticket(Ticket_list MDL_lock::*list, MDL_ticket *ticket)
|
||||
which now might be able to do it. Wake them up!
|
||||
*/
|
||||
wake_up_waiters();
|
||||
rw_unlock(&m_rwlock);
|
||||
rw_pr_unlock(&m_rwlock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1102,9 +1129,9 @@ bool MDL_lock::has_pending_conflicting_lock(enum_mdl_type type)
|
||||
|
||||
mysql_mutex_assert_not_owner(&LOCK_open);
|
||||
|
||||
rw_rdlock(&m_rwlock);
|
||||
rw_pr_rdlock(&m_rwlock);
|
||||
result= (m_waiting.bitmap() & incompatible_granted_types_bitmap()[type]);
|
||||
rw_unlock(&m_rwlock);
|
||||
rw_pr_unlock(&m_rwlock);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1298,7 +1325,7 @@ MDL_context::try_acquire_lock(MDL_request *mdl_request)
|
||||
{
|
||||
ticket->m_lock= lock;
|
||||
lock->m_granted.add_ticket(ticket);
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
|
||||
m_tickets.push_front(ticket);
|
||||
|
||||
@ -1308,7 +1335,7 @@ MDL_context::try_acquire_lock(MDL_request *mdl_request)
|
||||
{
|
||||
/* We can't get here if we allocated a new lock. */
|
||||
DBUG_ASSERT(! lock->is_empty());
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
MDL_ticket::destroy(ticket);
|
||||
}
|
||||
|
||||
@ -1349,9 +1376,9 @@ MDL_context::clone_ticket(MDL_request *mdl_request)
|
||||
ticket->m_lock= mdl_request->ticket->m_lock;
|
||||
mdl_request->ticket= ticket;
|
||||
|
||||
rw_wrlock(&ticket->m_lock->m_rwlock);
|
||||
rw_pr_wrlock(&ticket->m_lock->m_rwlock);
|
||||
ticket->m_lock->m_granted.add_ticket(ticket);
|
||||
rw_unlock(&ticket->m_lock->m_rwlock);
|
||||
rw_pr_unlock(&ticket->m_lock->m_rwlock);
|
||||
|
||||
m_tickets.push_front(ticket);
|
||||
|
||||
@ -1457,7 +1484,7 @@ bool MDL_context::acquire_lock_impl(MDL_request *mdl_request,
|
||||
if (ticket->is_upgradable_or_exclusive())
|
||||
lock->notify_shared_locks(this);
|
||||
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
|
||||
set_deadlock_weight(mdl_request->get_deadlock_weight());
|
||||
will_wait_for(ticket);
|
||||
@ -1492,7 +1519,7 @@ bool MDL_context::acquire_lock_impl(MDL_request *mdl_request,
|
||||
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
rw_wrlock(&lock->m_rwlock);
|
||||
rw_pr_wrlock(&lock->m_rwlock);
|
||||
}
|
||||
|
||||
lock->m_waiting.remove_ticket(ticket);
|
||||
@ -1502,7 +1529,7 @@ bool MDL_context::acquire_lock_impl(MDL_request *mdl_request,
|
||||
(*lock->cached_object_release_hook)(lock->cached_object);
|
||||
lock->cached_object= NULL;
|
||||
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
|
||||
m_tickets.push_front(ticket);
|
||||
|
||||
@ -1647,7 +1674,7 @@ MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
|
||||
is_new_ticket= ! has_lock(mdl_svp, mdl_xlock_request.ticket);
|
||||
|
||||
/* Merge the acquired and the original lock. @todo: move to a method. */
|
||||
rw_wrlock(&mdl_ticket->m_lock->m_rwlock);
|
||||
rw_pr_wrlock(&mdl_ticket->m_lock->m_rwlock);
|
||||
if (is_new_ticket)
|
||||
mdl_ticket->m_lock->m_granted.remove_ticket(mdl_xlock_request.ticket);
|
||||
/*
|
||||
@ -1659,7 +1686,7 @@ MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
|
||||
mdl_ticket->m_type= MDL_EXCLUSIVE;
|
||||
mdl_ticket->m_lock->m_granted.add_ticket(mdl_ticket);
|
||||
|
||||
rw_unlock(&mdl_ticket->m_lock->m_rwlock);
|
||||
rw_pr_unlock(&mdl_ticket->m_lock->m_rwlock);
|
||||
|
||||
if (is_new_ticket)
|
||||
{
|
||||
@ -1677,7 +1704,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
MDL_ticket *ticket;
|
||||
bool result= FALSE;
|
||||
|
||||
rw_rdlock(&m_rwlock);
|
||||
rw_pr_rdlock(&m_rwlock);
|
||||
|
||||
Ticket_iterator granted_it(m_granted);
|
||||
Ticket_iterator waiting_it(m_waiting);
|
||||
@ -1729,7 +1756,7 @@ bool MDL_lock::find_deadlock(MDL_ticket *waiting_ticket,
|
||||
}
|
||||
|
||||
end:
|
||||
rw_unlock(&m_rwlock);
|
||||
rw_pr_unlock(&m_rwlock);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1738,7 +1765,7 @@ bool MDL_context::find_deadlock(Deadlock_detection_context *deadlock_ctx)
|
||||
{
|
||||
bool result= FALSE;
|
||||
|
||||
rw_rdlock(&m_waiting_for_lock);
|
||||
rw_pr_rdlock(&m_waiting_for_lock);
|
||||
|
||||
if (m_waiting_for)
|
||||
{
|
||||
@ -1767,14 +1794,14 @@ bool MDL_context::find_deadlock(Deadlock_detection_context *deadlock_ctx)
|
||||
deadlock_ctx->victim= this;
|
||||
else if (deadlock_ctx->victim->m_deadlock_weight >= m_deadlock_weight)
|
||||
{
|
||||
rw_unlock(&deadlock_ctx->victim->m_waiting_for_lock);
|
||||
rw_pr_unlock(&deadlock_ctx->victim->m_waiting_for_lock);
|
||||
deadlock_ctx->victim= this;
|
||||
}
|
||||
else
|
||||
rw_unlock(&m_waiting_for_lock);
|
||||
rw_pr_unlock(&m_waiting_for_lock);
|
||||
}
|
||||
else
|
||||
rw_unlock(&m_waiting_for_lock);
|
||||
rw_pr_unlock(&m_waiting_for_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1800,7 +1827,7 @@ bool MDL_context::find_deadlock()
|
||||
if (deadlock_ctx.victim != this)
|
||||
{
|
||||
deadlock_ctx.victim->awake(VICTIM_WAKE_UP);
|
||||
rw_unlock(&deadlock_ctx.victim->m_waiting_for_lock);
|
||||
rw_pr_unlock(&deadlock_ctx.victim->m_waiting_for_lock);
|
||||
/*
|
||||
After adding new arc to waiting graph we found that it participates
|
||||
in some loop (i.e. there is a deadlock). We decided to destroy this
|
||||
@ -1813,7 +1840,7 @@ bool MDL_context::find_deadlock()
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(&deadlock_ctx.victim->m_waiting_for_lock == &m_waiting_for_lock);
|
||||
rw_unlock(&deadlock_ctx.victim->m_waiting_for_lock);
|
||||
rw_pr_unlock(&deadlock_ctx.victim->m_waiting_for_lock);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@ -1870,14 +1897,14 @@ MDL_context::wait_for_lock(MDL_request *mdl_request, ulong lock_wait_timeout)
|
||||
|
||||
if (lock->can_grant_lock(mdl_request->type, this))
|
||||
{
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MDL_ticket *pending_ticket;
|
||||
if (! (pending_ticket= MDL_ticket::create(this, mdl_request->type)))
|
||||
{
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1886,7 +1913,7 @@ MDL_context::wait_for_lock(MDL_request *mdl_request, ulong lock_wait_timeout)
|
||||
lock->m_waiting.add_ticket(pending_ticket);
|
||||
|
||||
wait_reset();
|
||||
rw_unlock(&lock->m_rwlock);
|
||||
rw_pr_unlock(&lock->m_rwlock);
|
||||
|
||||
set_deadlock_weight(MDL_DEADLOCK_WEIGHT_DML);
|
||||
will_wait_for(pending_ticket);
|
||||
@ -2037,7 +2064,7 @@ void MDL_ticket::downgrade_exclusive_lock(enum_mdl_type type)
|
||||
if (m_type != MDL_EXCLUSIVE)
|
||||
return;
|
||||
|
||||
rw_wrlock(&m_lock->m_rwlock);
|
||||
rw_pr_wrlock(&m_lock->m_rwlock);
|
||||
/*
|
||||
To update state of MDL_lock object correctly we need to temporarily
|
||||
exclude ticket from the granted queue and then include it back.
|
||||
@ -2046,7 +2073,7 @@ void MDL_ticket::downgrade_exclusive_lock(enum_mdl_type type)
|
||||
m_type= type;
|
||||
m_lock->m_granted.add_ticket(this);
|
||||
m_lock->wake_up_waiters();
|
||||
rw_unlock(&m_lock->m_rwlock);
|
||||
rw_pr_unlock(&m_lock->m_rwlock);
|
||||
}
|
||||
|
||||
|
||||
|
15
sql/mdl.h
15
sql/mdl.h
@ -624,10 +624,11 @@ private:
|
||||
/**
|
||||
Read-write lock protecting m_waiting_for member.
|
||||
|
||||
TODO/FIXME: Replace with RW-lock which will prefer readers
|
||||
on all platforms and not only on Linux.
|
||||
@note The fact that this read-write lock prefers readers is
|
||||
important as deadlock detector won't work correctly
|
||||
otherwise. @sa Comment for MDL_lock::m_rwlock.
|
||||
*/
|
||||
rw_lock_t m_waiting_for_lock;
|
||||
rw_pr_lock_t m_waiting_for_lock;
|
||||
MDL_ticket *m_waiting_for;
|
||||
uint m_deadlock_weight;
|
||||
/**
|
||||
@ -651,9 +652,9 @@ private:
|
||||
|
||||
void will_wait_for(MDL_ticket *pending_ticket)
|
||||
{
|
||||
rw_wrlock(&m_waiting_for_lock);
|
||||
rw_pr_wrlock(&m_waiting_for_lock);
|
||||
m_waiting_for= pending_ticket;
|
||||
rw_unlock(&m_waiting_for_lock);
|
||||
rw_pr_unlock(&m_waiting_for_lock);
|
||||
}
|
||||
|
||||
void set_deadlock_weight(uint weight)
|
||||
@ -669,9 +670,9 @@ private:
|
||||
|
||||
void stop_waiting()
|
||||
{
|
||||
rw_wrlock(&m_waiting_for_lock);
|
||||
rw_pr_wrlock(&m_waiting_for_lock);
|
||||
m_waiting_for= NULL;
|
||||
rw_unlock(&m_waiting_for_lock);
|
||||
rw_pr_unlock(&m_waiting_for_lock);
|
||||
}
|
||||
|
||||
void wait_reset()
|
||||
|
@ -1965,7 +1965,8 @@ extern ulong slow_launch_threads, slow_launch_time;
|
||||
extern ulong table_cache_size, table_def_size;
|
||||
extern MYSQL_PLUGIN_IMPORT ulong max_connections;
|
||||
extern ulong max_connect_errors, connect_timeout;
|
||||
extern ulong slave_net_timeout, slave_trans_retries;
|
||||
extern ulong slave_trans_retries;
|
||||
extern uint slave_net_timeout;
|
||||
extern ulong what_to_log,flush_time;
|
||||
extern ulong query_buff_size;
|
||||
extern ulong max_prepared_stmt_count, prepared_stmt_count;
|
||||
|
@ -464,7 +464,8 @@ ulong table_cache_size, table_def_size;
|
||||
ulong what_to_log;
|
||||
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
|
||||
ulong open_files_limit, max_binlog_size, max_relay_log_size;
|
||||
ulong slave_net_timeout, slave_trans_retries;
|
||||
ulong slave_trans_retries;
|
||||
uint slave_net_timeout;
|
||||
uint slave_exec_mode_options;
|
||||
ulonglong slave_type_conversions_options;
|
||||
ulong thread_cache_size=0, thread_pool_size= 0;
|
||||
|
116
sql/sql_parse.cc
116
sql/sql_parse.cc
@ -1587,6 +1587,113 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Implementation of FLUSH TABLES <table_list> WITH READ LOCK.
|
||||
|
||||
In brief: take exclusive locks, expel tables from the table
|
||||
cache, reopen the tables, enter the 'LOCKED TABLES' mode,
|
||||
downgrade the locks.
|
||||
|
||||
Required privileges
|
||||
-------------------
|
||||
Since the statement implicitly enters LOCK TABLES mode,
|
||||
it requires LOCK TABLES privilege on every table.
|
||||
But since the rest of FLUSH commands require
|
||||
the global RELOAD_ACL, it also requires RELOAD_ACL.
|
||||
|
||||
Compatibility with the global read lock
|
||||
---------------------------------------
|
||||
We don't wait for the GRL, since neither the
|
||||
5.1 combination that this new statement is intended to
|
||||
replace (LOCK TABLE <list> WRITE; FLUSH TABLES;),
|
||||
nor FLUSH TABLES WITH READ LOCK do.
|
||||
@todo: this is not implemented, Dmitry disagrees.
|
||||
Currently we wait for GRL in another connection,
|
||||
but are compatible with a GRL in our own connection.
|
||||
|
||||
Behaviour under LOCK TABLES
|
||||
---------------------------
|
||||
Bail out: i.e. don't perform an implicit UNLOCK TABLES.
|
||||
This is not consistent with LOCK TABLES statement, but is
|
||||
in line with behaviour of FLUSH TABLES WITH READ LOCK, and we
|
||||
try to not introduce any new statements with implicit
|
||||
semantics.
|
||||
|
||||
Compatibility with parallel updates
|
||||
-----------------------------------
|
||||
As a result, we will wait for all open transactions
|
||||
against the tables to complete. After the lock downgrade,
|
||||
new transactions will be able to read the tables, but not
|
||||
write to them.
|
||||
|
||||
Differences from FLUSH TABLES <list>
|
||||
-------------------------------------
|
||||
- you can't flush WITH READ LOCK a non-existent table
|
||||
- you can't flush WITH READ LOCK under LOCK TABLES
|
||||
- currently incompatible with the GRL (@todo: fix)
|
||||
*/
|
||||
|
||||
static bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
|
||||
{
|
||||
Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
|
||||
TABLE_LIST *table_list;
|
||||
|
||||
/*
|
||||
This is called from SQLCOM_FLUSH, the transaction has
|
||||
been committed implicitly.
|
||||
*/
|
||||
|
||||
/* RELOAD_ACL is checked by the caller. Check table-level privileges. */
|
||||
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto error;
|
||||
|
||||
if (thd->locked_tables_mode)
|
||||
{
|
||||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
@todo: Since lock_table_names() acquires a global IX
|
||||
lock, this actually waits for a GRL in another connection.
|
||||
We are thus introducing an incompatibility.
|
||||
Do nothing for now, since not taking a global IX violates
|
||||
current internal MDL asserts, fix after discussing with
|
||||
Dmitry.
|
||||
*/
|
||||
if (lock_table_names(thd, all_tables))
|
||||
goto error;
|
||||
|
||||
if (open_and_lock_tables(thd, all_tables, FALSE,
|
||||
MYSQL_OPEN_HAS_MDL_LOCK,
|
||||
&lock_tables_prelocking_strategy) ||
|
||||
thd->locked_tables_list.init_locked_tables(thd))
|
||||
{
|
||||
close_thread_tables(thd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
Downgrade the exclusive locks.
|
||||
Use MDL_SHARED_NO_WRITE as the intended
|
||||
post effect of this call is identical
|
||||
to LOCK TABLES <...> READ, and we didn't use
|
||||
thd->in_lock_talbes and thd->sql_command= SQLCOM_LOCK_TABLES
|
||||
hacks to enter the LTM.
|
||||
@todo: release the global IX lock here!!!
|
||||
*/
|
||||
for (table_list= all_tables; table_list;
|
||||
table_list= table_list->next_global)
|
||||
table_list->mdl_request.ticket->downgrade_exclusive_lock(MDL_SHARED_NO_WRITE);
|
||||
|
||||
return FALSE;
|
||||
|
||||
error:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read query from packet and store in thd->query.
|
||||
Used in COM_QUERY and COM_STMT_PREPARE.
|
||||
@ -3728,9 +3835,18 @@ end_with_restore_list:
|
||||
case SQLCOM_FLUSH:
|
||||
{
|
||||
bool write_to_binlog;
|
||||
|
||||
if (check_global_access(thd,RELOAD_ACL))
|
||||
goto error;
|
||||
|
||||
if (first_table && lex->type & REFRESH_READ_LOCK)
|
||||
{
|
||||
if (flush_tables_with_read_lock(thd, all_tables))
|
||||
goto error;
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
reload_acl_and_cache() will tell us if we are allowed to write to the
|
||||
binlog or not.
|
||||
|
@ -767,10 +767,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
|
||||
%pure_parser /* We have threads */
|
||||
/*
|
||||
Currently there are 169 shift/reduce conflicts.
|
||||
Currently there are 168 shift/reduce conflicts.
|
||||
We should not introduce new conflicts any more.
|
||||
*/
|
||||
%expect 169
|
||||
%expect 168
|
||||
|
||||
/*
|
||||
Comments for TOKENS.
|
||||
@ -1554,6 +1554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
opt_column_list grant_privileges grant_ident grant_list grant_option
|
||||
object_privilege object_privilege_list user_list rename_list
|
||||
clear_privileges flush_options flush_option
|
||||
opt_with_read_lock flush_options_list
|
||||
equal optional_braces
|
||||
opt_mi_check_type opt_to mi_check_types normal_join
|
||||
table_to_table_list table_to_table opt_table_list opt_as
|
||||
@ -11095,17 +11096,27 @@ flush:
|
||||
;
|
||||
|
||||
flush_options:
|
||||
flush_options ',' flush_option
|
||||
| flush_option
|
||||
;
|
||||
|
||||
flush_option:
|
||||
table_or_tables
|
||||
{ Lex->type|= REFRESH_TABLES; }
|
||||
opt_table_list {}
|
||||
| TABLES WITH READ_SYM LOCK_SYM
|
||||
{ Lex->type|= REFRESH_TABLES | REFRESH_READ_LOCK; }
|
||||
| ERROR_SYM LOGS_SYM
|
||||
opt_with_read_lock {}
|
||||
| flush_options_list
|
||||
;
|
||||
|
||||
opt_with_read_lock:
|
||||
/* empty */ {}
|
||||
| WITH READ_SYM LOCK_SYM
|
||||
{ Lex->type|= REFRESH_READ_LOCK; }
|
||||
;
|
||||
|
||||
flush_options_list:
|
||||
flush_options_list ',' flush_option
|
||||
| flush_option
|
||||
{}
|
||||
;
|
||||
|
||||
flush_option:
|
||||
ERROR_SYM LOGS_SYM
|
||||
{ Lex->type|= REFRESH_ERROR_LOG; }
|
||||
| ENGINE_SYM LOGS_SYM
|
||||
{ Lex->type|= REFRESH_ENGINE_LOG; }
|
||||
|
@ -1305,6 +1305,17 @@ static Sys_var_ulong Sys_optimizer_prune_level(
|
||||
SESSION_VAR(optimizer_prune_level), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, 1), DEFAULT(1), BLOCK_SIZE(1));
|
||||
|
||||
/** Warns about deprecated value 63 */
|
||||
static bool fix_optimizer_search_depth(sys_var *self, THD *thd,
|
||||
enum_var_type type)
|
||||
{
|
||||
SV *sv= type == OPT_GLOBAL ? &global_system_variables : &thd->variables;
|
||||
if (sv->optimizer_search_depth == MAX_TABLES+2)
|
||||
WARN_DEPRECATED(thd, 6, 0, "optimizer-search-depth=63",
|
||||
"a search depth less than 63");
|
||||
return false;
|
||||
}
|
||||
|
||||
static Sys_var_ulong Sys_optimizer_search_depth(
|
||||
"optimizer_search_depth",
|
||||
"Maximum depth of search performed by the query optimizer. Values "
|
||||
@ -1313,10 +1324,12 @@ static Sys_var_ulong Sys_optimizer_search_depth(
|
||||
"than the number of tables in a relation result in faster "
|
||||
"optimization, but may produce very bad query plans. If set to 0, "
|
||||
"the system will automatically pick a reasonable value; if set to "
|
||||
"63, the optimizer will switch to the original find_best search"
|
||||
"(used for testing/comparison)",
|
||||
"63, the optimizer will switch to the original find_best search. "
|
||||
"NOTE: The value 63 and its associated behaviour is deprecated",
|
||||
SESSION_VAR(optimizer_search_depth), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, MAX_TABLES+2), DEFAULT(MAX_TABLES+1), BLOCK_SIZE(1));
|
||||
VALID_RANGE(0, MAX_TABLES+2), DEFAULT(MAX_TABLES+1), BLOCK_SIZE(1),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
|
||||
ON_UPDATE(fix_optimizer_search_depth));
|
||||
|
||||
static const char *optimizer_switch_names[]=
|
||||
{
|
||||
@ -2795,7 +2808,7 @@ static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type)
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
return false;
|
||||
}
|
||||
static Sys_var_ulong Sys_slave_net_timeout(
|
||||
static Sys_var_uint Sys_slave_net_timeout(
|
||||
"slave_net_timeout", "Number of seconds to wait for more data "
|
||||
"from a master/slave connection before aborting the read",
|
||||
GLOBAL_VAR(slave_net_timeout), CMD_LINE(REQUIRED_ARG),
|
||||
|
@ -66,7 +66,7 @@ ulong events_waits_history_per_thread;
|
||||
/** Number of instruments class per thread. */
|
||||
ulong instr_class_per_thread;
|
||||
/** Number of locker lost. @sa LOCKER_STACK_SIZE. */
|
||||
ulong locker_lost;
|
||||
ulong locker_lost= 0;
|
||||
|
||||
/**
|
||||
Mutex instrumentation instances array.
|
||||
@ -746,8 +746,23 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
|
||||
}
|
||||
}
|
||||
|
||||
if (len >= sizeof(pfs->m_filename))
|
||||
len= sizeof(pfs->m_filename) - 1;
|
||||
/*
|
||||
Normalize the file name to avoid duplicates when using aliases:
|
||||
- absolute or relative paths
|
||||
- symbolic links
|
||||
*/
|
||||
char buffer[FN_REFLEN];
|
||||
const char *normalized_filename;
|
||||
int normalized_length;
|
||||
|
||||
/*
|
||||
Ignore errors, the file may not exist.
|
||||
my_realpath always provide a best effort result in buffer.
|
||||
*/
|
||||
(void) my_realpath(buffer, filename, MYF(0));
|
||||
|
||||
normalized_filename= buffer;
|
||||
normalized_length= strlen(normalized_filename);
|
||||
|
||||
PFS_file **entry;
|
||||
uint retry_count= 0;
|
||||
@ -755,7 +770,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
|
||||
search:
|
||||
entry= reinterpret_cast<PFS_file**>
|
||||
(lf_hash_search(&filename_hash, thread->m_filename_hash_pins,
|
||||
filename, len));
|
||||
normalized_filename, normalized_length));
|
||||
if (entry && (entry != MY_ERRPTR))
|
||||
{
|
||||
pfs= *entry;
|
||||
@ -783,9 +798,9 @@ search:
|
||||
if (pfs->m_lock.free_to_dirty())
|
||||
{
|
||||
pfs->m_class= klass;
|
||||
strncpy(pfs->m_filename, filename, len);
|
||||
pfs->m_filename[len]= '\0';
|
||||
pfs->m_filename_length= len;
|
||||
strncpy(pfs->m_filename, normalized_filename, normalized_length);
|
||||
pfs->m_filename[normalized_length]= '\0';
|
||||
pfs->m_filename_length= normalized_length;
|
||||
pfs->m_file_stat.m_open_count= 1;
|
||||
pfs->m_wait_stat.m_control_flag=
|
||||
&flag_events_waits_summary_by_instance;
|
||||
|
Loading…
x
Reference in New Issue
Block a user