oracle读一致性与SCN解惑

thinkpadshi 2015-12-16 04:46:04
加精
如下两个问题有点困惑,请高手解释一下:

1.oracle的读一致性指的是,用户只会看到commit之后的数据,还是用户只会看到查询操作开始这个时间点时的数据?

2.oracle中scn号是commit之后产生的,还是commit之前产生的,如果是commit之后产生的,那么在commit之前scn都没有,还怎么用比较scn号大小的方法来实现读一致性呢?
...全文
2692 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
lsy721 2016-09-24
  • 打赏
  • 举报
回复
似乎拿火车票的例子更容易理解些
thinkpadshi 2015-12-24
  • 打赏
  • 举报
回复
引用 14 楼 ad1983 的回复:
为什么没有提示信息?
什么提示信息?
thinkpadshi 2015-12-24
  • 打赏
  • 举报
回复
引用 14 楼 ad1983 的回复:
为什么没有提示信息?
什么提示信息?
God眯眯眼 2015-12-24
  • 打赏
  • 举报
回复
学习
shpppppp 2015-12-23
  • 打赏
  • 举报
回复
学习了!!!!!!!!!!
thinkpadshi 2015-12-23
  • 打赏
  • 举报
回复
引用 9 楼 LHDZ_BJ 的回复:
忽略,因为它不符合一致性视图条件。
我刚在测试库测试了一下,我写了一条select语句(300万数据,exists了另一个数据库中的2000万数据),大概 需要6分钟执行完,我取select结果集中的最后一条的id,然后在某个时间点再次执行这个select语句用create table tmp select * from 这种形式把select的结果集放入tmp表中,当然这需要6分钟左右,然后我在第一时间(大概create语句执行2秒之后),update了上述的最后一条数据,并提交,耗时1秒钟,然后6分钟左右的时候,create语句执行完毕,我从tmp表中可以找到那个中途update的数据,而且还是update之前的原始数据,那这个应该可以证明oracle不会直接忽略scn号比查询发出时的scn号还大的记录,而是去undo中找修改之前的数据吧?
ad1983 2015-12-23
  • 打赏
  • 举报
回复
为什么没有提示信息?
ad1983 2015-12-23
  • 打赏
  • 举报
回复
不能证明,建议在严密的理论推导下做测试,这样才有意义。 该贴相关话题已经说了很多,恕不再回复,见谅。
lhdz_bj 2015-12-23
  • 打赏
  • 举报
回复
不能证明,建议在严密的理论推导下做测试,这样才有意义。 该贴相关话题已经说了很多,恕不再回复,见谅。
thinkpadshi 2015-12-22
  • 打赏
  • 举报
回复
引用 3 楼 LHDZ_BJ 的回复:
我从来没说过scn是在commit之后产生的,是你自己这么理解的。 获取一个scn并将其写入数据块头部是commit操作的一个环节,commit完成前,新的scn不会写入数据块头部。因此,像你说的那个场景,你讲的过程是不对的。当查询读取一个数据块时,如果发现该数据块的scn大于查询开始时的scn,直接忽视。如果发现scn小于或等于开始时的scn,如果有未提交的事务,就去通过undo构建cr数据块,否则,就直接读取该数据块。
恩,非常感谢上述解答,但是还有如下疑问 第一:“当查询读取一个数据块时,如果发现该数据块的scn大于查询开始时的scn,直接忽视”,当该数据块的scn大于查询开始时的scn时,说明此改变是在查询开始之后提交的,不应该直接忽视,而是也应该去undo中读取为修改之前的数据吧,否则直接忽视的话,岂不是造成数据丢失了? 第二:“如果发现scn小于或等于开始时的scn,如果有未提交的事务”,如何判断已修改但未提交?比对是否产生undo日志吗?如果查询的每一条记录都这么判断会不会显著降低查询性能?
lhdz_bj 2015-12-22
  • 打赏
  • 举报
