第一个前提:事务是存储引擎层面支持的,InnoDB支持事务,MyISAM不支持事务。本文都是指的InnoDB。
第二个前提 :MySQL默认设置autocommit = on
,即任何语句若没有显示地开启事务,都被当做一个独立的事务进行执行 —— Even a select statement opens a transaction
老生常谈,说起事务,就得先提一下事务的ACID特性
以上隔离级别由1-4,并发性能越来越差,隔离程度越来越深。InnoDB默认的隔离级别是可重复读,而大部分互联网公司设置的线上隔离级别是读提交。通过show variables like 'tx_isolation'
可以查看数据库事务级别。
有个我觉得很有意思能帮助理解的例子,看这里,对于“脏读”,“不可重复读”,“幻读”的解释,例子里也说的很清楚~
解决以上“脏读”,“不可重复读”,“幻读”有两种思路,一个就是加锁,另外一个就是MVCC(Multi-version Concurrency Control)即数据多版本并发控制。MVCC的目的:让读写互相不阻塞,提高事务并发处理的能力。MVCC的核心思想:提供数据的历史版本,即我记录的不是一个静态的2D的表,而是一个“3D”的表,每个数据还有一个维度是他的版本号(transaction id/trx_id,该id按照先后严格递增)。
InnoDB在实现MVCC的时候,用到了一致性视图(consistent read view)。这个视图和我们查询的时候的视图不是一个同一个东西。这个一致性视图其实是根据数据的最新版本和undo log(回滚日志)计算出来的。
以可重复读举例,事务一开始的时候,就创建了一个一致性视图,该视图的数据,如上所述是根据数据当时的最新版本和undo log计算出来的。而这个视图计算出的数据满足以下条件:
总的来说,就是根据当前最新数据,和undo log,找到一个提交过的最新版本,作为一致性视图。
一个栗子