读书笔记: 数据仓库同步的陷阱与Oracle读一致性的奥秘

我们的文章会在微信公众号IT民工的龙马人生博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。

本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。

数据仓库同步的陷阱与Oracle读一致性的奥秘

常见数据仓库同步技术的致命缺陷

许多团队使用以下方法同步数据仓库:

  1. 在源表使用触发器维护LAST_UPDATED
  2. 初始同步时记录当前时间(如9:00),拉取全量数据
  3. 刷新时记录新时间(如10:00),拉取9:00后变更的数据

这种方法在支持非阻塞读的数据库(如Oracle)中存在严重问题:如果9:00时有未提交的事务(如8:59:30开始的修改),这些变更既不会出现在9:00的全量拉取中(因为未提交),也不会出现在10:00的增量拉取中(因为修改时间早于9:00)。

解决方案:应该查询V$TRANSACTION视图,获取当前时间和最早活动事务开始时间中的较小值作为同步起点,确保不会遗漏任何变更。

Oracle读一致性的双刃剑

热表I/O异常高的秘密

在生产环境中,某些查询的I/O量可能异常高于测试环境,原因在于Oracle的多版本读一致性机制:

  1. 当查询需要读取被其他事务修改过的数据块时,必须从撤销段(undo)获取旧版本
  2. 每个回滚操作都可能涉及额外I/O
  3. 高并发修改的表会导致查询需要频繁访问撤销段

典型案例:一个简单查询在测试环境只需7次I/O,在生产环境可能激增至10,004次,因为需要回滚10,000次修改才能获取查询开始时的数据版本。

缓冲区缓存的智能优化

Oracle会在内存中保留数据块的多个版本,后续查询可能直接访问缓存中的合适版本,避免重复回滚操作。可以通过查询查看缓存中的块版本数量:

SELECT COUNT(*) FROM v$bh WHERE file#=文件ID AND dbablk=块ID;

通常每个块不超过6个版本,这显著减少了I/O压力。

写一致性的复杂世界

更新操作的双重读取机制

Oracle执行UPDATE时采用两种读取方式:

  1. 一致读取:查找要修改的行(基于查询开始时的数据快照)
  2. 当前读取:实际更新行时获取最新块版本

如果发现WHERE条件中使用的列值已被修改,Oracle会重新启动整个更新操作。

令人惊讶的"重新启动"现象

通过触发器可以观察到更新操作的重新启动:

-- 测试表
CREATE TABLE t (x INT PRIMARY KEY, y INT);
INSERT INTO t VALUES (1,5);

-- 观察触发器
CREATE OR REPLACE TRIGGER before_update
BEFORE UPDATE ON t FOR EACH ROW
BEGIN
  DBMS_OUTPUT.PUT_LINE('old.x='||:old.x||' old.y='||:old.y);
  DBMS_OUTPUT.PUT_LINE('new.x='||:new.x||' new.y='||:new.y);
END;

当两个会话并发更新同一行时,第二个会话的触发器会触发两次,显示出更新被重新启动。

重新启动的深远影响

  1. 触发器多次执行:可能导致非事务性操作(如发送邮件)重复执行
  2. 性能问题:大批量更新中途重新启动会导致已处理工作回滚
  3. PL/SQL变量不一致:重新启动不会回滚PL/SQL全局变量的修改

最佳实践

  • 避免在触发器中执行非事务性操作
  • 使用DBMS_JOB等机制在事务提交后执行副作用操作
  • 谨慎使用自治事务触发器
  • 优先使用AFTER触发器而非BEFORE触发器以提高效率

总结

Oracle的读一致性和多版本控制是强大功能,但也带来独特挑战。理解这些机制对于:

  • 设计可靠的数据同步方案
  • 诊断性能问题
  • 编写正确的数据库应用
    至关重要。特别是在高并发环境中,必须考虑长查询与数据修改的交互影响,避免微妙的正确性和性能问题。

------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)

posted @ 2025-08-17 14:57  认真就输  阅读(13)  评论(0)    收藏  举报