oracle如何保证数据一致性和避免脏读
oracle通过undo保证一致性读和不发生脏读
1.不发生脏读
例如:用户A对表更新了,没有提交,用户B对进行查询,没有提交的更新不能出现在用户的查询结果中
举例并通个dump数据块说明避免脏读的原理
创建测试表,并插入两条记录,会话A执行更新但不提交
SQL>select*from test;
ID NAME
--------------------
1 A
2 B
SQL> update test set name='C'where id=2;
1 row updated.
会话B查询,数据没变
SQL>select*from test;
ID NAME
--------------------
1 A
2 B
通过下面sql语句查询数据所在的数据文件和块号,并进行dump
SQL>select id, rowid, dbms_rowid.rowid_relative_fno(rowid) fn,dbms_rowid.rowid_block_number(rowid) bk from test order by id;
ID ROWID FN BK
------------------------------------------------
1AAAzkeAAIAAAACDAAA8131
2AAAzkeAAIAAAACDAAB8131
SQL> alter system dump datafile 8 block 139;
System altered.
未提交的数据块dump结果
ItlXidUbaFlagLckScn/Fsc
0x010x0002.001.000a90a20x00c00093.9f1d.16 C---0 scn 0x0000.395178de
0x020x0007.010.000a93c50x00c00f4b.9f5d.34----1 fsc 0x0000.00000000
---上面事务槽中Flag为----从0x00c00f4b undo地址中读取
bdba:0x0200008b
data_block_dump,data header at 0x7fb742fc8a64
===============
tsiz:0x1f98
hsiz:0x16
pbl:0x7fb742fc8a64
76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f88
avsp=0x1f70
tosp=0x1f70
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f90
0x14:pri[1] offs=0x1f88
block_row_dump:---下面是表中数据行的dump
tab 0, row 0,@0x1f90
tl:8 fb:--H-FL-- lb:0x0 cc:2
col 0:[2] c1 02
col 1:[1]41--第一行 A
tab 0, row 1,@0x1f88
tl:8 fb:--H-FL-- lb:0x2 cc:2---lb为0x2说明未提交
col 0:[2] c1 03
col 1:[1]43---第二行 C
end_of_block_dump
说明:通过上面的dump文件发现,数据已经被修改成C(43),但是Oracle发现这条数据有lb: 0x2 对应的是ITL,从ltl为0x02的记录看到flag为—-,表示有事务标记,数据被加锁,需要从undo段的uba(undo block address)中读取
undo段中对应的块信息为:0x00c00f4b,这里是十六进制,下面先转换成10进制
SQL>select to_number('00c00f4b','XXXXXXXXXXXXXXX')from dual;
TO_NUMBER('00C00F4B','XXXXXXXXXXXXXXX')
---------------------------------------
12586827
得到值为12586827
对undo块进行dump
在通过下面的语句得到数据块信息:
SQL>select dbms_utility.data_block_address_file(12586827), dbms_utility.data_block_address_block(12586827)from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(12586827) DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(12586827)
---------------------------------------------------------------------------------------------
33915
SQL>select file#,name from v$datafile where file#=3;
FILE# NAME
------------------------------------------------------------
3/u01/app/oracle/oradata/FGLDB/undotbs01.dbf
SQL> alter system dump datafile 3 block 3915;
System altered.
dump内容如下:
*-----------------------------
*Rec#0x34 slt: 0x10 objn: 211231(0x0003391f) objd: 211231 tblspc: 4(0x00000004) --objd 为object id
*Layer:11(Row) opc:1 rci 0x00
Undo type:Regular undo Begin trans Last buffer split:No
TempObject:No
TablespaceUndo:No
rdba:0x00000000Ext idx:0
flg2:0
*-----------------------------
uba:0x00c00f4b.9f5d.25 ctl max scn:0x0000.39516d48 prv tx scn:0x0000.39516db3
txn start scn: scn:0x0000.395178de logon user:83
prev brb:12586818 prev bcl:0
KDO undo record:
KTB Redo
op:0x03 ver:0x01
compat bit:4(post-11) padding:1
op: Z
ArrayUpdate of 1 rows:
tabn:0 slot:1(0x1) flag:0x2clock:0 ckix:12
ncol:2 nnew:1 size:0
KDO Op code:21 row dependencies Disabled
xtype:XAxtype KDO_KDOM2 flags:0x00000080 bdba:0x0200008b hdba:0x0200008a
itli:2 ispac:0 maxfr:4858
vect =3
col 1:[1]42--- undo中数据为B
从undo块中发现值为B(42),故其他用户看到的是B,看不到C,避免了脏读
附:提交后的数据块dump结果
ItlXidUbaFlagLckScn/Fsc
0x010x0002.001.000a90a20x00c00093.9f1d.16 C---0 scn 0x0000.395178de
0x020x0007.010.000a93c50x00c00f4b.9f5d.34 C---0 scn 0x0000.39517d7a
---Flag为C---
bdba:0x0200008b
data_block_dump,data header at 0x7fa3c77efa64
===============
tsiz:0x1f98
hsiz:0x16
pbl:0x7fa3c77efa64
76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f88
avsp=0x1f70
tosp=0x1f70
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f90
0x14:pri[1] offs=0x1f88
block_row_dump:
tab 0, row 0,@0x1f90
tl:8 fb:--H-FL-- lb:0x0 cc:2
col 0:[2] c1 02
col 1:[1]41
tab 0, row 1,@0x1f88
tl:8 fb:--H-FL-- lb:0x0 cc:2--- lb为0x0
col 0:[2] c1 03
col 1:[1]43
end_of_block_dump
总结:数据库通过判断数据块头部的ITL槽的信息来确定是否有未提交的事务,如果事务槽Flag为—-,则通过事务槽中的undo块地址查询到原来的数据,进而达到数据隔离的效果,避免脏读。
2.一致性读
例如:假设某一个用户A在6点对某一个表发出了一个查询数据量很大的数据,需要15分钟才能把结果完全查询出来,在这期间,6点10分用户B对数据进行了更新并提交了,用户A查询的结果仍然是6点时候的表的数据,用户B更新的数据不出现在用户A的查询结果中,这就是一致性读。
- 用户A在执行开始的时候会记录当时的SCN号,如图中10021
在每次从数据块中读数据的时候会比较记录的SCN号和数据块事务槽中的SCN号(下一个事务的SCN号一定比当前的大)
a.如果数据块中的SCN比当前分配的SCN号小,则认为该数据没有被修改,直接读取;
b.如果数据块中的SCN号比当前分配的SCN大,则根据块中保存的地址去undo中读取当时分配SCN时间点的数据(根据undo数据块在内存中重新构造出该数据块,称为consistent read (CR)块)一个查询如果耗费很长时间,而查询的结果在查询的阶段被更改了,而且对应着undo段的数据已经被清理了,就会发生Oracle中著名的ORA-01555: snapshot too old(快照太久)错误。
如果一条数据在查询期间被更新过多次并且提交,后放入undo段的块会记录相对的块上次放在undo段中的块地址,从而一路寻找到查询开始时间点在undo段中的数据块。
3. 事务槽(ITL)小解
ITL(Interested Transaction List)是Oracle数据块内部的一个组成部分,位于数据块头(block header),itl由xid,uba,flag,lck和scn/fsc组成,用来记录该块所有发生的事务,一个itl可以看作是一条事务记录。当然,如果这个事务已经提交,那么这个itl的位置就可以被反复使用了,因为itl类似记录,所以,有的时候也叫itl槽位。如果一个事务一直没有提交,那么,这个事务将一直占用一个itl槽位,itl里面记录了事务信息,回滚段的入口,事务类型等等。如果这个事务已经提交,那么,itl槽位中还保存的有这个事务提交时候的SCN号。
Xid:事务id,在回滚段事务表中有一条记录和这个事务对应
Uba:回滚段地址,该事务对应的回滚段地址
- 第一段地址:回滚数据块的地址,包括回滚段文件号和数据块号
- 第二段地址:回滚序列号
- 第三段地址:回滚记录号
–查看UBA
SELECT UBAFIL undo_file_id,UBABLK undo_blk_num,UBASQN undo_segment_num,UBAREC undo_recode_num FROM v$transaction;
Flag:事务标志位。这个标志位就记录了这个事务的操作,各个标志的含义分别是:
- —– = 事务是活动的,或者在块清除前提交事务
- C— = 事务已经提交并且清除了行锁定。
- -B– = this undo record contains the undo for this ITL entry
- –U- = 事务已经提交(SCN已经是最大值),但是锁定还没有清除(快速清除)。
- —T = 当块清除的SCN被记录时,该事务仍然是活动的,块上如果有已经提交的事务,
那么在clean ount的时候,块会被进行清除,但是这个块里面的事务不会被清除。
Lck:影响的记录数
Scn/Fsc:快速提交(Fast Commit Fsc)的SCN或者Commit SCN。
每条记录中的行级锁对应于Itl列表中的序号,即哪个事务在该记录上产生的锁。
关注公众号:数据库技术分享,不定期分享技术干货
oracle如何保证数据一致性和避免脏读的更多相关文章
- MySQL 是怎么保证数据一致性的(转载)
在<写数据库同时发mq消息事务一致性的一种解决方案>一文的方案中把分布式事务巧妙转成了数据库事务.我们都知道关系型数据库事务能保证数据一致性,那数据库到底是怎么设计事务这一特性的呢? 一. ...
- ZooKeeper 如何保证数据一致性?
在分布式场景中,ZooKeeper 的应用非常广泛,比如数据发布和订阅.命名服务.配置中心.注册中心.分布式锁等. 在分布式场景中,ZooKeeper 的应用非常广泛,比如数据发布和订阅.命名服务.配 ...
- 【面试普通人VS高手系列】Redis和Mysql如何保证数据一致性
今天分享一道一线互联网公司高频面试题. "Redis和Mysql如何保证数据一致性". 这个问题难倒了不少工作5年以上的程序员,难的不是问题本身,而是解决这个问题的思维模式. 下面 ...
- Dynamo分布式系统——「RWN」协议解决多备份数据如何读写来保证数据一致性,而「向量时钟」来保证当读取到多个备份数据的时候,如何判断哪些数据是最新的这种情况
转自:http://blog.jqian.net/post/dynamo.html Dynamo是Amazon开发的一款高可用的分布式KV系统,已经在Amazon商店的后端存储有很成熟的应用.它的特点 ...
- oracle如何保证读一致性 第二弹
Oracle之数据库一致性读的原理 在Oracle数据库中,undo主要有三大作用:提供一致性读(Consistent Read).回滚事务(Rollback Transaction)以及实例恢复(I ...
- oracle如何保证读一致性 第一弹
oracle保证读一致性原理 1:undo segment的概念 当数据库进行修改的时候,需要把保存到以前的old的数据保存到一个地方,然后进行修改,用于保存o ...
- ZK集群如何保证数据一致性源码阅读
什么是数据一致性? 只有当服务端的ZK存在多台时,才会出现数据一致性的问题, 服务端存在多台服务器,他们被划分成了不同的角色,只有一台Leader,多台Follower和多台Observer, 他们中 ...
- MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- 通俗理解ZooKeeper是如何保证数据一致性的
https://blog.csdn.net/liuhaiabc/article/details/70771322 https://blog.csdn.net/zhaoyangjian724/artic ...
随机推荐
- Redis哨兵日志说明
一.说明
- ICEM-interface相关操作
原视频下载地址: https://pan.baidu.com/s/14Tx-eYPccvhrg5wrg7gYvw 密码: 8fdp
- 利用Wireshark抓取并分析OpenFlow协议报文
OpenFlow 交换机与控制器交互步骤 1. 利用Mininet仿真平台构建如下图所示的网络拓扑,配置主机h1和h2的IP地址(h1:10.0.0.1,h2:10.0.0.2),测试两台主机之间的网 ...
- YARN 状态机可视化,生成状态机图
由于在windows下面,配置好所有 编译hadoop2.4.1源码 的环境会很麻烦,好在我之前已经把hadoop2.4.1的源码成功导入eclipse,并解决了所有错误提示,所以我就可以在eclip ...
- MYSQL | ERROR 1305(42000) SAVEPOINT *** DOES NOT EXIST
autocommit模式:在开启情况下,对于每条statement来说,都会自动形成一个commit,也就是会即时对开始和结束一个事务.所以,当出现rollback to savepoint出现这个错 ...
- [转] Filezilla server设置指南及中文乱码、登录欢迎语问题解决
一.filezilla server 安装指南:FileZilla是一款免费而且开源的FTP工具.包括FileZilla Client,FileZilla Server两个版本.FileZilla S ...
- centos7使用MariaDB(转)
转载文章:https://blog.csdn.net/zwkkkk1/article/details/78444581?locationNum=10&fps=1 最近使用centos7,php ...
- js实现replaceAll方法
js本来有replace方法,请看w3school的说明: replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 语法: stringObject.rep ...
- 小D课堂 - 零基础入门SpringBoot2.X到实战_第8节 数据库操作之整合Mybaties和事务讲解_32..SpringBoot2.x持久化数据方式介绍
笔记 1.SpringBoot2.x持久化数据方式介绍 简介:介绍近几年常用的访问数据库的方式和优缺点 1.原始java访问数据库 开发流程麻烦 ...
- mac PHP安装imageMagic扩展
1. 安装:ImageMagick:命令:brew install ImageMagick这种方式安装下来的imageMagic,不缺少东西,报错较少.安装之后的位置:/usr/local/Cella ...