关注“数据和云”,精彩不容错过

杨廷琨

云和恩墨高级咨询顾问, ITPUB Oracle 数据库管理版版主 ,人称 “杨长老”,十数年如一日坚持进行 Oracle 技术研究与写作,号称 “Oracle 的百科全书”。迄今已经在自己的博客上发表了超过 3000 篇技术文章。2010 年,与 Eygle 共同主编出版了《Oracle DBA 手记》一书,2007 年被 Oracle 公司授予 ACE 称号。

事件背景

最近看到一个比较有意思的例子,是和更新重启动有关。

更新重启动是 Oracle 中一个隐藏的知识点,当 Oracle 在读取数据时,会构造读一致性,当读取的内容发生了修改,Oracle 会通过 UNDO 信息来还原数据的前镜像,把数据还原到查询发生的时刻,通过构造一致性的结果来实现读取数据的一致性和隔离性。

Oracle 实现的读一致性也被称为多版本读一致性,每个会话都会构造自己的一致性查询版本。但是对于写操作而言,这种方式是不可能的,因为最终的数据只有一份,如要要修改数据,就只能修改唯一的这份数据,所以对读操作,访问的是一致性版本,而对于写操作,修改的永远是当前版本。

既然写操作只能修改当前版本,当写操作执行的过程中,发现要修改的记录发生了变化,破坏了更新发起时刻的一致性,这时就触发了更新重启动,也就是说更新操作会放弃之前的修改,然后重新发起一次新的更新操作。

案例一

ITPUB 上有一个有意思的案例,展示的就是更新重启动现象,链接如下:

http://www.itpub.net/forum.php?mod=viewthread&tid=2102897

这里来重现一下更新重启动,建立一张简单测试用表,在会话一插入初始数据并进行更新操作:

SQL> SET SQLP 'SQL1> '

SQL1> CREATE TABLE T_UPDATE (ID NUMBER);

Table created.

SQL1> INSERT INTO T_UPDATE SELECT ROWNUM FROM DUAL CONNECT BY LEVEL < 4;

3 rows created.

SQL1> COMMIT;

Commit complete.

SQL1> SELECT * FROM T_UPDATE;

ID

----------

1

2

3

SQL1> UPDATE T_UPDATE SET ID = 4 WHERE ID > 2;

1 row updated.

在会话 2 发起 UPDATE 语句,更新 ID 大于 0 的记录,这时 UPDATE 操作由于会话 1 更新了 ID 为 3 的记录且未提交,会处于挂起状态:

SQL> SET SQLP 'SQL2> '

SQL2> UPDATE T_UPDATE SET ID = ID + 0.1 WHERE ID > 0;

然后在会话 3 插入一条新的记录,并提交:

SQL> SET SQLP 'SQL3> '

SQL3> INSERT INTO T_UPDATE VALUES (0.1);

1 row created.

SQL3> COMMIT;

Commit complete.

这时回到会话1,进行提交:

SQL1> COMMIT;

Commit complete.

检查会话 2,发现更新重启动发生,UPDATE 操作更新了 4 条记录:

4 rows updated.

SQL2> SELECT * FROM T_UPDATE;

ID

----------

1.1

2.1

4.1

.2

会话 2 中不仅更新了之前存在的三条记录,连更新语句发起之后插入并提交的第四条记录也一起进行了更新,这说明更新重启动发生在第四条记录插入之后。

论坛里问题的时序和结果如下,大家也可以参考这个范例,理解更新重启动的含义:

这个案例很好的展示了更新重启动现象,不过这个帖子并没有完,除了这个更新重启动的案例外,还展示了一个另外一个案例,操作和这个案例仅有很小的差别,但是结果却大不相同。

案例2

首先把数据恢复到初始状态,在会话 2 回滚之前的更新:

SQL2> ROLLBACK;

Rollback complete.

在会话1,恢复初始的数据情况,然后开始更新数据:

SQL1> DELETE T_UPDATE WHERE ID < 1;

1 row deleted.

SQL1> UPDATE T_UPDATE SET ID = 3 WHERE ID = 4;

1 row updated.

SQL1> COMMIT;

Commit complete.

SQL1> SELECT * FROM T_UPDATE;

ID

----------

1

2

3

SQL1> UPDATE T_UPDATE SET ID = 4 WHERE ID > 2;

