这篇文章涉及到数据库锁的概念,个人一篇关于数据库锁的博客:http://www.javashuo.com/article/p-ywdxblsb-ms.html.html
这里的讨论是以innodb引擎做为基础,一个事务在执行前会去获取本身须要的全部锁,事务提交或者回滚后释放锁.mysql
事务隔离级别有如下五种:sql
1. TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务能够读取另外一个事务修改但尚未提交的数据。该级别不能防止脏读,不可重复读和幻读,所以不多使用该隔离级别。好比PostgreSQL实际上并无此级别。数据库
这个是最低的一种隔离级别,没有任何防范措施.安全
2. TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另外一个事务已经提交的数据。该级别能够防止脏读,这也是大多数状况下的推荐值。并发
脏读产生的缘由是一个事务A对一行数据进行了修改,随后回滚了.另外一个事务B在事务A回滚以前读到了被修改的那一行数据,这样在事务A回滚以后,事务B的数据就是脏数据.该隔离级别下修改数据行时会加上写锁(排它锁),当事务读取被加锁的数据行时,会从undo log中获取最近的数据,这样事务B就不能读取到事务A未提交的数据,从而防止了脏读,可是会产生不可重复读和幻读.oracle
3. TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程当中能够屡次重复执行某个查询,而且每次返回的记录都相同。该级别能够防止脏读和不可重复读。性能
不可重复读产生的缘由是事务A在第一次读取一行数据以后,另外一个事务B对该行数据进行了修改而且提交,而后事务A再一次读取该行数据,会发现两次读取数据不一致.在该隔离级别下,事务读取数据时会加上读锁(共享锁),共享锁与排它锁不能共存,因此这样就可以保证本身在读取事务时,数据不会被其余事务修改,从而防止了不可重复读,可是会产生幻读.spa
4. TransactionDefinition.ISOLATION_SERIALIZABLE:全部的事务依次逐个执行,这样事务之间就彻底不可能产生干扰,也就是说,该级别能够防止脏读、不可重复读以及幻读。可是这将严重影响程序的性能。一般状况下也不会用到该级别。code
幻读产生的缘由是事务A在对多行数据进行操做,例如将全部知足条件A的数据所有修改成X这样的批量操做时,事务B插入了一条知足条件A的可是数据值不为X的值,这样事务A再次查询时,就会发现有一行没有被修,产生了执行失败的幻觉.以上说的隔离级别都是对要操做的数据行进行加锁实现的,而幻读是进行insert操做产生的,insert是插入了一条新数据行,锁是没法影响到insert操做的,因此该隔离级别经过让事务串行执行,从而达到防止幻读的功能.
以上都是基于悲观锁,有他的实现原理就可以看出来,他们的并发性不是很好,因此大多成熟的数据库,例如mysql,oracle等都会采用一种基于乐观锁的并发控制-----MVCC(多版本并发控制).
MVCC具体原理之后理解深入了在写,这里先说一下我如今对MVCC的理解:咱们不考虑隔离级别,单纯的考虑MVCC的话,他不能防止脏读,不可重复读,幻读,他的做用是为了提升事务的并发度,由上面的各个隔离级别能够看出,隔离级别越高,并发度越低,MVCC就是在下降隔离级别的同时提升安全性.举一个例子:咱们使用REPEATABLE_READ隔离级别时会出现幻读,可是咱们的系统要杜绝幻读,但是咱们不想使用SERIALIZABLE隔离级别,由于并发度过低了,这个时候MVCC的做用就体现出来了,虽然他不能杜绝幻读,可是若是使用了MVCC的话,那么在REPEATABLE_READ隔离级别加上MVCC机制下,可能出现幻读的状况我只能想到一种:
当前系统版本号0,数据版本号0->事务A开启版本号1,系统版本号1->事务B开启版本号2,系统版本号2->事务B执行update->事务A执行insert,数据版本号2->事务B执行select,查询版本号<=2,幻读发生
若是想要彻底杜绝幻读,那么咱们能够给程序增长保险机制,例如:里面使用一个循环操做,每次update以后再查询数据库是否还有为更改的数据,这样的操做确定会很费时间.可是咱们使用了MVCC以后,发生幻读的几率降低,那么进入保险机制的几率就被减少,因此提升了并发度,同时解决了幻读问题.