oracle数据库,只有两种隔离级别:read committed和serializable。
简单的说,read committed是语句级隔离,serializable是事务级隔离,read committed意思是指,在你操作数据期间,就是指事务期间,可以看到别人操作commit的结果,serializable是指操作数据期间,就是事务期间,看不到别人操作commit的结果,简单的将,就是在事务开始的时候,给做了一个快照一样,别人在同一个表里的操作commit是看不到的。
serializable是最高级别的事务隔离,一般来说,应该是非常重要或者极其重要的数据,在长时间或者较长时间内处理的时候,不希望自己正在处理的数据被改变,有人说,我们不是在处理数据的时候,加上锁了吗?怎么还会被改变呢,实际情况是,确实会被改变,这是因为oracle默认隔离级别是read committed,阻止脏读(看不到别人未提交的数据),但是不阻止非重复读和幻象。
一、先考虑隔离级别对select查询的影响。
serializable隔离级别,是事务级隔离,按照这个概念,在事务开始或者将事务隔离级别确定为serializable后,就确定了SCN,然后根据这个SCN和系统SCN比对,来确定查询是否进入撤销段。
也就是说,隔离级别是否对select有影响,如何影响,在这个事务期间,能否看到和自己事务不冲突的“其他人动过”的数据。这个有待于验证。
已经验证,在连接后,事务隔离级别更改为serializable后,确实无法看不到别人commit的操作结果,应该可以确定,在事务隔离级别更改后,本事务就被隔离,完全看不到别人的操作,也就是说,已经给数据库拍了个快照,这时候事务能看到的是一个静态的数据库。
二、隔离级别serializable引发冲突
serializable是最高隔离级别,对数据的操作要求非常霸道,针对同一行数据时,通俗的讲,就是我update或者delete(insert估计没有影响)这行数据的时候,任何其他用户不能动,动了的话,我就直接报错。
现在假定,事务1(read committed隔离)对A行数据更新,不提交,然后事务2(serializable隔离)对A行数据更新,这时候锁定机制存在,事务2开始等待。下一步,事务1,使用commit提交。界面再回到事务2上,就是发现,报错ora08177,这就是说,事务2的serializable隔离级别,要求我在开始操作数据的时候,不允许别人操作数据,由于默认脏读已经被隔离,所以这里指的不允许别人操作数据的动作应该是commit,而不是dml动作。
这里可以看出一点,serializable隔离级别,好像很不喜欢锁排队机制,上面的举例,是每次都准确的,也就是说,serializable隔离级别的事务,一旦被阻塞,需要排队等待锁,那么有50%或者更高的几率会报错,这是因为dml操作的最后结果有两个:commit和rollback。按照概念上的理解,rollback应该不会引发错误。
三、serializable隔离级别的用途
serializable是最高的隔离级别,针对的应该是非常重要或者及其重要的数据,或者说要求查询出来的结果,在事务期间,多个查询结果必须完全一致,不能被其他用户变动,这样的要求可以使用serializable隔离级别,其他一般用途建议还是使用默认隔离级别。
serializable隔离级别,考虑应该是为了保持隔离,也就是彻底隔离别个用户对本用户的影响,或者从用户角度看,就是我先完成事务,其他事务才能继续,实际情况只是这个用户被完全隔离,完全看不到别个用户所做的操作。
四、serializable隔离级别的缺点
1是这种隔离级别,需要的撤销数据会增加很多,从实际情况看,在事务确定更改隔离级别为serializable后,系统可能会检测到有高隔离级别事务存在,从而增加需要保存的撤销数据,以便能够提供一个读一致性快照,这个要注意的是,这个读一致性快照,是一个全面性的快照,也就是说很可能的是,因为serializable隔离级别事务存在,很多撤销段,状态是unexpired,不过期,就是事务已经提交,但是因为读一致性要求,数据库希望这个撤销段继续保持,不重写。在一个高并发的数据库中,长时间或者较长时间存在一个serializable隔离级别的事务,意味着数据库可能认为需要提供一个很长时间保持存在的读一致性快照,从而进一步增加撤销空间,这样会浪费服务器资源,可能导致其他用户事务停止或者非常缓慢,或者导致dml无法执行,因为无法扩展撤销段或者指定撤销段(撤销段全被serializable隔离级别使用的读一致性快照占用)。
2是serializable隔离级别,在这个事务期间,如果有dml操作,那么就会导致这个事务等待,从而可能这个事务dml操作失败,也就是ora08177。网络上的ora08177错误,往往是一个测试,或者一个表,但是如果实际操作中,serializable隔离级别的事务,长时间或者较长时间存在,那么实际情况比测试更加严重,因为这个高隔离级别的事务,可能针对多个表进行dml操作,同时可能和多个用户发生ora08177错误。
五、serializable隔离级别
从实际测试可以看出,serializable隔离级别,其实际目的是想当某个特定用户,在某个特定时间,在一个高并发、数据改变频繁的数据库里面,能够看到一个静态的、不发生改变的数据库,也就是一个大的数据快照。
实际用途应该是结算、或者数据转移等等,也就是,业务要求,我在操作期间,数据不要改变,这时候可以使用serializable隔离级别,这种高隔离级别的事务,要结合你所拥有的服务器资源考虑,来考虑其事务执行时间,要切记不要长时间保持这种高隔离级别事务的存在,因为时间一长,撤销数据就增加很快,资源消耗,会导致数据库性能下降,影响其他用户体验。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9606200/viewspace-1435691/
,如需转载,请注明出处,否则将追究法律责任。