1 row updated.

在会话 2,对表中所有的记录的 ID 执行 UPDATE 操作,和上一个案例的唯一差别是,这里没有使用 WHERE 语句:

SQL2> UPDATE T_UPDATE SET ID = ID + 0.1;

同样在会话3插入数据并提交:

SQL3> INSERT INTO T_UPDATE VALUES (0.1);

1 row created.

SQL3> COMMIT;

Commit complete.

回到会话1,进行提交:

SQL1> COMMIT;

Commit complete.

发现会话 2 仅更新了 3 条记录:

3 rows updated.

SQL2> SELECT * FROM T_UPDATE;

ID

----------

1.1

2.1

4.1

.1

可以清晰的看到,最后一条插入的记录并未被更新,说明更新重启动并未被触发。

对比分析

为什么带有 WHERE 条件的更新操作触发了更新重启动,而不带 WHERE 条件的更新未触发重启动呢,我是这样理解的:当 UPDATE 操作包含了 WHERE 条件,那么这个查询的结果要满足 WHERE 定义的查询一致性,当更新发现一致性不满足的情况下,就会触发更新重启动。

而对于不包含 WHERE 条件或包含 WHERE 条件但是该条件与表查询无关的情况,这时 Oracle 的目标只是将表中所有的数据进行一次更新,并不需要考虑一致性的问题。因此,这个不加 WHERE 条件的 UPDATE,感觉其实现方式上类似这种通过 ORA_ROWSCN 限定来实现:

SQL2> ROLLBACK;

Rollback complete.

回到会话 1 恢复数据,并检查 ORA_ROWSCN 的值:

SQL1> DELETE T_UPDATE WHERE ID < 1;

1 row deleted.

SQL1> UPDATE T_UPDATE SET ID = 3 WHERE ID = 4;

1 row updated.

SQL1> COMMIT;

Commit complete.

SQL1> SELECT ID, ORA_ROWSCN FROM T_UPDATE;

ID ORA_ROWSCN

---------- ----------

1  231512964

2  231512964

3  231512964

SQL1> UPDATE T_UPDATE SET ID = 4 WHERE ID > 2;

1 row updated.

在会话 2,发起包含制定 ORA_ROWSCN 限制条件的更新:

SQL2> UPDATE T_UPDATE SET ID = ID + 0.1 WHERE ORA_ROWSCN = 231512964;

会话 3 插入并提交:

SQL3> INSERT INTO T_UPDATE VALUES (0.1);

1 row created.

SQL3> COMMIT;

Commit complete.

回到会话 1,进行提交:

SQL1> COMMIT;

Commit complete.

检查会话2:

3 rows updated.

SQL2> SELECT * FROM T_UPDATE;

ID

----------

1.1

2.1

4.1

.1

采用 ORA_ROWSCN 的效果与直接 UPDATE 不带任何 WHERE 条件是一样的,说明更新只关注 UPDATE 语句发出时刻的数据,不再考虑整体更新结果的一致性问题。

关于更新重启动的更详细的描述,建议参考ASKTOM上的回复:

https://asktom.oracle.com/pls/apex/asktom.search?tag=write-consistency


作者:杨廷琨。

投稿:有投稿意向技术人请在公众号对话框留言。

转载:意向文章下方留言。

更多精彩请关注 “数据和云” 公众号


资源下载

关注公众号:数据和云(OraNews)回复关键字获取

2018DTCC , 数据库大会PPT

2017DTC,2017 DTC 大会 PPT

DBALIFE ,“DBA 的一天”海报

DBA04 ,DBA 手记4 电子书

122ARCH ,Oracle 12.2体系结构图

2017OOW ,Oracle OpenWorld 资料

PRELECTION ,大讲堂讲师课程资料

近期文章

仅仅使用AWR做报告? 性能优化还未入门

实战课堂:一则CPU 100%的故障分析

杨廷琨:如何编写高效SQL(含PPT)

一份高达555页的技术PPT会是什么样子?

大象起舞:用PostgreSQL解海盗分金问题

ProxySQL!像C罗一样的强大

高手过招:用SQL解决环环相扣刑侦推理问题

