日常的业务场景中,会出现多事务并发访问数据库的场景,首先我们看一下在不考虑事务隔离级别,并发访问数据库的情况下,可能出现的几类问题。

1、第一类丢失更新:A开启A事务,B开启B事务,数据count=100,B事务执行count+10=110,提交B事务。A事务回滚事务,count被重新回滚到100,B事务所做提交丢失。(A事                                      务撤回使B事务已作的提交失效)。这种问题现代关系型数据库已经不会发生。

2、第二类丢失更新:A开启A事务,B开启B事务,数据count=100,B事务执行count+10=110,提交B事务。A事务接着执行count-10=90,提交事务,count变为90,B事务所做提交                                   丢失。(A事务提交覆盖了B事务的提交)

3、脏读:A开启A事务,B开启B事务,数据库count=100,事务B执行count+10=110,但是未提交,事务A读取count=110。事务B回滚,count重新变为100,但是此时事务A一直以                    为count=110。(A事务读取了B事务未提交,后面又回滚的更改)

4、不可重复读:A开启A事务,B开启B事务,数据count=100,A事务第一次查询count=100,B事务执行count+10=110,提交事务,A事务第二次查询count=110。(A事务两次读取                            同一数据不一样)

5、幻读:A开启A事务、B开启B事务,A事务根据where条件查询出1条数据,B事务插入或删除了符合同一where条件的1条数据,提交事务,A事务根据同一where条件第二次查询                   出2条或0条数据。(A事务两次读取的记录条数不一样)

我们需要根据不同的场景屏蔽不同的问题,并不是上述每种问题,我们都需要避免,过多的控制会带来性能上的丢失。所以数据库提供了四种事务隔离机制。

1、读未提交(read uncommited):顾名思义,即一个事务对数据进行更改后还没有提交,别的事务依然可以读取这个更改(原理:事务在读取的时候没有加任何锁)。这种级别在实                                                       际中很少用到,因为数据安全性太低,只能避免第一类丢失更新。

2、读已提交(read commited):在一个事务修改数据的过程中,如果没有提交,其他事务不能读取这个改变(原理:更新时加行级排它锁,直到事务结束,读取时加行级共享锁,一                                                   旦读完该行,立即释放)。这种级别可以避免脏读。

3、可重复读(repeatable read):在一个事务读取数据的过程中,如果没有提交,其他事务不能更改这个数据(原理:更新时加行级排它锁,直到事务结束,读取时加行级共享锁,直                                                     到事务结束)。这种级别可以避免脏读和不可重复读以及第二类丢失更新,也是mysql的默认隔离级别。

4、序列化(serializable):可以解决其他级别都不能解决的幻读(原理:读取时加表级共享锁,直到事务结束,更新时加表级排他锁,直到事务结束)。

上述我们提到了锁,其实这也是数据库实现数据安全的重要手段。从程序员的角度,锁可以分为悲观锁和乐观锁;从数据库系统的角度,锁可以分为共享锁、更新锁和排它锁;从锁的粒度上,又可以分为行级锁和表级锁。关于锁的部分,我们见下一节。

版权声明:本文为nick-xlj原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/nick-xlj/p/10932791.html