当前位置: 首页 > news >正文

读书笔记: 数据仓库同步的陷阱与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
BEGINDBMS_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)

http://www.sczhlp.com/news/13810/

相关文章:

  • SDFZ contest 444 题解
  • 设计表 Design table _2 获取单元格内容
  • 最小二乘法计算触摸事件速度
  • Font Awesome 一个基于CSS和LESS的免费图标库工具包 【下载与使用教程】
  • 铝5052、铝6061、铝7075、铝2A12的主要区别表格:
  • 揭秘ChatGPT共享功能重大隐私漏洞的发现与报告过程
  • 红日靶场01
  • ABC 419 E(滑窗同余 + dp)
  • 与配置相关的设计表 Design table
  • 在 Ubuntu 上安装 Jenkins
  • 2025高效招聘体系搭建:Moka智能化系统落地方法论
  • 使用Python 与 Seq2Seq Transformer 的可变长度验证码识别
  • OpenAI 发布了 GPT-5,有哪些新特性值得关注?国内怎么使用GPT5?
  • loguru 用法
  • 8.17
  • 不知道干什么,谁能陪我聊天
  • 【前端开发】iconfont 阿里巴巴免费矢量图标库超级实用!
  • 采用DoraCloud免费版,部署20用户云桌面
  • 深度学习(修改onnx文件batchsize)
  • 虚树(Virtual Tree)学习笔记
  • ABC419题解
  • 牛 CDR3 单抗 “茎 - 旋钮” 结构的核心特性及学科启示
  • 题解:P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪
  • ECS本质,ecs设计更像是写数据库查询
  • Luogu P7302 [NOI1998] 免费的馅饼 题解 [ 蓝 ] [ 二维偏序 ] [ 树状数组优化 DP ]
  • 基础数论笔记
  • Node.js导入MongoDB具体操作
  • Python入门学习(九)Python的高级语法与用法(四)装饰器
  • 团队编程思考:组合优于继承、依赖管理、缓存过期
  • 智慧农业(接口设计)