MySQL如何捕获运行的SQL查询,使用统一表存储活动历史日志?
你提出的使用统一历史表+触发器记录全业务表变更的方案,在AWS RDS MySQL环境下完全可以落地,不需要额外改造应用业务代码,仅需在数据库侧完成配置即可。
方案实现细节
1. 统一历史表结构优化
原有结构可以稍作调整,适配多场景的变更记录需求:
CREATE TABLE history_table ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, table_name VARCHAR(64) NOT NULL COMMENT '变更所属业务表名', record_primary_key VARCHAR(64) NOT NULL COMMENT '变更行的主键值,方便回溯定位具体数据', column_modified VARCHAR(64) COMMENT '变更字段名,整行插入/删除时可填NULL', action ENUM('insert', 'update', 'delete') NOT NULL COMMENT '操作类型', data_before_modify JSON COMMENT '变更前数据,insert操作时可填NULL', data_after_modify JSON COMMENT '变更后数据,delete操作时可填NULL', date_modified DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '变更时间,精确到毫秒避免并发冲突', INDEX idx_table_date (table_name, date_modified), INDEX idx_record_pk (table_name, record_primary_key) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这里使用JSON类型存储前后数据,相比字符串格式更灵活,后续查询过滤也更方便。
2. 触发器编写示例
插入触发器
DROP TRIGGER IF EXISTS game_data_insert; DELIMITER // CREATE TRIGGER game_data_insert AFTER INSERT ON game_data FOR EACH ROW BEGIN INSERT INTO history_table ( table_name, record_primary_key, action, data_after_modify ) VALUES ( 'game_data', NEW.id, 'insert', JSON_OBJECT( 'season_data', NEW.season_data, 'other_column1', NEW.other_column1, 'other_column2', NEW.other_column2 -- 业务表其他字段依次补充即可 ) ); END // DELIMITER ;
更新触发器
DROP TRIGGER IF EXISTS game_data_update; DELIMITER // CREATE TRIGGER game_data_update AFTER UPDATE ON game_data FOR EACH ROW BEGIN -- 增加判断仅记录真实发生变更的字段,避免生成无意义日志 IF OLD.season_data <> NEW.season_data THEN INSERT INTO history_table ( table_name, record_primary_key, column_modified, action, data_before_modify, data_after_modify ) VALUES ( 'game_data', OLD.id, 'season_data', 'update', OLD.season_data, NEW.season_data ); END IF; -- 其他需要监听的字段可依次增加IF判断逻辑 END // DELIMITER ;
删除触发器
DROP TRIGGER IF EXISTS game_data_delete; DELIMITER // CREATE TRIGGER game_data_delete AFTER DELETE ON game_data FOR EACH ROW BEGIN INSERT INTO history_table ( table_name, record_primary_key, action, data_before_modify ) VALUES ( 'game_data', OLD.id, 'delete', JSON_OBJECT( 'season_data', OLD.season_data, 'other_column1', OLD.other_column1, 'other_column2', OLD.other_column2 -- 业务表其他字段依次补充即可 ) ); END // DELIMITER ;
注意事项
- AWS RDS MySQL默认已开放触发器使用权限,无需额外调整实例参数,仅需确保操作账号持有
TRIGGER权限即可正常创建触发器。 - 高并发场景下需关注
history_table的写入性能,可通过按时间分表、调整InnoDB刷盘参数等方式优化,避免影响原业务表的写入效率。 - 若业务表字段有增删变更,需同步更新对应触发器的字段逻辑,避免遗漏变更记录。
- 不要在触发器中加入复杂计算、跨表查询等逻辑,否则会大幅拖慢原业务的写入速度。
内容的提问来源于stack exchange,提问作者zack_falcon
相关产品推荐
相关产品推荐

