数据库事务隔离级别

事务的隔离性是通过加锁的方式获得的,锁会降低系统的性能,所以事务提供了控制隔离级别程度的机制。如果使用较高的隔离级别,则事务会比较好的与其他事务隔离开来,但是也会带来大量的系统开销;而使用了较低的隔离级别,事务的隔离性较差,但是能获得较好的系统性能。

事务的隔离级别分为四种:READ_UNCOMMITED、READ_COMMITED、REPEATABLE_READ、SERIALIZABLE。

要理解以上四种隔离级别,先要清楚以下几个概念:脏读、不可重复读、幻影读取。

一,假设同一个数据库,同时并发A和B两个操作,A和B执行的任务如下:从数据库中读取整数N,然后将N加上10,再更新回数据库。这两个并发执行的操作可能会发生下面的实行顺序。

1.A从数据库读取到整数N,当前数据库中N=0;

2.A操作将N加上10,并将N更新到数据库,当前数据库中N=10。然而由于A的事务还未提交,所以数据库更新还没能成为持久性的;

3.B操作从数据库中读取整数N,当前数据库中N=10;

4.此时,A操作发生异常,做了事务回滚,所以数据库中N恢复到了N=0;

5.B操作将N加上了10,并将N更新到数据库,使得当前数据库中N=20;

以上执行顺序出现了B在A提交之前读取了A所更新的数据,由于A回滚了事务,所以数据库中出现了错误的数据N=20。尽管A回滚了事务,但是A更新的数据还是间接的通过B操作被更新到了数据库中,这种读取了未提交的数据的方法就是脏读(dirty)问题。

二,两个用户U1 和 U2,当U1从数据库中读取数据N时,U2修改了这条数据N,所以数据N发生了改变,U1再次读取N时就出现了不可重复读取的问题,比如:

1.U1从数据库中读取整数N,此时数据库中N=0;

2.U2操作N,将N加上了10,并更新到数据库,此时N=10;

3.当U1再次读取N时,会发现N值变了,读到了N=10;

三,还有就是幻影读取,幻影读取时指两次数据库读取操作之间,一组新的新居会出现在数据库中。比如:

1.A操作从数据库检索到了一些数据;

2.B操作使用Insert语句向数据库中插入了一些新数据;

3.A再次查询的时候,发现查到了新的数据

根据以上的场景分析,再了解下四种事务隔离级别的概念

1)使用read_uncommited级别,会导致脏读问题、幻影读取问题和不可重复读取问题。在需要敏感计算任务的事务中,这样的模式是不太适合的;

2)使用read_commited级别,可以解决脏读问题,但是还会有幻影读取问题和不可重复读问题。这种级别做报表较合适。Oracle数据库默认使用该隔离级别;

3)使用repeatable_read级别,可以解决脏读问题和不可重复读取问题,但是会有幻影读取问题,MySQL 默认使用了该隔离级别;

4)使用serializable级别可以解决脏读问题、幻影读取问题和不可重复读取问题。这事最严格的事务隔离级别;

使用建议

一般主流的DBMS都提供了启动、提交以及回滚事务的机制,也提供了指定锁粒度、隔离级别的机制,不过这些机制一般是随着DBMS的不同而不同的,请参考具体DBMS的说明文档。比如在MSSQLServer中执行一个read_uncommited级别的事务SQL语句如下:

Set  transaction isolation level read uncommited
begin transaction
--具体操作
commit

 

posted @ 2017-03-19 11:32  zhouzh(水金)  阅读(157)  评论(0)    收藏  举报