Allow one to block an account by using GRANT max_user_connections = -1
One can set @@global.max_user_connections to -1 to block anyone, except SUPER user, to login. If max_user_connection is 0, one can't change it without a restart (needed to get user connections counting to work correctly) mysql-test/r/system_mysql_db.result: Changed max_user_connections to handle negative numbers. mysql-test/r/user_limits-2.result: New test case that one can't change max_user_connection if it was 0 mysql-test/r/user_limits.result: Fixed wrong error messages. mysql-test/r/variables.result: Store / restore max_user_connections (needed as there is now a --master.opt file that changes it) mysql-test/t/subselect_mat_cost-master.opt: Enable slow query log (as this test found some errors in slow query logging) mysql-test/t/user_limits-2.test: New test case that one can't change max_user_connection if it was 0 mysql-test/t/user_limits-master.opt: Set max_user_connections (as one can't change it if it was 0) mysql-test/t/user_limits.test: Test max_user_connections -1 mysql-test/t/variables-master.opt: Set max_user_connections (as one can't change it if it was 0) mysql-test/t/variables.test: Set/restore max_user_connections scripts/Makefile.am: Add a text message to mysql_fix_privilege_tables.sql that it's automaticly generated scripts/mysql_system_tables.sql: Change max_user_connections to signed scripts/mysql_system_tables_fix.sql: Change max_user_connections to signed sql/item_func.cc: Change SHOW_INT to be signed. (Needed for max_user_connections and it's probably a bug that it was not originally signed) sql/log.cc: Remove some code that was not needed (All these variables are reset at start of query) sql/mysql_priv.h: Made max_user_connections signed. Added max_user_connections_checking sql/mysqld.cc: Added max_user_connections_checking so that we know if max_user_connections was 0 at startup (Which means that we will not do connection counting for accounts that don't have user resource limits) Set thd->start_utime at same time as thr_create_utime. (Before start_utime could be < thr_create_utime which lead to wrong query counting) sql/set_var.cc: Don't allow one to change 'max_user_connections' if it was 0 at startup. sql/sql_acl.cc: Change user_connection counting to be negative. sql/sql_connect.cc: If max_user_connections is < 0 then only SUPER user can login. Fixed wrong variable names for error messages. Fixed wrong initial value for questions. Set thd->start_utime and thd->thr_create_utime at startup. Needed to get time_out_user_resource_limits() to work. sql/sql_show.cc: SHOW_INT is now negative sql/sql_yacc.yy: Support negative values for MAX_USER_CONNECTIONS sql/structs.h: Make user connect counting work with signed numbers.
This commit is contained in:
parent
f0c6ce9ade
commit
7800d93bc3
@ -117,7 +117,7 @@ user CREATE TABLE `user` (
|
|||||||
`max_questions` int(11) unsigned NOT NULL DEFAULT '0',
|
`max_questions` int(11) unsigned NOT NULL DEFAULT '0',
|
||||||
`max_updates` int(11) unsigned NOT NULL DEFAULT '0',
|
`max_updates` int(11) unsigned NOT NULL DEFAULT '0',
|
||||||
`max_connections` int(11) unsigned NOT NULL DEFAULT '0',
|
`max_connections` int(11) unsigned NOT NULL DEFAULT '0',
|
||||||
`max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
|
`max_user_connections` int(11) NOT NULL DEFAULT '0',
|
||||||
`plugin` char(60) CHARACTER SET latin1 NOT NULL DEFAULT '',
|
`plugin` char(60) CHARACTER SET latin1 NOT NULL DEFAULT '',
|
||||||
`auth_string` text COLLATE utf8_bin NOT NULL,
|
`auth_string` text COLLATE utf8_bin NOT NULL,
|
||||||
PRIMARY KEY (`Host`,`User`)
|
PRIMARY KEY (`Host`,`User`)
|
||||||
|
2
mysql-test/r/user_limits-2.result
Normal file
2
mysql-test/r/user_limits-2.result
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
set global max_user_connections=100;
|
||||||
|
ERROR HY000: The MySQL server is running with the --max-user-connections=0 option so it cannot execute this statement
|
@ -1,3 +1,4 @@
|
|||||||
|
set @my_max_user_connections= @@global.max_user_connections;
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
create table t1 (i int);
|
create table t1 (i int);
|
||||||
delete from mysql.user where user like 'mysqltest\_%';
|
delete from mysql.user where user like 'mysqltest\_%';
|
||||||
@ -12,9 +13,9 @@ i
|
|||||||
select * from t1;
|
select * from t1;
|
||||||
i
|
i
|
||||||
select * from t1;
|
select * from t1;
|
||||||
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_questions' resource (current value: 2)
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_queries_per_hour' resource (current value: 2)
|
||||||
select * from t1;
|
select * from t1;
|
||||||
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_questions' resource (current value: 2)
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_queries_per_hour' resource (current value: 2)
|
||||||
drop user mysqltest_1@localhost;
|
drop user mysqltest_1@localhost;
|
||||||
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 2;
|
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 2;
|
||||||
flush user_resources;
|
flush user_resources;
|
||||||
@ -27,11 +28,11 @@ i
|
|||||||
delete from t1;
|
delete from t1;
|
||||||
delete from t1;
|
delete from t1;
|
||||||
delete from t1;
|
delete from t1;
|
||||||
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates' resource (current value: 2)
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates_per_hour' resource (current value: 2)
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i
|
i
|
||||||
delete from t1;
|
delete from t1;
|
||||||
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates' resource (current value: 2)
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates_per_hour' resource (current value: 2)
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i
|
i
|
||||||
drop user mysqltest_1@localhost;
|
drop user mysqltest_1@localhost;
|
||||||
@ -65,10 +66,20 @@ select * from t1;
|
|||||||
i
|
i
|
||||||
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||||
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
|
||||||
|
grant usage on *.* to mysqltest_1@localhost with max_user_connections -1;
|
||||||
|
show grants for mysqltest_1@localhost;
|
||||||
|
Grants for mysqltest_1@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_USER_CONNECTIONS -1
|
||||||
|
flush user_resources;
|
||||||
|
show grants for mysqltest_1@localhost;
|
||||||
|
Grants for mysqltest_1@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_USER_CONNECTIONS -1
|
||||||
|
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||||
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: -1)
|
||||||
drop user mysqltest_1@localhost;
|
drop user mysqltest_1@localhost;
|
||||||
select @@session.max_user_connections, @@global.max_user_connections;
|
select @@session.max_user_connections, @@global.max_user_connections;
|
||||||
@@session.max_user_connections @@global.max_user_connections
|
@@session.max_user_connections @@global.max_user_connections
|
||||||
0 0
|
1000 1000
|
||||||
set session max_user_connections= 2;
|
set session max_user_connections= 2;
|
||||||
ERROR HY000: Variable 'max_user_connections' is a GLOBAL variable and should be set with SET GLOBAL
|
ERROR HY000: Variable 'max_user_connections' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
set global max_user_connections= 2;
|
set global max_user_connections= 2;
|
||||||
@ -92,5 +103,21 @@ select @@session.max_user_connections, @@global.max_user_connections;
|
|||||||
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||||
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
|
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
|
||||||
set global max_user_connections= 0;
|
set global max_user_connections= 0;
|
||||||
|
grant usage on *.* to mysqltest_1@localhost with max_user_connections 0;
|
||||||
|
set global max_user_connections=-1;
|
||||||
|
show variables like "max_user_user_connections";
|
||||||
|
Variable_name Value
|
||||||
|
select @@max_user_connections;
|
||||||
|
@@max_user_connections
|
||||||
|
-1
|
||||||
|
select @@global.max_user_connections;
|
||||||
|
@@global.max_user_connections
|
||||||
|
-1
|
||||||
|
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||||
|
ERROR 42000: User mysqltest_1 already has more than 'max_user_connections' active connections
|
||||||
|
set global max_user_connections=1;
|
||||||
|
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
|
||||||
|
ERROR 42000: User mysqltest_1 already has more than 'max_user_connections' active connections
|
||||||
drop user mysqltest_1@localhost;
|
drop user mysqltest_1@localhost;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
set global max_user_connections= @my_max_user_connections;
|
||||||
|
@ -14,6 +14,7 @@ set @my_max_delayed_threads =@@global.max_delayed_threads;
|
|||||||
set @my_max_heap_table_size =@@global.max_heap_table_size;
|
set @my_max_heap_table_size =@@global.max_heap_table_size;
|
||||||
set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads;
|
set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads;
|
||||||
set @my_max_join_size =@@global.max_join_size;
|
set @my_max_join_size =@@global.max_join_size;
|
||||||
|
set @my_max_user_connections =@@global.max_user_connections;
|
||||||
set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size;
|
set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size;
|
||||||
set @my_myisam_max_sort_file_size =@@global.myisam_max_sort_file_size;
|
set @my_myisam_max_sort_file_size =@@global.myisam_max_sort_file_size;
|
||||||
set @my_net_buffer_length =@@global.net_buffer_length;
|
set @my_net_buffer_length =@@global.net_buffer_length;
|
||||||
@ -1049,7 +1050,7 @@ set global max_delayed_threads =@my_max_delayed_threads;
|
|||||||
set global max_heap_table_size =@my_max_heap_table_size;
|
set global max_heap_table_size =@my_max_heap_table_size;
|
||||||
set global max_insert_delayed_threads=@my_max_insert_delayed_threads;
|
set global max_insert_delayed_threads=@my_max_insert_delayed_threads;
|
||||||
set global max_join_size =@my_max_join_size;
|
set global max_join_size =@my_max_join_size;
|
||||||
set global max_user_connections =default;
|
set global max_user_connections =@my_max_user_connections;
|
||||||
set global max_write_lock_count =default;
|
set global max_write_lock_count =default;
|
||||||
set global myisam_data_pointer_size =@my_myisam_data_pointer_size;
|
set global myisam_data_pointer_size =@my_myisam_data_pointer_size;
|
||||||
set global myisam_max_sort_file_size =@my_myisam_max_sort_file_size;
|
set global myisam_max_sort_file_size =@my_myisam_max_sort_file_size;
|
||||||
|
1
mysql-test/t/subselect_mat_cost-master.opt
Normal file
1
mysql-test/t/subselect_mat_cost-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--log-output=TABLE,FILE --log --log-slow-queries --slow-query-log=1
|
11
mysql-test/t/user_limits-2.test
Normal file
11
mysql-test/t/user_limits-2.test
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#
|
||||||
|
# Test behavior of various per-account limits (aka quotas)
|
||||||
|
#
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# We will get an error as it was set to 0 at startup
|
||||||
|
#
|
||||||
|
--error ER_OPTION_PREVENTS_STATEMENT
|
||||||
|
set global max_user_connections=100;
|
||||||
|
|
1
mysql-test/t/user_limits-master.opt
Normal file
1
mysql-test/t/user_limits-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--max-user-connections=1000
|
@ -8,6 +8,8 @@
|
|||||||
# Save the initial number of concurrent sessions
|
# Save the initial number of concurrent sessions
|
||||||
--source include/count_sessions.inc
|
--source include/count_sessions.inc
|
||||||
|
|
||||||
|
set @my_max_user_connections= @@global.max_user_connections;
|
||||||
|
|
||||||
# Prepare play-ground
|
# Prepare play-ground
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
@ -120,8 +122,18 @@ select * from t1;
|
|||||||
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||||
--error ER_USER_LIMIT_REACHED
|
--error ER_USER_LIMIT_REACHED
|
||||||
connect (muc5, localhost, mysqltest_1,,);
|
connect (muc5, localhost, mysqltest_1,,);
|
||||||
# Clean up
|
|
||||||
connection default;
|
connection default;
|
||||||
|
# Test with negative max_user_connections
|
||||||
|
grant usage on *.* to mysqltest_1@localhost with max_user_connections -1;
|
||||||
|
show grants for mysqltest_1@localhost;
|
||||||
|
flush user_resources;
|
||||||
|
show grants for mysqltest_1@localhost;
|
||||||
|
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||||
|
--error ER_USER_LIMIT_REACHED
|
||||||
|
connect (muc5, localhost, mysqltest_1,,);
|
||||||
|
|
||||||
|
# Clean up
|
||||||
disconnect muc2;
|
disconnect muc2;
|
||||||
disconnect muc3;
|
disconnect muc3;
|
||||||
disconnect muc4;
|
disconnect muc4;
|
||||||
@ -165,12 +177,37 @@ disconnect muca1;
|
|||||||
disconnect muca2;
|
disconnect muca2;
|
||||||
disconnect muca3;
|
disconnect muca3;
|
||||||
set global max_user_connections= 0;
|
set global max_user_connections= 0;
|
||||||
drop user mysqltest_1@localhost;
|
|
||||||
--enable_ps_protocol
|
--enable_ps_protocol
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test setting negative values of max_user_connections
|
||||||
|
#
|
||||||
|
grant usage on *.* to mysqltest_1@localhost with max_user_connections 0;
|
||||||
|
set global max_user_connections=-1;
|
||||||
|
show variables like "max_user_user_connections";
|
||||||
|
select @@max_user_connections;
|
||||||
|
select @@global.max_user_connections;
|
||||||
|
# Check that we can't connect anymore except as root
|
||||||
|
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||||
|
--error ER_TOO_MANY_USER_CONNECTIONS
|
||||||
|
connect (muca2, localhost, mysqltest_1,,);
|
||||||
|
connect (muca2, localhost, root,,);
|
||||||
|
disconnect muca2;
|
||||||
|
connection default;
|
||||||
|
set global max_user_connections=1;
|
||||||
|
# Check that we can connect one time, not two
|
||||||
|
connect (muca2, localhost, mysqltest_1,,);
|
||||||
|
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
|
||||||
|
--error ER_TOO_MANY_USER_CONNECTIONS
|
||||||
|
connect (muca3, localhost, mysqltest_1,,);
|
||||||
|
disconnect muca2;
|
||||||
|
connection default;
|
||||||
|
drop user mysqltest_1@localhost;
|
||||||
|
|
||||||
# Final cleanup
|
# Final cleanup
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
# Wait till all disconnects are completed
|
# Wait till all disconnects are completed
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
|
||||||
|
set global max_user_connections= @my_max_user_connections;
|
||||||
|
1
mysql-test/t/variables-master.opt
Normal file
1
mysql-test/t/variables-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--max-user-connections=1
|
@ -23,6 +23,7 @@ set @my_max_delayed_threads =@@global.max_delayed_threads;
|
|||||||
set @my_max_heap_table_size =@@global.max_heap_table_size;
|
set @my_max_heap_table_size =@@global.max_heap_table_size;
|
||||||
set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads;
|
set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads;
|
||||||
set @my_max_join_size =@@global.max_join_size;
|
set @my_max_join_size =@@global.max_join_size;
|
||||||
|
set @my_max_user_connections =@@global.max_user_connections;
|
||||||
set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size;
|
set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size;
|
||||||
set @my_myisam_max_sort_file_size =@@global.myisam_max_sort_file_size;
|
set @my_myisam_max_sort_file_size =@@global.myisam_max_sort_file_size;
|
||||||
set @my_net_buffer_length =@@global.net_buffer_length;
|
set @my_net_buffer_length =@@global.net_buffer_length;
|
||||||
@ -830,7 +831,7 @@ set global max_delayed_threads =@my_max_delayed_threads;
|
|||||||
set global max_heap_table_size =@my_max_heap_table_size;
|
set global max_heap_table_size =@my_max_heap_table_size;
|
||||||
set global max_insert_delayed_threads=@my_max_insert_delayed_threads;
|
set global max_insert_delayed_threads=@my_max_insert_delayed_threads;
|
||||||
set global max_join_size =@my_max_join_size;
|
set global max_join_size =@my_max_join_size;
|
||||||
set global max_user_connections =default;
|
set global max_user_connections =@my_max_user_connections;
|
||||||
set global max_write_lock_count =default;
|
set global max_write_lock_count =default;
|
||||||
set global myisam_data_pointer_size =@my_myisam_data_pointer_size;
|
set global myisam_data_pointer_size =@my_myisam_data_pointer_size;
|
||||||
set global myisam_max_sort_file_size =@my_myisam_max_sort_file_size;
|
set global myisam_max_sort_file_size =@my_myisam_max_sort_file_size;
|
||||||
|
@ -117,7 +117,10 @@ mysqlbug: ${top_builddir}/config.status mysqlbug.sh
|
|||||||
mysql_fix_privilege_tables.sql: mysql_system_tables.sql \
|
mysql_fix_privilege_tables.sql: mysql_system_tables.sql \
|
||||||
mysql_system_tables_fix.sql
|
mysql_system_tables_fix.sql
|
||||||
@echo "Building $@";
|
@echo "Building $@";
|
||||||
@cat mysql_system_tables.sql mysql_system_tables_fix.sql > $@
|
@echo "-- This file is automaticly generated from" > $@
|
||||||
|
@echo "-- mysql_system_tables.sql & mysql_system_tables_fix.sql" >> $@
|
||||||
|
@echo "" >> $@
|
||||||
|
@cat mysql_system_tables.sql mysql_system_tables_fix.sql >> $@
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build mysql_fix_privilege_tables_sql.c from
|
# Build mysql_fix_privilege_tables_sql.c from
|
||||||
|
@ -13,7 +13,7 @@ set @had_db_table= @@warning_count != 0;
|
|||||||
CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
|
CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, auth_string TEXT NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
|
CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, auth_string TEXT NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
|
||||||
|
|
||||||
-- Remember for later if user table already existed
|
-- Remember for later if user table already existed
|
||||||
set @had_user_table= @@warning_count != 0;
|
set @had_user_table= @@warning_count != 0;
|
||||||
|
@ -326,8 +326,11 @@ UPDATE host SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv,
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Add max_user_connections resource limit
|
# Add max_user_connections resource limit
|
||||||
|
# this is signed in MariaDB so that if one sets it's to -1 then the user
|
||||||
|
# can't connect anymore.
|
||||||
#
|
#
|
||||||
ALTER TABLE user ADD max_user_connections int(11) unsigned DEFAULT '0' NOT NULL AFTER max_connections;
|
ALTER TABLE user ADD max_user_connections int(11) DEFAULT '0' NOT NULL AFTER max_connections;
|
||||||
|
ALTER TABLE user MODIFY max_user_connections int(11) DEFAULT '0' NOT NULL AFTER max_connections;
|
||||||
|
|
||||||
#
|
#
|
||||||
# user.Create_user_priv
|
# user.Create_user_priv
|
||||||
|
@ -5063,12 +5063,16 @@ void Item_func_get_system_var::fix_length_and_dec()
|
|||||||
switch (var->show_type())
|
switch (var->show_type())
|
||||||
{
|
{
|
||||||
case SHOW_LONG:
|
case SHOW_LONG:
|
||||||
case SHOW_INT:
|
|
||||||
case SHOW_HA_ROWS:
|
case SHOW_HA_ROWS:
|
||||||
unsigned_flag= TRUE;
|
unsigned_flag= TRUE;
|
||||||
max_length= MY_INT64_NUM_DECIMAL_DIGITS;
|
max_length= MY_INT64_NUM_DECIMAL_DIGITS;
|
||||||
decimals=0;
|
decimals=0;
|
||||||
break;
|
break;
|
||||||
|
case SHOW_INT:
|
||||||
|
unsigned_flag= FALSE;
|
||||||
|
max_length= MY_INT64_NUM_DECIMAL_DIGITS;
|
||||||
|
decimals=0;
|
||||||
|
break;
|
||||||
case SHOW_LONGLONG:
|
case SHOW_LONGLONG:
|
||||||
unsigned_flag= TRUE;
|
unsigned_flag= TRUE;
|
||||||
max_length= MY_INT64_NUM_DECIMAL_DIGITS;
|
max_length= MY_INT64_NUM_DECIMAL_DIGITS;
|
||||||
@ -5209,7 +5213,7 @@ longlong Item_func_get_system_var::val_int()
|
|||||||
|
|
||||||
switch (var->show_type())
|
switch (var->show_type())
|
||||||
{
|
{
|
||||||
case SHOW_INT: get_sys_var_safe (uint);
|
case SHOW_INT: get_sys_var_safe (int);
|
||||||
case SHOW_LONG: get_sys_var_safe (ulong);
|
case SHOW_LONG: get_sys_var_safe (ulong);
|
||||||
case SHOW_LONGLONG: get_sys_var_safe (ulonglong);
|
case SHOW_LONGLONG: get_sys_var_safe (ulonglong);
|
||||||
case SHOW_HA_ROWS: get_sys_var_safe (ha_rows);
|
case SHOW_HA_ROWS: get_sys_var_safe (ha_rows);
|
||||||
|
11
sql/log.cc
11
sql/log.cc
@ -1062,17 +1062,6 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
|
|||||||
query_length= command_name[thd->command].length;
|
query_length= command_name[thd->command].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!query_length)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Not a real query; Reset counts for slow query logging
|
|
||||||
(QQ: Wonder if this is really needed)
|
|
||||||
*/
|
|
||||||
thd->sent_row_count= thd->examined_row_count= 0;
|
|
||||||
thd->query_plan_flags= QPLAN_INIT;
|
|
||||||
thd->query_plan_fsort_passes= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (current_handler= slow_log_handler_list; *current_handler ;)
|
for (current_handler= slow_log_handler_list; *current_handler ;)
|
||||||
error= (*current_handler++)->log_slow(thd, current_time,
|
error= (*current_handler++)->log_slow(thd, current_time,
|
||||||
user_host_buff, user_host_len,
|
user_host_buff, user_host_len,
|
||||||
|
@ -2151,7 +2151,8 @@ extern MYSQL_PLUGIN_IMPORT ulong max_connections;
|
|||||||
extern ulong max_connect_errors, connect_timeout;
|
extern ulong max_connect_errors, connect_timeout;
|
||||||
extern ulong extra_max_connections;
|
extern ulong extra_max_connections;
|
||||||
extern ulong slave_net_timeout, slave_trans_retries;
|
extern ulong slave_net_timeout, slave_trans_retries;
|
||||||
extern uint max_user_connections;
|
extern int max_user_connections;
|
||||||
|
extern bool max_user_connections_checking;
|
||||||
extern ulonglong denied_connections;
|
extern ulonglong denied_connections;
|
||||||
extern ulong what_to_log,flush_time;
|
extern ulong what_to_log,flush_time;
|
||||||
extern ulong query_buff_size;
|
extern ulong query_buff_size;
|
||||||
|
@ -669,7 +669,8 @@ ulong extra_max_connections;
|
|||||||
*/
|
*/
|
||||||
ulong max_long_data_size;
|
ulong max_long_data_size;
|
||||||
|
|
||||||
uint max_user_connections= 0;
|
int max_user_connections= 0;
|
||||||
|
bool max_user_connections_checking=0;
|
||||||
ulonglong denied_connections;
|
ulonglong denied_connections;
|
||||||
/**
|
/**
|
||||||
Limit of the total number of prepared statements in the server.
|
Limit of the total number of prepared statements in the server.
|
||||||
@ -2142,6 +2143,7 @@ static bool cache_thread()
|
|||||||
*/
|
*/
|
||||||
thd->mysys_var->abort= 0;
|
thd->mysys_var->abort= 0;
|
||||||
thd->thr_create_utime= microsecond_interval_timer();
|
thd->thr_create_utime= microsecond_interval_timer();
|
||||||
|
thd->start_utime= thd->thr_create_utime;
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@ -5263,7 +5265,7 @@ void create_thread_to_handle_connection(THD *thd)
|
|||||||
thread_created++;
|
thread_created++;
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
|
DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
|
||||||
thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
|
thd->prior_thr_create_utime= microsecond_interval_timer();
|
||||||
if ((error=pthread_create(&thd->real_id,&connection_attrib,
|
if ((error=pthread_create(&thd->real_id,&connection_attrib,
|
||||||
handle_one_connection,
|
handle_one_connection,
|
||||||
(void*) thd)))
|
(void*) thd)))
|
||||||
@ -7432,9 +7434,9 @@ each time the SQL thread starts.",
|
|||||||
&max_system_variables.max_tmp_tables, 0, GET_ULONG,
|
&max_system_variables.max_tmp_tables, 0, GET_ULONG,
|
||||||
REQUIRED_ARG, 32, 1, (longlong) ULONG_MAX, 0, 1, 0},
|
REQUIRED_ARG, 32, 1, (longlong) ULONG_MAX, 0, 1, 0},
|
||||||
{"max_user_connections", OPT_MAX_USER_CONNECTIONS,
|
{"max_user_connections", OPT_MAX_USER_CONNECTIONS,
|
||||||
"The maximum number of active connections for a single user (0 = no limit).",
|
"The maximum number of active connections for a single user (0 = no limit. In addition global max_user_connections counting and checking is permanently disabled).",
|
||||||
&max_user_connections, &max_user_connections, 0, GET_UINT,
|
&max_user_connections, &max_user_connections, 0, GET_INT,
|
||||||
REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0},
|
REQUIRED_ARG, 0, 0, INT_MAX, 0, 1, 0},
|
||||||
{"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
|
{"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
|
||||||
"After this many write locks, allow some read locks to run in between.",
|
"After this many write locks, allow some read locks to run in between.",
|
||||||
&max_write_lock_count, &max_write_lock_count, 0, GET_ULONG,
|
&max_write_lock_count, &max_write_lock_count, 0, GET_ULONG,
|
||||||
@ -9641,6 +9643,8 @@ static int get_options(int *argc,char **argv)
|
|||||||
if (!max_long_data_size_used)
|
if (!max_long_data_size_used)
|
||||||
max_long_data_size= global_system_variables.max_allowed_packet;
|
max_long_data_size= global_system_variables.max_allowed_packet;
|
||||||
|
|
||||||
|
/* Rember if max_user_connections was 0 at startup */
|
||||||
|
max_user_connections_checking= max_user_connections != 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3082,7 +3082,19 @@ void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
|
|||||||
bool sys_var_max_user_conn::check(THD *thd, set_var *var)
|
bool sys_var_max_user_conn::check(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
if (var->type == OPT_GLOBAL)
|
if (var->type == OPT_GLOBAL)
|
||||||
|
{
|
||||||
|
if (! max_user_connections_checking)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We can't change the value of max_user_connections from 0 as then
|
||||||
|
connect counting would be wrong.
|
||||||
|
*/
|
||||||
|
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
|
||||||
|
"--max-user-connections=0");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
return sys_var_thd::check(thd, var);
|
return sys_var_thd::check(thd, var);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -3098,7 +3110,7 @@ bool sys_var_max_user_conn::update(THD *thd, set_var *var)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(var->type == OPT_GLOBAL);
|
DBUG_ASSERT(var->type == OPT_GLOBAL);
|
||||||
pthread_mutex_lock(&LOCK_global_system_variables);
|
pthread_mutex_lock(&LOCK_global_system_variables);
|
||||||
max_user_connections= (uint)var->save_result.ulonglong_value;
|
max_user_connections= (int) var->save_result.ulonglong_value;
|
||||||
pthread_mutex_unlock(&LOCK_global_system_variables);
|
pthread_mutex_unlock(&LOCK_global_system_variables);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2089,7 +2089,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
|
|||||||
table->field[next_field+2]->store((longlong) mqh.conn_per_hour, TRUE);
|
table->field[next_field+2]->store((longlong) mqh.conn_per_hour, TRUE);
|
||||||
if (table->s->fields >= 36 &&
|
if (table->s->fields >= 36 &&
|
||||||
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
|
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
|
||||||
table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE);
|
table->field[next_field+3]->store((longlong) mqh.user_conn, FALSE);
|
||||||
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
|
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
|
||||||
|
|
||||||
next_field+=4;
|
next_field+=4;
|
||||||
@ -4578,7 +4578,8 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant,
|
|||||||
|
|
||||||
/* Help function for mysql_show_grants */
|
/* Help function for mysql_show_grants */
|
||||||
|
|
||||||
static void add_user_option(String *grant, ulong value, const char *name)
|
static void add_user_option(String *grant, long value, const char *name,
|
||||||
|
my_bool is_signed)
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
@ -4586,7 +4587,7 @@ static void add_user_option(String *grant, ulong value, const char *name)
|
|||||||
grant->append(' ');
|
grant->append(' ');
|
||||||
grant->append(name, strlen(name));
|
grant->append(name, strlen(name));
|
||||||
grant->append(' ');
|
grant->append(' ');
|
||||||
p=int10_to_str(value, buff, 10);
|
p=int10_to_str(value, buff, is_signed ? -10 : 10);
|
||||||
grant->append(buff,p-buff);
|
grant->append(buff,p-buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4768,13 +4769,13 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
|
|||||||
if (want_access & GRANT_ACL)
|
if (want_access & GRANT_ACL)
|
||||||
global.append(STRING_WITH_LEN(" GRANT OPTION"));
|
global.append(STRING_WITH_LEN(" GRANT OPTION"));
|
||||||
add_user_option(&global, acl_user->user_resource.questions,
|
add_user_option(&global, acl_user->user_resource.questions,
|
||||||
"MAX_QUERIES_PER_HOUR");
|
"MAX_QUERIES_PER_HOUR", 0);
|
||||||
add_user_option(&global, acl_user->user_resource.updates,
|
add_user_option(&global, acl_user->user_resource.updates,
|
||||||
"MAX_UPDATES_PER_HOUR");
|
"MAX_UPDATES_PER_HOUR", 0);
|
||||||
add_user_option(&global, acl_user->user_resource.conn_per_hour,
|
add_user_option(&global, acl_user->user_resource.conn_per_hour,
|
||||||
"MAX_CONNECTIONS_PER_HOUR");
|
"MAX_CONNECTIONS_PER_HOUR", 0);
|
||||||
add_user_option(&global, acl_user->user_resource.user_conn,
|
add_user_option(&global, acl_user->user_resource.user_conn,
|
||||||
"MAX_USER_CONNECTIONS");
|
"MAX_USER_CONNECTIONS", 1);
|
||||||
}
|
}
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(global.ptr(),global.length(),global.charset());
|
protocol->store(global.ptr(),global.length(),global.charset());
|
||||||
@ -8147,10 +8148,16 @@ bool acl_authenticate(THD *thd, uint connect_errors,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't allow the user to connect if he has done too many queries */
|
/*
|
||||||
if ((acl_user->user_resource.questions || acl_user->user_resource.updates ||
|
Don't allow the user to connect if he has done too many queries.
|
||||||
|
As we are testing max_user_connections == 0 here, it means that we
|
||||||
|
can't let the user change max_user_connections from 0 in the server
|
||||||
|
without a restart as it would lead to wrong connect counting.
|
||||||
|
*/
|
||||||
|
if ((acl_user->user_resource.questions ||
|
||||||
|
acl_user->user_resource.updates ||
|
||||||
acl_user->user_resource.conn_per_hour ||
|
acl_user->user_resource.conn_per_hour ||
|
||||||
acl_user->user_resource.user_conn || max_user_connections) &&
|
acl_user->user_resource.user_conn || max_user_connections_checking) &&
|
||||||
get_or_create_user_conn(thd,
|
get_or_create_user_conn(thd,
|
||||||
(opt_old_style_user_limits ? sctx->user : sctx->priv_user),
|
(opt_old_style_user_limits ? sctx->user : sctx->priv_user),
|
||||||
(opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
|
(opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
|
||||||
@ -8163,7 +8170,7 @@ bool acl_authenticate(THD *thd, uint connect_errors,
|
|||||||
if (thd->user_connect &&
|
if (thd->user_connect &&
|
||||||
(thd->user_connect->user_resources.conn_per_hour ||
|
(thd->user_connect->user_resources.conn_per_hour ||
|
||||||
thd->user_connect->user_resources.user_conn ||
|
thd->user_connect->user_resources.user_conn ||
|
||||||
max_user_connections) &&
|
max_user_connections_checking) &&
|
||||||
check_for_max_user_connections(thd, thd->user_connect))
|
check_for_max_user_connections(thd, thd->user_connect))
|
||||||
{
|
{
|
||||||
/* Ensure we don't decrement thd->user_connections->connections twice */
|
/* Ensure we don't decrement thd->user_connections->connections twice */
|
||||||
|
@ -113,8 +113,11 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
|
|||||||
DBUG_ENTER("check_for_max_user_connections");
|
DBUG_ENTER("check_for_max_user_connections");
|
||||||
|
|
||||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||||
|
|
||||||
|
/* Root is not affected by the value of max_user_connections */
|
||||||
if (max_user_connections && !uc->user_resources.user_conn &&
|
if (max_user_connections && !uc->user_resources.user_conn &&
|
||||||
max_user_connections < (uint) uc->connections)
|
max_user_connections < uc->connections &&
|
||||||
|
!(thd->security_ctx->master_access & SUPER_ACL))
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
|
my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
|
||||||
goto end;
|
goto end;
|
||||||
@ -202,7 +205,7 @@ void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
|
|||||||
/* If more than a hour since last check, reset resource checking */
|
/* If more than a hour since last check, reset resource checking */
|
||||||
if (check_time - uc->reset_utime >= LL(3600000000))
|
if (check_time - uc->reset_utime >= LL(3600000000))
|
||||||
{
|
{
|
||||||
uc->questions=1;
|
uc->questions=0;
|
||||||
uc->updates=0;
|
uc->updates=0;
|
||||||
uc->conn_per_hour=0;
|
uc->conn_per_hour=0;
|
||||||
uc->reset_utime= check_time;
|
uc->reset_utime= check_time;
|
||||||
@ -231,7 +234,7 @@ bool check_mqh(THD *thd, uint check_command)
|
|||||||
if (uc->user_resources.questions &&
|
if (uc->user_resources.questions &&
|
||||||
uc->questions++ >= uc->user_resources.questions)
|
uc->questions++ >= uc->user_resources.questions)
|
||||||
{
|
{
|
||||||
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_questions",
|
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_queries_per_hour",
|
||||||
(long) uc->user_resources.questions);
|
(long) uc->user_resources.questions);
|
||||||
error=1;
|
error=1;
|
||||||
goto end;
|
goto end;
|
||||||
@ -243,7 +246,7 @@ bool check_mqh(THD *thd, uint check_command)
|
|||||||
(sql_command_flags[check_command] & CF_CHANGES_DATA) &&
|
(sql_command_flags[check_command] & CF_CHANGES_DATA) &&
|
||||||
uc->updates++ >= uc->user_resources.updates)
|
uc->updates++ >= uc->user_resources.updates)
|
||||||
{
|
{
|
||||||
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_updates",
|
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_updates_per_hour",
|
||||||
(long) uc->user_resources.updates);
|
(long) uc->user_resources.updates);
|
||||||
error=1;
|
error=1;
|
||||||
goto end;
|
goto end;
|
||||||
@ -1131,6 +1134,8 @@ pthread_handler_t handle_one_connection(void *arg)
|
|||||||
THD *thd= (THD*) arg;
|
THD *thd= (THD*) arg;
|
||||||
|
|
||||||
thd->thr_create_utime= microsecond_interval_timer();
|
thd->thr_create_utime= microsecond_interval_timer();
|
||||||
|
/* We need to set this because of time_out_user_resource_limits */
|
||||||
|
thd->start_utime= thd->thr_create_utime;
|
||||||
|
|
||||||
if (thread_scheduler.init_new_connection_thread())
|
if (thread_scheduler.init_new_connection_thread())
|
||||||
{
|
{
|
||||||
|
@ -2439,7 +2439,7 @@ static bool show_status_array(THD *thd, const char *wild,
|
|||||||
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
|
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
|
||||||
break;
|
break;
|
||||||
case SHOW_INT:
|
case SHOW_INT:
|
||||||
end= int10_to_str((long) *(uint32*) value, buff, 10);
|
end= int10_to_str((long) *(int*) value, buff, -10);
|
||||||
break;
|
break;
|
||||||
case SHOW_HAVE:
|
case SHOW_HAVE:
|
||||||
{
|
{
|
||||||
|
@ -1350,7 +1350,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
|
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
|
||||||
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
|
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
|
||||||
optional_flush_tables_arguments opt_dyncol_type dyncol_type
|
optional_flush_tables_arguments opt_dyncol_type dyncol_type
|
||||||
opt_time_precision kill_type kill_option
|
opt_time_precision kill_type kill_option int_num
|
||||||
|
|
||||||
%type <ulong_num>
|
%type <ulong_num>
|
||||||
ulong_num real_ulong_num merge_insert_types
|
ulong_num real_ulong_num merge_insert_types
|
||||||
@ -9676,6 +9676,12 @@ delete_limit_clause:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
int_num:
|
||||||
|
NUM { int error; $$= (int) my_strtoll10($1.str, (char**) 0, &error); }
|
||||||
|
| '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
|
||||||
|
| '-' LONG_NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
|
||||||
|
;
|
||||||
|
|
||||||
ulong_num:
|
ulong_num:
|
||||||
NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
|
NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
|
||||||
| HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
|
| HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
|
||||||
@ -13434,7 +13440,7 @@ grant_option:
|
|||||||
lex->mqh.conn_per_hour= $2;
|
lex->mqh.conn_per_hour= $2;
|
||||||
lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
|
lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
|
||||||
}
|
}
|
||||||
| MAX_USER_CONNECTIONS_SYM ulong_num
|
| MAX_USER_CONNECTIONS_SYM int_num
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->mqh.user_conn= $2;
|
lex->mqh.user_conn= $2;
|
||||||
|
@ -222,8 +222,11 @@ typedef struct user_resources {
|
|||||||
uint updates;
|
uint updates;
|
||||||
/* Maximum number of connections established per hour. */
|
/* Maximum number of connections established per hour. */
|
||||||
uint conn_per_hour;
|
uint conn_per_hour;
|
||||||
/* Maximum number of concurrent connections. */
|
/*
|
||||||
uint user_conn;
|
Maximum number of concurrent connections. If -1 then no new
|
||||||
|
connections allowed
|
||||||
|
*/
|
||||||
|
int user_conn;
|
||||||
/*
|
/*
|
||||||
Values of this enum and specified_limits member are used by the
|
Values of this enum and specified_limits member are used by the
|
||||||
parser to store which user limits were specified in GRANT statement.
|
parser to store which user limits were specified in GRANT statement.
|
||||||
@ -256,7 +259,7 @@ typedef struct user_conn {
|
|||||||
/* Total length of the key. */
|
/* Total length of the key. */
|
||||||
uint len;
|
uint len;
|
||||||
/* Current amount of concurrent connections for this account. */
|
/* Current amount of concurrent connections for this account. */
|
||||||
uint connections;
|
int connections;
|
||||||
/*
|
/*
|
||||||
Current number of connections per hour, number of updating statements
|
Current number of connections per hour, number of updating statements
|
||||||
per hour and total number of statements per hour for this account.
|
per hour and total number of statements per hour for this account.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user