IO性能瓶颈导致检查点不完全,表现为log file switch (checkpoint incomplete)等待事件;需结合db file parallel write耗时、v$filestat的avgiotim与phywrts、iostat的%util和await,定位RAID 5/LUN争用、ASM条带过大及TEMP表空间IO干扰问题。
这不是sql写得差或缺索引的问题,而是dbwr写不过来——重做日志切换时,dbwr还没把脏块刷完,新日志无法复用,会卡住所有dml。awr里看到这个等待排前几,且 db file parallel write 平均耗时 >15ms,基本锁定是底层io跟不上。
关键指标要一起看:v$sysstat 里查 physical writes 和 physical writes direct 的比例;v$session_wait 过滤 event = 'log file switch (checkpoint incomplete)',看对应 sid 是否集中在几个高写入表空间上。
别只盯着日志文件,真正拖慢检查点的是数据文件写入。先跑这个关联查询:
SELECT df.name, fs.phyrds, fs.phywrts, fs.avgiotim, fs.maxiowtmFROM v$filestat fs, v$datafile dfWHERE fs.file# = df.file#ORDER BY fs.phywrts DESCFETCH FIRST 5 ROWS ONLY;
重点看 avgiotim > 20 且 phywrts 高的文件。再用 iostat -x 1 5 对应设备名(如 sdb),确认 %util > 70 且 await 持续 >30ms。如果这些文件都在同一组RAID 5 LUN上,问题就明确了:日志写、回滚写、数据写全挤在一块盘上,互相抢队列。
很多人迁完发现没改善,是因为ASM或存储层条带设置反向放大了随机写开销。查当前ASM条带大小:
SELECT name, allocation_unit_size FROM v$asm_diskgroup;
如果返回值是 1048576(1MB),而你的OLTP平均IO大小是8KB–64KB,等于每次写都要跨至少16块盘寻道。正确做法是:
ALLOCATION_UNIT_SIZE = 131072(128KB)或 262144(256KB)ALTER DATABASE MOVE DATAFILE,目标路径所在挂载点必须启用 noatime,nodiratime
哪怕业务SQL本身不慢,大量 ORDER BY + ROWNUM 或无索引 GROUP BY 也会触发磁盘排序,占用TEMP表空间IO,间接拖慢DBWR刷脏。查活跃排序:
SELECT tablespace_name, segtype, blocks*8/1024 MB FROM v$sort_segment WHERE segtype = 'SORT';
如果 MB 值持续 >500,说明TEMP正在被高频使用。此时:
ALTER USER app_user TEMPORARY TABLESPACE temp_fast;
检查点超时本质是写链路断在了物理层,调 fast_start_mttr_target 或加大日志文件只是掩盖症状。真正要动的是数据文件落盘位置、条带粒度和临时段IO路径——这三处任一没对齐,压测时照样卡住。