回复
忽略,因为它不符合一致性视图条件。
thinkpadshi 2015-12-22
  • 打赏
  • 举报
回复
引用 7 楼 LHDZ_BJ 的回复:
查询数据,是为了查询数据库中存在的数据,既然update了,那这个数据就变为update后的了,update之前的数据就不存在了,而这个update后的数据,是不符合条件的,也就是不符合比查询开始时的scn大这个条件的。现实中,我们统计任何数据,也是要定一个时间点的,例如:统计人口,统计到2010.12.31前出生的人口,统计期间,也许会有新出生的,但不会被统计进去,不然,这个工作也许就永远做不完了;其他统计,也会定一个类似的截止日期的。这样做,是为了最终结果的一致性,这样才会有意义。 没提交的数据之所以构造cr块来查它的前影像,是因为现在的数据没生成,如果必须等现在的数据生成,那就得等事务提交并释放锁,这会降低数据库的并发性,这也是个折衷方案。之前的SQL SERVER,DB2数据库就是一直等,所以导致它们的并发性不好,Oracle就是凭借这种折衷的、巧妙的MVCC机制才赢得广大用户而占领了绝对的市场地位。现在所有关系库,也都支持这种mvcc,就是为了改善数据库的并发性。 数据库中的数据,代表的是现实中的一个个实体,每个字段代表的是实体的属性,比如:人的肤色,人的身高,人的年龄,人的性别等。现实世界中的实体,虽然时刻在变化着,但任何一个时刻,只能有一个客观体代表这个实体,而不能同时有多个客观体代表这一个实体,而属性,在任何时刻,也只能有一个。再做个比喻,就像一个人,虽然时刻在变化,但他不可能同时有多个躯体,只能从20岁的样子变到21岁的样子,不能既有一个20岁的,还有一个21岁的;岁数也是,只能有一个岁数,不能既是20岁,又是21岁。。。,这是从数据库理论的角度分析你提出的问题,希望这些能让你理解。
说的非常好,又扩展了我的视野,回到原来的问题,还是有点疑问, 比如:1:00时刻我查询select name from table where addr = '上海',数据量大,需要10分钟,但是在查询开始后一分钟,1:01时刻有人update table set name = 'thinkpad' where addr='上海' and id = '1',且提交,这个时候当数据库查询到这条已修改的数据时,scn号肯定比查询发出时的大,这个时候它是直接忽略这条记录还是去undo中查找修改之前的数据?
lhdz_bj 2015-12-22
  • 打赏
  • 举报
回复
查询数据,是为了查询数据库中存在的数据,既然update了,那这个数据就变为update后的了,update之前的数据就不存在了,而这个update后的数据,是不符合条件的,也就是不符合比查询开始时的scn大这个条件的。现实中,我们统计任何数据,也是要定一个时间点的,例如:统计人口,统计到2010.12.31前出生的人口,统计期间,也许会有新出生的,但不会被统计进去,不然,这个工作也许就永远做不完了;其他统计,也会定一个类似的截止日期的。这样做,是为了最终结果的一致性,这样才会有意义。 没提交的数据之所以构造cr块来查它的前影像,是因为现在的数据没生成,如果必须等现在的数据生成,那就得等事务提交并释放锁,这会降低数据库的并发性,这也是个折衷方案。之前的SQL SERVER,DB2数据库就是一直等,所以导致它们的并发性不好,Oracle就是凭借这种折衷的、巧妙的MVCC机制才赢得广大用户而占领了绝对的市场地位。现在所有关系库,也都支持这种mvcc,就是为了改善数据库的并发性。 数据库中的数据,代表的是现实中的一个个实体,每个字段代表的是实体的属性,比如:人的肤色,人的身高,人的年龄,人的性别等。现实世界中的实体,虽然时刻在变化着,但任何一个时刻,只能有一个客观体代表这个实体,而不能同时有多个客观体代表这一个实体,而属性,在任何时刻,也只能有一个。再做个比喻,就像一个人,虽然时刻在变化,但他不可能同时有多个躯体,只能从20岁的样子变到21岁的样子,不能既有一个20岁的,还有一个21岁的;岁数也是,只能有一个岁数,不能既是20岁,又是21岁。。。,这是从数据库理论的角度分析你提出的问题,希望这些能让你理解。
thinkpadshi 2015-12-22
  • 打赏
  • 举报
