写点什么

如何限制用户修改 long_query_time

作者:GreatSQL
  • 2024-10-30
    福建
  • 本文字数:1492 字

    阅读完需:约 5 分钟

如何限制用户修改 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_threadCreate 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_ci1 row in set (0.00 sec)
#存储全局的系统变量greatsql> SHOW CREATE TABLE global_variables\G*************************** 1. row *************************** Table: global_variablesCreate 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_ci1 row in set (0.00 sec)
复制代码


event 程序的实现:


DELIMITER $$CREATE EVENT check_session_long_query_timeON SCHEDULE EVERY 5 SECONDDOBEGIN    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)》。


发布于: 刚刚阅读数: 5
用户头像

GreatSQL

关注

GreatSQL社区 2023-01-31 加入

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。 社区:https://greatsql.cn/ Gitee: https://gitee.com/GreatSQL/GreatSQL

评论

发布
暂无评论
如何限制用户修改long_query_time_greatsql_GreatSQL_InfoQ写作社区