事务日志 / undo 膨胀
症状
事务日志文件或 undo/redo 区域快速增长;出现 'log full'、'ORA-01555 snapshot too old'、'unable to extend undo'。
1. 找出使日志增长的未结事务
在最老的活动事务结束之前,日志/undo 无法被清理。一个长时间打开的事务就可能占住整个日志。
Oracle
SELECT s.sid, s.username, t.start_time, t.used_ublk FROM v$transaction t JOIN v$session s ON t.ses_addr=s.saddr ORDER BY t.start_time;PostgreSQL
SELECT pid, state, xact_start, now()-xact_start age, query FROM pg_stat_activity WHERE xact_start IS NOT NULL ORDER BY xact_start;MySQL
SELECT trx_id, trx_started, trx_mysql_thread_id FROM information_schema.innodb_trx ORDER BY trx_started;SQL Server
DBCC OPENTRAN;2. 理解各引擎特有的根本原因
MSSQL:在 FULL 恢复模式下,若不做日志备份,日志会无限增长。Oracle:ORA-01555 = undo 保留时间/大小不足 + 长查询。PG:若复制槽不推进,WAL 会累积;长事务会阻塞 VACUUM。
3. 针对 MSSQL 日志的正确做法
执行日志备份(BACKUP LOG)——这会使日志可以重用。若恢复模式确实应为 SIMPLE,则予以更改。之后,如有需要(且仅在需要时)再收缩日志。
SQL Server
BACKUP LOG [DB] TO DISK='C:\backup\DB_log.trn';
-- Then, if needed: DBCC SHRINKFILE (N'DB_log', 512);4. PG WAL / 复制槽检查
不推进的(inactive)复制槽会导致 WAL 累积。删除之前,先核实该槽的所有者(slot_type、database、plugin):它可能是暂时断开的备库,也可能是逻辑订阅者/CDC(例如 Debezium)。若删除该槽,所连接的备库必须重建,订阅者/CDC 端也必须重新同步。只有确实不再使用时才删除;如需长期防护,请用 max_slot_wal_keep_size(PG13+)设置上限。
PostgreSQL
SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) retained FROM pg_replication_slots ORDER BY 3 DESC;
-- If unneeded: SELECT pg_drop_replication_slot('slot_name');5. 调整 undo/保留设置并防止再次发生
Oracle:扩大 UNDO 表空间,根据长查询设置 undo_retention(或 RETENTION GUARANTEE)。在应用中避免长时间打开的事务。监控日志备份作业是否运行。