MySQL 能不能直接查近3个月SQL访问量?结论先给你

一、对应达梦 V$SQL_HISTORY 的 MySQL 内存表:完全不能查3个月

MySQL 里 performance_schema.events_statements_history / events_statements_history_long 等同于达梦 V$SQL_HISTORY硬性限制

  1. 纯内存存储,重启全部清空
  2. 默认 history_long 仅存 10000条 全局SQL,新数据进来旧记录直接覆盖;
  3. 高并发库可能几十分钟就把历史冲干净,最多只能看最近几十分钟/1~2小时;
  4. 无法持久化,不可能查到3个月前数据

示例(只能查近期,3个月区间返回0)

  1. SELECT
  2. COUNT(*) total_sql,
  3. SUM(CASE WHEN SQL_TEXT LIKE 'SELECT%' THEN 1 ELSE 0 END) select_cnt,
  4. SUM(CASE WHEN SQL_TEXT REGEXP '^(INSERT|UPDATE|DELETE)' THEN 1 ELSE 0 END) dml_cnt
  5. FROM performance_schema.events_statements_history_long
  6. WHERE EVENT_TIME >= NOW() - INTERVAL 3 MONTH; -- 3个月,几乎无数据

二、MySQL 四种可行方案(按长期统计需求排序)

方案1:定时快照入库(轻量、推荐做月度报表,不开全量日志)

原理:SHOW GLOBAL STATUS LIKE 'Com_%' 是数据库启动后累计计数器,无时间戳,不能直接查历史;

  1. show global status like 'Com_%';

写定时脚本(crontab 每小时/每半小时)采集 Com_select/Com_insert/Com_update/Com_delete/Questions,存入自建统计表,带采集时间。 后续直接查统计表,用期末值 - 期初值得到任意月份/3个月总SQL访问量。

  1. 自建统计表
    1. CREATE TABLE mysql_sql_stat (
    2. id BIGINT AUTO_INCREMENT PRIMARY KEY,
    3. stat_time DATETIME,
    4. com_select BIGINT,
    5. com_insert BIGINT,
    6. com_update BIGINT,
    7. com_delete BIGINT,
    8. total_qps BIGINT
    9. );
  2. 统计近3个月总访问量
    1. -- 3个月前最早一条快照、当前最新快照,差值就是总量
    2. SELECT
    3. (curr.com_select - old.com_select) AS total_select,
    4. (curr.com_insert - old.com_insert) AS total_insert,
    5. (curr.com_update - old.com_update) AS total_update,
    6. (curr.com_delete - old.com_delete) AS total_delete
    7. FROM mysql_sql_stat curr, mysql_sql_stat old
    8. WHERE curr.stat_time = (SELECT MAX(stat_time) FROM mysql_sql_stat)
    9. AND old.stat_time <= NOW() - INTERVAL 3 MONTH
    10. ORDER BY old.stat_time DESC LIMIT 1;
    优点:性能损耗极小,适合长期统计日报、季报; 缺点:没有单条SQL明细,只有汇总总量

方案2:开启全量通用日志 general_log(可查任意3个月明细,线上不推荐长期开)

  • 开启后每条SQL落地磁盘日志,带精确时间戳,日志切割归档保存3个月以上;
  • 可用 greppt-query-digest 筛选时间段统计SQL条数; 致命缺点:全量写入磁盘,高QPS库IO压力暴增,仅临时排查使用,不适合长期打开做常规统计。

方案3:审计日志(MySQL Enterprise Audit,企业版付费)

官方审计插件,持久化存储每条执行SQL+操作时间,支持直接SQL按时间区间COUNT统计,完美支持近3个月;社区版无此功能。

方案4:Binlog 间接统计(仅DML,不含SELECT)

binlog 只记录增删改,查不到SELECT查询量,只能统计写入操作,无法完整统计数据库总访问量。

三、对比达梦 & MySQL 能否查3个月

方式 达梦 MySQL 能否查近3个月
内存SQL历史视图(V$SQL_HISTORY / events_statements_history_long) 内存循环覆盖 内存循环覆盖 ❌ 不能
定时快照自建汇总表 V$SYSSTAT差值 Com_xxx差值 ✅ 能(只有汇总)
全量SQL日志/SVR_LOG SVR_LOG持久化 general_log文件 ✅ 能(明细,耗IO)
审计持久化表 V$AUDITRECORDS 企业版Audit插件 ✅ 能(明细,付费)

四、如果你要做「近3个月数据库访问量报表」最优方案

  1. 生产环境首选:定时脚本采集Com_xxx入库,无性能损耗,按月汇总总量;
  2. 需要明细SQL、区分每条SQL执行次数:归档 general_log 日志,定时解析入库;
  3. 社区版MySQL没有原生持久化SQL历史表,不像达梦审计开箱即用,必须靠日志/自建快照实现长期区间统计。

补充:数据库访问流量(应用与MySQL传输流量)

MySQL 默认无内置时段流量统计,两种方式:

  1. 服务器层 tcpdump 抓3306端口流量,归档统计;
  2. 中间件(MyCat、Sharding-JDBC)采集交互字节存入监控库。