oracle幻读如何解决,oracle怎么解决幻读
什么是oracle数据库隔离级别
1.查看当前会话隔离级别
创新互联建站是一家专业提供临洮企业网站建设,专注与成都网站设计、成都做网站、HTML5、小程序制作等业务。10年已为临洮众多企业、政府机构等服务。创新互联专业网站制作公司优惠进行中。
select @@tx_isolation;
2.查看系统当前隔离级别
select @@global.tx_isolation;
3.设置当前会话隔离级别
set session transaction isolatin level repeatable read;
4.设置系统当前隔离级别
set global transaction isolation level repeatable read;
5.命令行,开始事务时
set autocommit=off 或者 start transaction
关于隔离级别的理解
1.read uncommitted
可以看到未提交的数据(脏读),举个例子:别人说的话你都相信了,但是可能他只是说说,并不实际做。
2.read committed
读取提交的数据。但是,可能多次读取的数据结果不一致(不可重复读,幻读)。用读写的观点就是:读取的行数据,可以写。
3.repeatable read(MySQL默认隔离级别)
可以重复读取,但有幻读。读写观点:读取的数据行不可写,但是可以往表中新增数据。在MySQL中,其他事务新增的数据,看不到,不会产生幻读。采用多版本并发控制(MVCC)机制解决幻读问题。
4.serializable
可读,不可写。像java中的锁,写数据必须等待另一个事务结束。
1.3 REPEATABLE READ(可重复读)
1.设置为可重复读
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2.首先TB做出一次查询,此时name为bb
3.TA对数据进行修改,并提交
4.此时加入session C作为对比,使用自动事务并做出查询,可见数据已经被修改
5.在已经开启事务的TB中,查询到的,仍然是数据开启事务之前的状态,所以数据是可重复读的
可重复读隔离级别中,每当事务开始后,第一次执行sql语句时(或者执行START TRANSACTION WITH CONSISTENT SNAPSHOT)MVCC会建立一个read view,选取当时的系统版本号,作为事务版本号,以Undo log的行系统版本号与事务版本号进行对比,增删改查都要遵循如下模式:
SELECT:
1, InnoDB只查找版本早于当前事务版本的数据行(行的系统版本号小于等于事务版本号),这样可以确保事务读取的行,要么是事务开始前就存在的,要么是事务自身插入的或修改过的。
2, 行的删除号要么未定义,要么大于当前事务版本号,这样可以确保事务读取到的行,在事务开始之前未被删除。
INSERT:
InnoDB 为新插入的每一行保存当前系统版本号做为行版本号。
DELETE:
INNODB 为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE:
InnoDB 为插入的每一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。
所以READ COMMITTED和REPEATABLE READ的区别在于,READ COMMITTED总是读取被锁定行的最新一份快照数据, 所以会有不可重复读的问题。而REPEATABLE READ读取事务开始时行系统版本号小于事务版本号的数据,解决不可重复读的问题。
此外要提的一点是,MySql的REPEATABLE READ与Oracle的不同,不但解决了不可重复读问题,还解决的“幻读”问题。
幻读的产生:遵循上述增删改查模式,假设TA事务的事物版本号为3,TB早于TA开启事务,TB事物版本号为2,TB先新增一条数据,行数据的版本号为2,并提交。TB提交后,TA查询时,满足“行的系统版本号小于等于事务版本号”的条件,可以查到数据,形成“幻读”。
InnoDB采用Next-key Lock(间隙锁)来避免“幻读”问题。
Record Lock:单个行记录的锁,锁定的是索引而非记录本身。
GAP Lock:间隙锁,锁定一个范围,但不包含记录本身。
Next-Key Lock:Gap Lock+Record Lock 锁定一个范围并锁定记录本身。
举例说明:
某表字段为ID和NAME,有3条睡觉,ID分别为10,20,50。
如果索引为 10,20,50,那么:
Record Lock:select * from tab where id = 10 for update; //对id=10单行进行加锁
Gap Lock锁范围:(-∞,10)(10,20)(20,50)(50,+∞)
Next-Key Lock锁范围:(-∞,10] (10,20] (20,50] (50,+∞)
当查询的索引含有唯一属性时,InnoDB会对Next-Key Lock进行优化,将其降级为Record Lock,即仅锁住索引本身,而不是范围。
虽然避免了幻读问题,但是还有个特殊情况,感觉可以叫做“幻改”,即当前事务修改了本身并不能查询到的数据。这也是MVCC造成的假象,当前事务虽然查询不到其他事务提交的数据,但是可以对其他事务提交的数据进行修改。
事务隔离的四个级别是什么?
事务隔离的四个级别是未提交读(Read Uncommitted)、提交读(Read Committed)、可重复读(Repeable Read)、可串行化(Serializable)。
1、未提交读(Read Uncommitted):事务可以读取未提交的数据,也称作脏读(Dirty Read)。一般很少使用。
2、提交读(Read Committed):是大都是DBMS(如:Oracle,SQLServer)默认事务隔离。执行两次同意的查询却有不同的结果,也叫不可重复读。
3、可重复读(Repeable Read):是MySQL默认事务隔离级别。能确保同一事务多次读取同一数据的结果是一致的。可以解决脏读的问题,但理论上无法解决幻读(Phantom Read)的问题。
4、可串行化(Serializable):是最高的隔离级别。强制事务串行执行,会在读取的每一行数据上加锁,这样虽然能避免幻读的问题,但也可能导致大量的超时和锁争用的问题。很少会应用到这种级别,只有在非常需要确保数据的一致性且可以接受没有并发的应用场景下才会考虑。
事务隔离级别特点比较
从事务隔离级别的定义上可以看出,Serializable级别隔离性最高,但是其效率也最低,因为其要求所有操作相同记录的事务都串行的执行。
对于MySql而言,其默认事务级别是Repeatable read,虽然在定义上讲,这种隔离级别无法解决幻读的问题,但是MySql使用了一种Next key-lock的算法来实现Repeatable read,这种算法是能够解决幻读问题的。
关于Next key-lock算法,在进行查询时,其不仅会将当前的操作记录锁住,也会将查询所涉及到的范围锁住。
也就是说,其他事务如果想要在当前事务查询的范围内进行数据操作,那么其是会被阻塞的,因而MySql在Repeatable read隔离级别下就已经具备了Serializable隔离级别的事务隔离性。
以上内容参考:百度百科-隔离级别
网页题目:oracle幻读如何解决,oracle怎么解决幻读
标题路径:http://pwwzsj.com/article/hogdhj.html