MYSQl中的事务
本博客中研究的都是InnoDB引擎
1.自动提交
MYSQL默认采用自动提交(auto commit)模式,也就是说,如果不是显式的开始一个事务,则每个查询都被当作一个事务执行提交操作。在当前的连接中可以通过设置autocommit变量来启用或者进用自动提交模式。
show VARIABLES LIKE 'AUTOCOMMIT';
命令来查看是否启用自动提交。
MYSQL还可以通过执行
SET TRANSCTION ISOLATION LEVEL命令来设置隔离级别。新的隔离级别会在下一个事务开始的时候生效。可以在配置文件中设置整个数据苦的隔离级别,有可以只改变当前会话的隔离级别。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITED;
2.在事务中混合使用存储引擎
MYSQL服务器层部管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中使用多种存储引擎是不可靠的。
在非事务型的表上执行事务相关的操作的时候,MYSQl通常是不会发出提醒,也不会报错。有时候回滚到时候才会发出一个警告:“某些非事务型的表上的变更不能被回滚”。不要报太高期望。
3.隐式锁定和显式锁定
InnoDB采用的式两阶段锁定协议(two-phase locking protocol).在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放的。前面描述的锁定都是隐式锁定,InnoDB会根据隔离级别在需要的时候自动加锁。
另外,InnoDB也支持通过特定的语句进行显式锁定,这些语句不属于SQL规范。
select ..... LOCK IN SHARE MODE
select .... FOR UPDATE
MYSQL也支持Lock TABLES 和UNLOCK TABLES 语句,这是在服务器层实现的,和存储引擎无关。它们有自己的用途,但是并不能替代事务处理。如果应用需要用到事务,还是应该选择事务型的存储引擎。
多版本并发控制
MYSQL的大多数事务型存储引起实现都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC).不仅是Mysql,包括Oracle,PostgreSQL等其他树控件系统也都实现了MVCC,但各自的实现机制不尽相同,因为MVCC没有统一的实现标准。
可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞读操作,写操作也只锁定必要的行。
MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。如果之前没有这方面的概念,这句话听起来有点迷糊。熟悉了以后就会发现,这句话其实还是很容易理解的。
MVCC实现的方式有典型的有如下几种:
乐观(optimistic)并发控制、悲观(pessimistic)并发控制。
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两列一个保存了行的创建时间,一个保存了行的过期时间(或删出时间)。当然存储的并不是实际的实际值,而是系统版本号(system version number).每开始一个新的事务,系统版本号就会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来查询到的每行记录的版本号进行比较。下面看一下在REPEATABLE READ隔离级别下,MVCC具体是如何操作的。
这里要介绍一下行锁的三种:
1.普通的行锁,只能锁定本行记录
2.gap间隙锁,锁定一个范围除了本行
3.next-key ,锁定 范围带自己本行
MYSQl 的MVCC
MVCC 的核心就是 Undo Log+ Read View,“MV”就是通过 Undo Log 来保存数据的历史版本,实现多版本的管理,“CC”是通过 Read View 来实现管理,通过 Read View 原则来决定数据是否显示。同时针对不同的隔离级别,Read View 的生成策略不同,也就实现了不同的隔离级别。