数据库事务隔离级别

web开发过程中数据都是从数据库取出来的。因为在实际项目中数据库的访问都是多线程的,这就不可避免的出现下次呢很难过安全问题。有可能用户A在查询数据,而用户B在修改数据。那么用户A在查询数据的时候就很可能查询到错误的数据,也就是脏读。解决脏读之类的线程安全问题有很多方案,设置数据库的隔离级别也是众多的解决方案之一。但是数据库的访问量大,盲目的为了数据安全而设置很高的数据库事务隔离级别是会牺牲掉很大的执行效率的,所以应该按照具体的系统需求去设计。今天我们只讲和数据库事务隔离级别有关的知识点。

数据库事务隔离级别

数据库事务的隔离级别主要有四种,这四种级别依次升高

1)读未提交(read-uncommitted)

2)读已提交(read-committed)

3)可重复读(repeatable-read)

4)可串行化(serializable)

在介绍各个事务隔离级别之前,我们首先来解释几个概念

脏读

脏读就是读到了错误的数据,比如有两个线程中的连个事务同时对数据库中的同一条数据进行操作。事务A开启——>执行select num from goods where code="a";的到商品a的数量是10。在事务A未提交之前,事务B开启——>执行update goods set num =num-1 where code="a";在B事务还没有提交之前,A事务再次去数据库中查询select num from goods where code="a";这时事务A查询出来的数量是9。A事务在得到这个结果之后提交。此时事务B因为某种未知的原因将数据回滚了。数据库中商品a的数量变回了10。这个时候事务A拿到的数据就是错误的数据就发生了脏读。

不可重复读

不可重复读的意思就是在同一个事务中多次查询数据得出的结果不一致。不可重复读和脏读比较相似,不同点是脏读强调的是一个事务读取到了另一个事务还没有提交的事务中的数据。而不可重复读强调同一个事务中读取同一条数据得到的结果不用。

不可重复读的栗子是在事务A访问数据库查询某一条数据时,事务B也在修改该数据。事务A开启——>执行select num from goods where code = "a";得到结果10。在事务A未提交之前,事务B开启——>执行update goods set num=num-1 where code="a";此时事务A有一次执行select num from goods where code="a";得到结果9。两次查询结果不一致,因为数据不一致所以不能重复读,重复读数据会有问题。

幻读

幻读和不可重读相似,都是关注的事务执行中的情况。不通点是不可重复读关注的是数据的修改,而幻读关注的是数据的添加和删除。

比如,事务A开启——>执行select * from goods where code ="b";执行的结果是没有该数据。此时事务B开启——>执行insert into goods (code,num)values ("b",10);事务B提交。此时事务A执行insert into goods (code,num)values ("b",10);会报错。因为goods表中主键code重复。那么事务A那次读取数据的操作就是幻读。

下面我们来说各个数据库事务隔离级别的特点

读未提交(read-uncommited)

读未提交的意思就是可以读取还没有提交的事务的数据。A数据去读数据,B事务对数据进行了修改还没提交。A读到的数据是B没有提交的数据。因为B还没提交,所以B可能会回滚,所以此时读到的数据可能是脏数据,就是会发生脏读。也有可能B事务多次修改数据,那么A事务多次读取数据的结果就可能不一样,因为同一个事务中查询同一条数据出现多个结果,那么就可能出现不可重复读现象。同样的B事务可能正在添加或者删除数据,也会出现幻读现象。

读已提交(read-committed)

读已提交即只能读取已经提交了的内容。事务A开启后执行查询select num from goods where code = "a";得到商品a的数量是10。这时事务B开启并修改商品a的数量为9,但是事务B不提交。此时事务A再去查询商品a的数量发现商品a的数量还是10。没有读取到事务B中未提交的数据。解决了脏读。如果事务B提交,A事务再去查询,得到数量9,事务A多次查询得出的结果不一样出现不可重复读现象。同样的原因也会出现幻读现象——事务B添加了数据,但是事务B提交之前A事务读不到该数据,出现幻读。

可重读(repeatable-read)

可重读的事务隔离级别是mysql数据库默认的数据库隔离级别。就是在同一个事务中,如果该事务中没有对数据进行修改那么读取的数据不管读取多少次都是一样的结果。比如,事务A开启——>查询商品a的数量,得出结果10。此时事务B开启——>执行修改商品a的数量的命令,将数量修改为9;并提交。此时事务A再次读取数据发现结果还是10。同样的原因,也会出现幻读——事务B添加了一条数据并提交。但是事务A在它的事务中反复查询数据是查不到事务B添加的数据的。

可串行化(serializable)

可串行化是最高级别的数据库事务隔离级别。数据库给事务强行排序。强制给读取的数据行加共享锁。使其他事务不能对表进行修改、添加、删除,避免了脏读、不可重复读、和幻读的现象,但是会导致大量的超时现象。效率低。

以上就是关于数据库事务隔离级别的内容了。以上内容均是本人在查阅了部分资料之后的理解。可能会有错误的地方,如果有疑问欢迎讨论

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180628G1NKV700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券