PreparedStatement批量插入归档日志需复用预编译语句、分批addBatch/executeBatch(500–2000条/批)、关闭自动提交并手动事务控制,配合分页拉取、范围删除及异步幂等设计,确保高性能与数据一致性。

用 PreparedStatement 批量插入归档表
日志流水归档本质是高频、大批量的 INSERT 操作,直接拼 SQL 或单条执行会严重拖慢性能。核心做法是复用 PreparedStatement,开启批量模式:
- 调用 connection.prepareStatement(sql) 获取预编译语句
- 循环调用 ps.setXXX() 设置参数后,立即执行 ps.addBatch()
- 每积累 500–2000 条(根据单行数据大小和内存调整)调用一次 ps.executeBatch(),并清空批次 ps.clearBatch()
- 务必关闭自动提交:connection.setAutoCommit(false),所有批次执行完再 commit(),失败则 rollback()
归档前加条件筛选与分页拉取
避免一次性查出全部待归档日志导致 OOM 或锁表。应按时间范围 + 主键/自增 ID 分片处理:
- 例如:归档 create_time 的数据,但不直接 SELECT * FROM log_table WHERE ...
- 改用带 LIMIT/OFFSET 或游标分页(推荐):WHERE create_time
- 每次归档后记录最大 id 或时间戳,作为下一批起点,确保不漏不重
源表数据及时清理,配合数据库原生能力
归档不是终点,归档成功后必须安全删除源表旧数据,否则日志表持续膨胀仍影响主业务:
- 删除操作同样走批量 + 事务,建议按主键范围分批删,如:DELETE FROM log_table WHERE id BETWEEN ? AND ?
- MySQL 可考虑 pt-archiver 工具,它内置限流、事务、校验,适合线上稳定归档
- PostgreSQL 可用 partitioning + ATTACH/DETACH 快速切换分区归档,零锁表
异步解耦 + 状态追踪防重复
归档任务若嵌入主流程会拖慢接口响应,应异步化并保证幂等:
- 将待归档的时间段或 ID 范围发到消息队列(如 Kafka/RocketMQ),由独立归档服务消费执行
- 在归档控制表(如 archive_task)中记录任务状态:pending / running / success / failed
- 每次启动先查未完成任务,失败任务可重试,同时用唯一约束(如 date_range + table_name)防止重复归档
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