深入解析:你听说过Oracle数据库的更新重启动吗?相关推荐

  1. 在linux操作系统中启动oracle数据库程序,Linux系统下Oracle数据库的安装和启动关闭操作教程...

    这篇文章主要介绍了Linux系统下Oracle数据库的安装和启动关闭操作教程,并针对在sqlplus下所需执行的命令进行讲解,需要的朋友可以参考下 1.准备: df -H 查看空间剩余   一般准备最 ...

  2. Oracle数据库的四种启动方式

    Oracle数据库的四种启动方式 1.startup nomount 非安装启动:这种方式启动下可执行:重建控制文件.重建数据库 启动instance,即启动SGA和后台进程,这种启动只需要init. ...

  3. oracle 数据库文件损坏无法启动

    指定日志: {<RET>=suggested | filename | AUTO | CANCEL} auto ORA-00308: 无法打开归档日志 'D:\DIABLOORACLE\P ...

  4. oracle数据库从关闭到启动,Oracle数据库的启动和关闭详细过程

    一.数据库打开 startup数据库正常启动 1.startup nomount 启动 Oracle DB 实例:NOMOUNT ,创建sga,创建了alert日志,用于create db,creat ...

  5. 安装完Oracle数据库之后设置手动启动方法

    1.右击"我的电脑",选择"管理",在管理窗口左边选择"服务",在右边的服务列表中查找有关Oracle的        服务项,右击&quo ...

  6. 关闭oracle的几种方法,Oracle数据库的几种启动和关闭方式 | 旺旺知识库

    有以下几种启动方式: 1.startup nomount 非安装启动,这种方式启动下可执行:重建控制文件.重建数据库 读取init.ora文件,启动instance,即启动SGA和后台进程,这种启动只 ...

  7. Oracle数据库异常---OracleDBConsoleorcl无法启动

    1.windows不能在本地计算机启动OracleDBConsoleorcl.有关更多信息,查阅系统事件日志.如果这是非Microsoft服务,请与服务厂商联系,并参考特定服务错误代码 2. 2. 这 ...

  8. oracle数据库卡住了无法保存,Oracle数据库使用NFS存储,启动报错提示无法锁定文件...

    Oracle报错信息: SQLgt; startup gt; ORA-10997: another startup/shutdown operation of this instance inprog ...

  9. ORACLE数据库日期更新到时分秒格式

    插入数据库(更新到时分秒): UPDATE TOKEI_IN_BK_CSV SET USR_ID = 'VENAS',YMDT = to_date('2018/04/13 16:17:06','yyy ...

最新文章

  1. C++中引用的用法和应用实例
  2. OPMS 1.2 版本更新发布
  3. sse php,sse.php · Gitee 极速下载/modphp - Gitee.com
  4. IDEA 方法注释模板和类注释模板
  5. oracle用户手册在哪里,Oracle用户管理常用操作参考手册
  6. Leetcode: Palindrome Partition I II
  7. 基于Tablestore多元索引打造亿量级店铺搜索系统
  8. Hibernate的核心API
  9. 收藏 | Pytorch-lightning的使用
  10. Java日常编程优化细节
  11. 6、numpy之文件保存与加载
  12. 基于C++和QT实现的第三人称RPG游戏编辑器设计
  13. 【寻找最佳小程序】13期:心算练习——寓教于乐,练就小朋友强大的算术能力...
  14. 如何用计算机测量图片景深,用比较仔细的测量搞清楚“景深”(1.实测景深与公式比较)...
  15. 零知识证明(zero-knowledge proof)
  16. 数据库设计的基本步骤
  17. 【尝鲜】无视tpm安装win11 - 任何电脑皆可安装
  18. linux动态磁盘怎么转换,动态磁盘转换器【使用办法】
  19. c语言之圆的周长、面积、圆球的体积--改良版
  20. LeetCode第334题 递增的三元子序列(c++)(建议二刷)

热门文章

  1. 公有云 私有云 混合云_混合云不断变化的面貌
  2. krita绘图_使用Krita 2.9的Digital Painting提供了缺少的Krita文档
  3. 机器学习焦点,范德比尔特(Vanderbilt U)的医疗机器人以及更多开源新闻
  4. HTML min/maxlength
  5. HTML 表格的样式属性
  6. d3 和echart_D3.js与echart.js的应用场景
  7. oracle动态语句打开游标,Oracle动态语句中返回游标
  8. net 架构师-数据库-sql server-触发器
  9. Shell脚本之七 选择、循环结构
  10. No rule to make target ...