回复
引用 5 楼 LHDZ_BJ 的回复:
1、怎么会数据丢失?根据一致性理论,你提交查询时要得到的结果就是那个时刻之前的结果,块的scn大于查询发出时的scn,就意味着那个块本来就不在你的结果范围内。就像你计算你目前拥有的金钱,难道会算上下个月,明年,今后几十年挣的钱吗? 2、数据行被修改后会持有行锁,这些行锁直到commit后才会被释放,select时会看到要查的结果数据行上有行锁,就知道是修改了还未提交,此时,就通过相应的信息获取undo信息构造cr块,直到构造的cr数据库的scn小于查询开始时的scn为止。这样也许会影响性能,但为了获取一致性数据,你或其他任何人有更好的办法吗?如果有且可行的话,那这个人就不得了了,呵呵。
哈哈,第二个问题回答的很好,我也理解了,赞一个! 第一个问题,有关数据丢失的,假如是update过的数据,已提交,其scn大于查询发出时的scn,这时候没法直接忽略这些update过的数据吧?难道不应该也去undo中查找更新之前的数据?
lhdz_bj 2015-12-22
  • 打赏
  • 举报
回复
1、怎么会数据丢失?根据一致性理论,你提交查询时要得到的结果就是那个时刻之前的结果,块的scn大于查询发出时的scn,就意味着那个块本来就不在你的结果范围内。就像你计算你目前拥有的金钱,难道会算上下个月,明年,今后几十年挣的钱吗? 2、数据行被修改后会持有行锁,这些行锁直到commit后才会被释放,select时会看到要查的结果数据行上有行锁,就知道是修改了还未提交,此时,就通过相应的信息获取undo信息构造cr块,直到构造的cr数据库的scn小于查询开始时的scn为止。这样也许会影响性能,但为了获取一致性数据,你或其他任何人有更好的办法吗?如果有且可行的话,那这个人就不得了了,呵呵。
lhdz_bj 2015-12-21
  • 打赏
  • 举报
回复
我从来没说过scn是在commit之后产生的,是你自己这么理解的。 获取一个scn并将其写入数据块头部是commit操作的一个环节,commit完成前,新的scn不会写入数据块头部。因此,像你说的那个场景,你讲的过程是不对的。当查询读取一个数据块时,如果发现该数据块的scn大于查询开始时的scn,直接忽视。如果发现scn小于或等于开始时的scn,如果有未提交的事务,就去通过undo构建cr数据块,否则,就直接读取该数据块。
thinkpadshi 2015-12-19
  • 打赏
  • 举报
回复
引用 1 楼 兰花岛主的回复:
1、查询开始时间点之前已经commit的数据。 2、scn,system change number,scn是一直增长的,每次提交,系统会为这个事务获取一个scn,并写到数据块的头部,事务的一致性读,就是通过它来控制的。
那也就是说scn号是在commit之后产生的,在判断读一致性时是根据scn号的大小去控制的,比如事务开始时最大的scn号是1000,当读到此事务开始之后有人修改过但未提交的数据时,比如这次修改的scn是1001,系统一看比事务开始时最大的scn号1000还大,就直接去undo中读取被修改之前的数据来保持读一致性,但是这是基于scn号是在修改数据之后,commit之前产生的,那就跟你说的commit之后产生的矛盾了
lhdz_bj 2015-12-17
  • 打赏
  • 举报
回复
1、查询开始时间点之前已经commit的数据。 2、scn,system change number,scn是一直增长的,每次提交,系统会为这个事务获取一个scn,并写到数据块的头部,事务的一致性读,就是通过它来控制的。

3,490

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