如何限制用户修改 long_query_time
需求来源
数据库的 long_query_time 设置了写入慢查询日志的 SQL 语句执行时长的阈值,当应用系统修改为很小的值或 0 时,会在数据库的慢查询日志中记录大量 SQL 语句,导致数据库性能降低和占用磁盘空间的快速增长。
GreatSQL 对于影响整个数据库会话级变量设置为受限会话变量(如:binlog_format,sql_log_bin和sql_log_off),同时增加了用户权限 SESSION_VARIABLES_ADMIN,只有授予了 SESSION_VARIABLES_ADMIN 的用户才能更改这些受限会话变量。
但 long_query_time 不在受限会话变量中,该如何限制应用程序修改 long_query_time 呢?
解决方法
在 performance_schema 中有表 variables_by_thread 存储了每个活动会话的会话级系统变量。可以编写一个 event 定时检查用户的 long_query_time 设置,如果与全局的 long_query_time 变量值不同,将该会话 kill 掉。
相关系统表:
performance_schema下的系统表
存储每个会话的会话级系统变量
greatsql> SHOW CREATE TABLE variables_by_thread\G
*************************** 1. row ***************************
Table: variables_by_thread
Create Table: CREATE TABLE variables_by_thread
(
THREAD_ID
bigint unsigned NOT NULL,
VARIABLE_NAME
varchar(64) NOT NULL,
VARIABLE_VALUE
varchar(1024) DEFAULT NULL,
PRIMARY KEY (THREAD_ID
,VARIABLE_NAME
)
) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
存储全局的系统变量
greatsql> SHOW CREATE TABLE global_variables\G
*************************** 1. row ***************************
Table: global_variables
Create Table: CREATE TABLE global_variables
(
VARIABLE_NAME
varchar(64) NOT NULL,
VARIABLE_VALUE
varchar(1024) DEFAULT NULL,
PRIMARY KEY (VARIABLE_NAME
)
) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
bk.yjh9988.com/D30eq.wAP
bk.zcyxsm.com/meyl/0wSwf.Wap
bk.qcbysq.com/cliq/0wSwf.Wap
bk.bctiantuo.com/beyn/c4FSw.wAp
bk.shuixitech.com/beyn/D30eq.wAP
bk.szlcdpq.com/deyz/f8W4d.wAP
bk.hndsedu.com/c4FSw.wAp
bk.hndsedu.com/0wSwf.Wap
bk.hndsedu.com/D30eq.wAP
bk.chinabgroup.com/f8W4d.wAP
bk.szlcdpq.com/beyn/c5W4R.WAp
bk.wekochat.com/asd7/0wSwf.Wap
bk.lovehua99.com/jasl/0wSwf.Wap
bk.tanjiuspace.com/beyn/fX8Xw.WaP
bk.51yjjy.com/beyn/D30eq.wAP
bk.kfamaw.com/c5W4R.WAp
bk.zcyxsm.com/meyl/c5W4R.WAp
bk.shuixitech.com/fX8Xw.WaP
bk.testoppo.com/asd7/f8W4d.wAP
bk.yjh9988.com/asd7/f8W4d.wAP
event 程序的实现:
DELIMITER $$
CREATE EVENT check_session_long_query_time
ON SCHEDULE EVERY 5 SECOND
DO
BEGIN
DECLARE v_processlist_id BIGINT UNSIGNED;
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR
SELECT t.PROCESSLIST_ID
FROM performance_schema.variables_by_thread v
inner join performance_schema.threads t on v.thread_id=t.thread_id
WHERE v.VARIABLE_NAME = 'long_query_time'
AND v.VARIABLE_VALUE != (select VARIABLE_VALUE from performance_schema.global_variables where
VARIABLE_NAME = 'long_query_time' ) ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_processlist_id ;
IF done THEN
LEAVE read_loop;
END IF;
-- 终止连接
KILL v_processlist_id ;
END LOOP;
CLOSE cur;
END$$
DELIMITER ;
总结
通过 kill 会话来限制用户修改会话级变量,有些暴力,但也是 DBA 的无奈手段。较好的方式是修改受限系统变量实现方法,将受限的会话变量做成一个可动态添加的列表,如在某个系统表中予以存储,DBA 可以通过添加和删除数据行来动态修改受限会话变量。MySQL 开源版本也存在同样的问题,MySQL 社区已确认作者提的 feature request《Optimize the handling of SESSION_VARIABLES_ADMIN permission (https://bugs.mysql.com/bug.php?id=115944)》。
Enjoy GreatSQL
标签:long,bk,time,VARIABLE,query,com From: https://www.cnblogs.com/XX-SHE/p/18537055