Nov,2019
今儿做了很多的业务需求,对接了几个接口,算是比较充实吧。想起了同事说的那句话,越忙的时候,越要停下来好好思考,抽空整理整理,不然就会很快陷入一个死循环里面去,最近也要好好整理整理之前学的一些东西了,一个清晰的条理,才能让你事半功倍。今天就补充一点之前遗漏的内容吧。
Innodb锁机制探究(一)---自增锁(2)
//
之前我们说过一篇关于MySQL的自增锁,但是没有系统的做测试,今天做一点测试,看看效果。如果不记得之前的文章了,没关系,传送门放在这里。
innodb锁机制探究(一)---自增锁(1)
当我们进行插入操作的时候,该操作会根据这个自增长的计数器的值 1赋予自增长的列,这个操作我们称之为auto-inc Locking,也就是自增长锁,这种锁其实采用的是特殊的表锁机制,如果insert操作出现在一个事务中,这个锁是在insert操作完成之后立即释放,而不是等待事务提交。
参数innodb_autoinc_lock_mode的参数来控制自增长的模式,它的取值可以是0,1,2,代表的含义上面的文章中有讲过。这里不再赘述。
来看我们的测试过程,为了理解方便,我们首先创建一个表,然后查看相关的参数:
代码语言:javascript复制mysql:yeyztest ::>>show create table lock_test1G
*************************** 1. row ***************************
Table: lock_test1
Create Table: CREATE TABLE `lock_test1` (
`id` int() NOT NULL AUTO_INCREMENT,
`age` int() DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
row in set (0.00 sec)
mysql:yeyztest ::>>show variables like '%innodb_autoinc_lock_mode%';
-------------------------- -------
| Variable_name | Value |
-------------------------- -------
| innodb_autoinc_lock_mode | |
-------------------------- -------
row in set (0.00 sec)
可以看到,这个表lock_test1有两个字段,分别是id和age字段,而参数innodb_autoinc_lock_mode的值设置为1,然后画图说明一下整个测试流程:
通过上面这张图我们可以看到,当我们在一个事务中进行自增列的insert操作时候,另外一个会话中又进行了插入记录的操作,在这种情况下,会发生2个奇怪的现象:
1、会话1中的自增列好像直接增加了2个值。
2、会话2中的自增列直接从2开始增加。
在官方文档上,我们可以看到这句话:
An AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns. In the simplest case, if one transaction is inserting values into the table, any other transactions must wait to do their own inserts into that table, so that rows inserted by the first transaction receive consecutive primary key values.
翻译过来就是:自增锁是一种特殊的表级别锁(table-level lock),专门针对事务插入AUTO_INCREMENT类型的列。最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。
那么为什么表级别的锁,我们还能够在会话1中的事务没有结束的时候,在另外一个会话2上成功执行insert呢?不应该直接锁表么?它的本质其实是在参数innodb_autoinc_lock_mode上,这个参数设置为1的时候,相当于将这种auto_inc lock弱化为了一个更轻量级的互斥自增长机制去实现,官方称之为mutex。
总结一下:
1、auto_inc lock 本身是一种表级别的锁。
2、对于常规的insert操作,可以使用参数innodb_autoinc_lock_mode来控制是否使用表级别的锁,如果该参数是0,则使用表级别的auto_inc 锁,如果该参数是1,则使用互斥自增长机制实现主键的自增。(关于这个参数,强烈建议读开头的那一篇文章。)
3、事务内部插入的id值可能会不连续。