Avoid races in connect.test.
The problem was in a test case for Bug33507: - when the number of active connections reaches the limit, the server accepts only root connections. That's achieved by accepting a connection, negotiating with the client and checking user credentials. If it is not SUPER, the connection is dropped. - when the server accepts connection, it increases the counter; - when the server drops connection, it decreases the counter; - the race was in between of decreasing the counter and accepting new connection: - max_user_connections = 2; - 2 oridinary user connections accepted; - extra user connection is establishing; - server checked user credentials, and sent 'Too many connections' error; - the client receives the error and establishes extra SUPER user connection; - the server however didn't decrease the counter (the extra user connection still is "alive" in the server) -- so, the new SUPER-user connection, will be dropped, because it exceeds (max_user_connections + 1). The fix is to implement "safe connect", which makes several attempts to connect and use it in the test script.
This commit is contained in:
parent
f2b39a5a5b
commit
393c54db50
56
mysql-test/include/connect2.inc
Normal file
56
mysql-test/include/connect2.inc
Normal file
@ -0,0 +1,56 @@
|
||||
# include/connect2.inc
|
||||
#
|
||||
# SUMMARY
|
||||
#
|
||||
# Make several attempts to connect.
|
||||
#
|
||||
# USAGE
|
||||
#
|
||||
# EXAMPLE
|
||||
#
|
||||
# connect.test
|
||||
#
|
||||
|
||||
--disable_query_log
|
||||
|
||||
let $wait_counter= 300;
|
||||
if ($wait_timeout)
|
||||
{
|
||||
let $wait_counter= `SELECT $wait_timeout * 10`;
|
||||
}
|
||||
# Reset $wait_timeout so that its value won't be used on subsequent
|
||||
# calls, and default will be used instead.
|
||||
let $wait_timeout= 0;
|
||||
|
||||
--echo # -- Establishing connection '$con_name' (user: $con_user_name)...
|
||||
|
||||
while ($wait_counter)
|
||||
{
|
||||
--disable_abort_on_error
|
||||
--disable_result_log
|
||||
--connect ($con_name,localhost,$con_user_name)
|
||||
--enable_result_log
|
||||
--enable_abort_on_error
|
||||
|
||||
let $error = $mysql_errno;
|
||||
|
||||
if (!$error)
|
||||
{
|
||||
let $wait_counter= 0;
|
||||
}
|
||||
if ($error)
|
||||
{
|
||||
real_sleep 0.1;
|
||||
dec $wait_counter;
|
||||
}
|
||||
}
|
||||
if ($error)
|
||||
{
|
||||
--echo # -- Error: can not establish connection '$con_name'.
|
||||
}
|
||||
if (!$error)
|
||||
{
|
||||
--echo # -- Connection '$con_name' has been established.
|
||||
}
|
||||
|
||||
--enable_query_log
|
@ -127,8 +127,7 @@ GRANT USAGE ON *.* TO mysqltest_u1@localhost;
|
||||
SET GLOBAL max_connections = 3;
|
||||
SET GLOBAL event_scheduler = ON;
|
||||
|
||||
# -- Waiting for old connections to close...
|
||||
|
||||
# -- Waiting for Event Scheduler to start...
|
||||
|
||||
# -- Disconnecting default connection...
|
||||
|
||||
@ -136,22 +135,33 @@ SET GLOBAL event_scheduler = ON;
|
||||
# -- many threads are running.
|
||||
|
||||
# -- Connecting (1)...
|
||||
|
||||
# -- Waiting for root connection to close...
|
||||
# -- Establishing connection 'con_1' (user: mysqltest_u1)...
|
||||
# -- Connection 'con_1' has been established.
|
||||
|
||||
# -- Connecting (2)...
|
||||
# -- Connecting (3)...
|
||||
# -- Connecting (4)...
|
||||
ERROR 08004: Too many connections
|
||||
# -- Establishing connection 'con_2' (user: mysqltest_u1)...
|
||||
# -- Connection 'con_2' has been established.
|
||||
|
||||
# -- Waiting for the last connection to close...
|
||||
# -- Connecting (3)...
|
||||
# -- Establishing connection 'con_3' (user: mysqltest_u1)...
|
||||
# -- Connection 'con_3' has been established.
|
||||
|
||||
# -- Connecting (4) [should fail]...
|
||||
# -- Establishing connection 'con_4' (user: mysqltest_u1)...
|
||||
# -- Error: can not establish connection 'con_4'.
|
||||
|
||||
# -- Check that we allow one extra SUPER-user connection.
|
||||
|
||||
# -- Connecting super (1)...
|
||||
# -- Connecting super (2)...
|
||||
ERROR HY000: Too many connections
|
||||
# -- Establishing connection 'con_super_1' (user: root)...
|
||||
# -- Connection 'con_super_1' has been established.
|
||||
|
||||
# -- Connecting super (2) [should fail]...
|
||||
# -- Establishing connection 'con_super_2' (user: root)...
|
||||
# -- Error: can not establish connection 'con_super_2'.
|
||||
|
||||
# -- Ensure that we have Event Scheduler thread, 3 ordinary user
|
||||
# -- connections and one extra super-user connection.
|
||||
SELECT user FROM information_schema.processlist ORDER BY id;
|
||||
user
|
||||
event_scheduler
|
||||
@ -165,6 +175,7 @@ SET GLOBAL max_connections = 151;
|
||||
|
||||
# -- Stopping Event Scheduler...
|
||||
SET GLOBAL event_scheduler = OFF;
|
||||
|
||||
# -- Waiting for Event Scheduler to stop...
|
||||
|
||||
# -- That's it. Closing connections...
|
||||
|
@ -114,106 +114,94 @@ drop table t1;
|
||||
--echo # -- End of 4.1 tests
|
||||
--echo # ------------------------------------------------------------------
|
||||
|
||||
###########################################################################
|
||||
|
||||
--echo
|
||||
--echo # -- Bug#33507: Event scheduler creates more threads than max_connections
|
||||
--echo # -- which results in user lockout.
|
||||
--echo
|
||||
|
||||
--echo
|
||||
GRANT USAGE ON *.* TO mysqltest_u1@localhost;
|
||||
|
||||
# NOTE: if the test case fails sporadically due to spurious connections,
|
||||
# consider disabling all users.
|
||||
|
||||
--echo
|
||||
|
||||
let $saved_max_connections = `SELECT @@global.max_connections`;
|
||||
|
||||
SET GLOBAL max_connections = 3;
|
||||
SET GLOBAL event_scheduler = ON;
|
||||
|
||||
--echo
|
||||
--echo # -- Waiting for old connections to close...
|
||||
let $wait_condition =
|
||||
SELECT COUNT(*) = 1
|
||||
FROM information_schema.processlist
|
||||
WHERE db = 'test';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--echo
|
||||
--echo # -- Waiting for Event Scheduler to start...
|
||||
let $wait_condition =
|
||||
SELECT COUNT(*) = 1
|
||||
FROM information_schema.processlist
|
||||
WHERE user = 'event_scheduler';
|
||||
--source include/wait_condition.inc
|
||||
--echo
|
||||
|
||||
--echo
|
||||
--echo # -- Disconnecting default connection...
|
||||
--disconnect default
|
||||
|
||||
--echo
|
||||
--echo # -- Check that we allow exactly three user connections, no matter how
|
||||
--echo # -- many threads are running.
|
||||
|
||||
--echo
|
||||
|
||||
--echo # -- Connecting (1)...
|
||||
--connect (con_1,localhost,mysqltest_u1)
|
||||
let $con_name = con_1;
|
||||
let $con_user_name = mysqltest_u1;
|
||||
--source include/connect2.inc
|
||||
|
||||
--echo
|
||||
--echo # -- Waiting for root connection to close...
|
||||
let $wait_condition =
|
||||
SELECT COUNT(*) = 1
|
||||
FROM information_schema.processlist
|
||||
WHERE db = 'test';
|
||||
--source include/wait_condition.inc
|
||||
--echo
|
||||
|
||||
--echo # -- Connecting (2)...
|
||||
--connect (con_2,localhost,mysqltest_u1)
|
||||
|
||||
--echo # -- Connecting (3)...
|
||||
--connect (con_3,localhost,mysqltest_u1)
|
||||
|
||||
--echo # -- Connecting (4)...
|
||||
--disable_query_log
|
||||
--error ER_CON_COUNT_ERROR
|
||||
--connect (con_4,localhost,mysqltest_u1)
|
||||
--enable_query_log
|
||||
let $con_name = con_2;
|
||||
let $con_user_name = mysqltest_u1;
|
||||
--source include/connect2.inc
|
||||
|
||||
--echo
|
||||
--echo # -- Waiting for the last connection to close...
|
||||
let $wait_condition =
|
||||
SELECT COUNT(*) = 3
|
||||
FROM information_schema.processlist
|
||||
WHERE db = 'test';
|
||||
--source include/wait_condition.inc
|
||||
--echo # -- Connecting (3)...
|
||||
let $con_name = con_3;
|
||||
let $con_user_name = mysqltest_u1;
|
||||
--source include/connect2.inc
|
||||
|
||||
--echo
|
||||
--echo # -- Connecting (4) [should fail]...
|
||||
let $con_name = con_4;
|
||||
let $con_user_name = mysqltest_u1;
|
||||
let $wait_timeout = 5;
|
||||
--source include/connect2.inc
|
||||
|
||||
--echo
|
||||
--echo # -- Check that we allow one extra SUPER-user connection.
|
||||
--echo
|
||||
|
||||
--echo
|
||||
--echo # -- Connecting super (1)...
|
||||
--connect (con_super_1,localhost,root)
|
||||
|
||||
--echo # -- Connecting super (2)...
|
||||
--disable_query_log
|
||||
--error ER_CON_COUNT_ERROR
|
||||
--connect (con_super_2,localhost,root)
|
||||
--enable_query_log
|
||||
let $con_name = con_super_1;
|
||||
let $con_user_name = root;
|
||||
--source include/connect2.inc
|
||||
|
||||
--echo
|
||||
# Ensure that we have Event Scheduler thread, 3 ordinary user connections and
|
||||
# one extra super-user connection.
|
||||
--echo # -- Connecting super (2) [should fail]...
|
||||
let $con_name = con_super_2;
|
||||
let $con_user_name = root;
|
||||
let $wait_timeout = 5;
|
||||
--source include/connect2.inc
|
||||
|
||||
--echo
|
||||
--echo # -- Ensure that we have Event Scheduler thread, 3 ordinary user
|
||||
--echo # -- connections and one extra super-user connection.
|
||||
SELECT user FROM information_schema.processlist ORDER BY id;
|
||||
|
||||
--echo
|
||||
--echo # -- Resetting variables...
|
||||
|
||||
--eval SET GLOBAL max_connections = $saved_max_connections
|
||||
|
||||
--echo
|
||||
--echo # -- Stopping Event Scheduler...
|
||||
SET GLOBAL event_scheduler = OFF;
|
||||
|
||||
--echo
|
||||
--echo # -- Waiting for Event Scheduler to stop...
|
||||
let $wait_condition =
|
||||
SELECT COUNT(*) = 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user