数据库事务隔离级别
事务的隔离性是通过加锁的方式获得的,锁会降低系统的性能,所以事务提供了控制隔离级别程度的机制。如果使用较高的隔离级别,则事务会比较好的与其他事务隔离开来,但是也会带来大量的系统开销;而使用了较低的隔离级别,事务的隔离性较差,但是能获得较好的系统性能。
事务的隔离级别分为四种: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

浙公网安备 33010602011771号