MySQL事务之隔离级别
在MySQL事务之控制演进 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中提到对于并发事务,采用锁机制解决。对于并发中出现的数据一致性问题,如“更新丢失”、”脏读”、“不可重复读”和“幻读”等,MySQL数据库是通过事务隔离级别来解决的,数据库系统提供了以下 4 种事务隔离级别供用户选择:
1)读未提交
Read Uncommitted 读未提交:解决了回滚覆盖类型的更新丢失,但可能发生脏读现象,也就是可能读取到其他会话中未提交事务修改的数据。
2)已提交读
Read Committed 读已提交:只能读取到其他会话中已经提交的数据,解决了脏读。但可能发生不可重复读现象,也就是可能在一个事务中两次查询结果一致。
3)可重复度
Repeatable Read 可重复读:解决了不可重复读,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上会出现幻读,简单的说幻读指的的当用户读取某一范围的数据行时,另一个事务又在该范围插入了新行,当用户在读取该范围的数据时会发现有新的幻影行。
4)可串行化
Serializable 串行化:所有的增删改查串行执行。它通过强制事务排序,解决相互冲突,从而解决幻度的问题。这个级别可能导致大量的超时现象的和锁竞争,效率低下。
数据库的事务隔离级别越高,并发问题就越小,但是并发处理能力越差(代价)。读未提交隔离级别最低,并发问题多,但是并发处理能力好。以后使用时,可以根据系统特点来选择一个合适的隔离级别,比如对不可重复读和幻读并不敏感,更多关心数据库并发处理能力,此时可以使用Read Commited隔离级别。
事务隔离级别,针对Innodb引擎,支持事务的功能。像MyISAM引擎没有关系。
那锁和隔离级别之间是不是该有点关系呢?事务隔离级别和锁的关系如下:
1)事务隔离级别是SQL92定制的标准,相当于事务并发控制的整体解决方案,本质上是对锁和MVCC使用的封装,隐藏了底层细节。
2)锁是数据库实现并发控制的基础,事务隔离性是采用锁来实现,对相应操作加不同的锁,就可以防止其他事务同时对数据进行读写操作。
3)对用户来讲,首先选择使用隔离级别,当选用的隔离级别不能解决并发问题或需求时,才有必要在开发中手动的设置锁。
MySQL默认隔离级别:可重复读;Oracle、SQLServer默认隔离级别:读已提交。
一般使用时,建议采用默认隔离级别,然后存在的一些并发问题,可以通过悲观锁、乐观锁等实现处理。
下面具体示范MySQL如何利用锁实现隔离级别控制:
MySQL隔离级别可通过查看当期数据库事务隔离级别命令获取:show variables like '@tx_isolation'; 或select @tx_isolation;
上图示例,说明没有设置事务隔离级别。
设置事务隔离级别可以如下命令:
set @tx_isolation='READ-UNCOMMITTED';
set @tx_isolation='READ-COMMITTED';
set @tx_isolation='REPEATABLE-READ';
set @tx_isolation='SERIALIZABLE';