初识MySQL事务
了解了MySQL事务中的隔离级别,继续学习关于事务的基本知识。
死锁
死锁是指两个或者多个事务在同一个资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁。
锁的行为和顺序是和存储引擎相关的。以同样的顺序执行语句,有些存储引擎会产生死锁,有些则不会。死锁的产生有双重原因: 有些是因为真正的数据冲突,这种情况通常很难避免,有些则完全是由于存储引擎的实现方式导致的。
InnoDB中处理死锁的两种策略:
- 设置锁等待超时时间,通过
innodb_lock_wait_timeout
,意味着当死锁出现后,第一个被锁住的线程要过了设定时间才退出,其他线程才可能继续执行。 - 主动死锁检测:
innodb_deadlock_detect
默认设置为on,主动死锁检测在发生死锁时,能够快速发现并处理。
事务日志
事务日志可以提高事务的效率,使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘。事务日志采用的是追加的方式。因此写日志的操作是将磁盘上的一小块区域内的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头,所以事务日志的方式相对来说要快的多。事务日志持久化后,内存中修改的数据可以在后台慢慢刷回磁盘。
启动方式
- 显示启动事务,begin或start transaction,直到显式地执行commit或者rollback回滚,该事务结束。
- set autocommit=1,也是MySQL默认采用的自动提交模式。每个查询都会被当作一个事务执行提交操作。
1
2
3
4
5
6
7
8
9mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)
mysql>
隐式和显式锁定
InnoDB采用两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时可以执行锁定,锁只有在执行commit或rollback的时候才会释放,并且所有的锁是在同一时候被释放。属于隐式锁定,InnoDB会根据隔离级别在需要的时候自动加锁。
InnoDB也支持通过特定的语句进行显式锁定,这些语句不属于SQL规范,实际应尽量避免使用:
1 | SELECT ... LOCK IN SHARE MODE |