如何查明MySQL数据库(含服务器端)的数据变更操作者及具体变更内容?
嘿,这个问题我在日常运维中碰到过好多次,给你梳理下事前预防和事后追溯的可行方案,帮你精准定位数据变更的操作者和内容:
如果还没发生变更,先做好这些配置,能让后续排查轻松10倍:
开启MySQL审计日志
这是最直接的方式,MySQL Enterprise版自带审计插件,社区版可以用第三方插件(比如Percona Audit Log Plugin)。配置后,所有数据库操作(包括连接、增删改查)都会被记录,包含操作者、时间、SQL语句。
举个社区版用Percona插件的配置示例,在my.cnf里加:plugin-load-add=audit_log.so audit_log_format=JSON audit_log_rotate_on_size=100000000重启MySQL后,日志默认存在
/var/lib/mysql/audit.log,直接查看就能找到变更操作者和对应的SQL。自定义触发器记录变更
如果你不想用插件,可以给关键业务表写触发器,把变更信息插入专门的审计表。比如先创建一个审计表:CREATE TABLE data_change_audit ( id INT AUTO_INCREMENT PRIMARY KEY, table_name VARCHAR(50) NOT NULL, operation_type ENUM('INSERT','UPDATE','DELETE') NOT NULL, operator VARCHAR(50) NOT NULL, change_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, old_data JSON, new_data JSON );然后给用户表写UPDATE触发器:
DELIMITER // CREATE TRIGGER tr_user_update AFTER UPDATE ON user FOR EACH ROW BEGIN INSERT INTO data_change_audit (table_name, operation_type, operator, old_data, new_data) VALUES ('user', 'UPDATE', USER(), JSON_OBJECT('id', OLD.id, 'name', OLD.name), JSON_OBJECT('id', NEW.id, 'name', NEW.name)); END // DELIMITER ;这样每次更新user表,都会把操作者(
USER()函数会返回用户名@主机)、变更前后的数据存到审计表里。
如果变更已经发生,且之前没做监控,别慌,试试这些方法:
解析Binlog日志
MySQL默认开启binlog(如果没开的话这条就没用了),binlog会记录所有数据变更的SQL语句,包含操作者信息。用mysqlbinlog工具解析:# 解析指定binlog文件,显示详细变更内容 mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000003 | grep -A 10 -B 2 "UPDATE\|INSERT\|DELETE"解析结果里会找到类似
/*!*/; # user@host: root[root] @ localhost [] Id: 123的行,这里的root@localhost就是操作者,后面跟着具体的SQL语句。检查服务器系统日志
如果数据库部署在Linux服务器上,可以查看/var/log/auth.log(不同系统路径可能有差异),排查哪些用户在变更时间点登录过服务器;如果有监控工具记录了SHOW PROCESSLIST的历史数据,也能辅助定位当时的数据库连接用户。排查应用层操作日志
大部分数据变更是通过应用程序发起的,去查应用的操作日志——一般正规应用都会记录业务用户ID、操作时间、操作内容,结合数据库变更的时间点,就能对应到具体的操作者和变更细节。
内容的提问来源于stack exchange,提问作者kiran

