平常的业务场景中,会出现多事务并发访问数据库的场景,首先咱们看一下在不考虑事务隔离级别,并发访问数据库的状况下,可能出现的几类问题。mysql
一、第一类丢失更新:A开启A事务,B开启B事务,数据count=100,B事务执行count+10=110,提交B事务。A事务回滚事务,count被从新回滚到100,B事务所作提交丢失。(A事 务撤回使B事务已做的提交失效)。这种问题现代关系型数据库已经不会发生。程序员
二、第二类丢失更新:A开启A事务,B开启B事务,数据count=100,B事务执行count+10=110,提交B事务。A事务接着执行count-10=90,提交事务,count变为90,B事务所作提交 丢失。(A事务提交覆盖了B事务的提交)sql
三、脏读:A开启A事务,B开启B事务,数据库count=100,事务B执行count+10=110,可是未提交,事务A读取count=110。事务B回滚,count从新变为100,可是此时事务A一直以 为count=110。(A事务读取了B事务未提交,后面又回滚的更改)数据库
四、不可重复读:A开启A事务,B开启B事务,数据count=100,A事务第一次查询count=100,B事务执行count+10=110,提交事务,A事务第二次查询count=110。(A事务两次读取 同一数据不同)安全
五、幻读:A开启A事务、B开启B事务,A事务根据where条件查询出1条数据,B事务插入或删除了符合同一where条件的1条数据,提交事务,A事务根据同一where条件第二次查询 出2条或0条数据。(A事务两次读取的记录条数不同)并发
咱们须要根据不一样的场景屏蔽不一样的问题,并非上述每种问题,咱们都须要避免,过多的控制会带来性能上的丢失。因此数据库提供了四种事务隔离机制。性能
一、读未提交(read uncommited):顾名思义,即一个事务对数据进行更改后尚未提交,别的事务依然能够读取这个更改(原理:事务在读取的时候没有加任何锁)。这种级别在实 际中不多用到,由于数据安全性过低,只能避免第一类丢失更新。事务
二、读已提交(read commited):在一个事务修改数据的过程当中,若是没有提交,其余事务不能读取这个改变(原理:更新时加行级排它锁,直到事务结束,读取时加行级共享锁,一 旦读完该行,当即释放)。这种级别能够避免脏读。it
三、可重复读(repeatable read):在一个事务读取数据的过程当中,若是没有提交,其余事务不能更改这个数据(原理:更新时加行级排它锁,直到事务结束,读取时加行级共享锁,直 到事务结束)。这种级别能够避免脏读和不可重复读以及第二类丢失更新,也是mysql的默认隔离级别。table
四、序列化(serializable):能够解决其余级别都不能解决的幻读(原理:读取时加表级共享锁,直到事务结束,更新时加表级排他锁,直到事务结束)。
上述咱们提到了锁,其实这也是数据库实现数据安全的重要手段。从程序员的角度,锁能够分为悲观锁和乐观锁;从数据库系统的角度,锁能够分为共享锁、更新锁和排它锁;从锁的粒度上,又能够分为行级锁和表级锁。关于锁的部分,咱们见下一节。