意向锁便是InnoDB使用的表级锁,当表t第11中学列a已经有一个值为1的事态下

在类型中时常会有那种须求,用户通过第一方系统登录时一旦没有注册,则自动给用户注册,注册过的用户自行登录。有时候图方便恐怕就一贯INSERT INTO user ON DUPLICAET KEY UPDATE...一句
SQL
化解了,成效都平常,难点正是若是用户表中有auto_increment字段,则会造成auto_increment字段发生空洞难题,一段时间后会发现用户ID会日常出现不一连的动静,尽管mysql的自增ID可以相当大,一般系统是够用的,可是对于性冷淡病人那几个是不可能经受的。作者测试的mysql版本为5.5.58,使用的是Innodb引擎,隔开分离级别为Repeatable
Read。

1.Locking

1 场景

当用户从第③方登录时,假定用的是手提式有线电话机号做唯一标识,日常在我们协调的系列中会建叁个用户表,如下:

 CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `mobile` varchar(11) DEFAULT NULL,
  `last_login_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `mobile` (`mobile`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

当用户从第一方登录时,大家校验通过后,会将手提式有线电话机号插入到user表里登记用户。借使用户已经存在,则更新最后登录时间,为了便利,日常像上边这么做,功用上看起来是没错的,难题便是运维一段时间后会发现user表的id字段居然是不总是的,而且平常多少个id之间空洞还相当大,比如上2个id是4,下四个改为了21。如上面例子中,再插入一条新记录时,id会变成3,也便是说id=2这一个值被荒废了。

mysql> INSERT INTO user(mobile, last_login_time) VALUES('15012345678',
 NOW()) ON DUPLICATE KEY UPDATE last_login_time = NOW();
Query OK, 1 row affected (0.00 sec)

mysql> show create table user;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                               |
+----------------------------------------------------------------------+
| user  | CREATE TABLE `user` (
......
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 |

mysql> INSERT INTO user(mobile, last_login_time) VALUES('15012345678', 
NOW()) ON DUPLICATE KEY UPDATE last_login_time = NOW();
Query OK, 2 rows affected (0.00 sec)

mysql> show create table user;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                               |
+-------+---------------------------------------------------------------------
| user  | CREATE TABLE `user` (
......
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 |

1.1加锁格局:共享锁与独占锁

InnoDB达成了两类行级锁, shared(S)locks 和exclusive(X)locks

  • 共享锁用于工作读取
  • 独占锁用于工作更新或许去除
  • S锁与S锁不冲突,与X锁争辨;X锁与S锁争持,与X锁争持

2 分析

在MySQL官方文档已经提到过那一个题目了实在,当表t第11中学列a已经有1个值为1的意况下,平日状态实施下边那两条语句效果是同等的,唯独注意了,倘若表t1是InnoDB引擎而且有一列为auto_increment的场合下,影响是不雷同的,会时有发生眼下提到的auto_increment空洞难点。MyISAM引擎的表不受此影响,不会生出空洞难点。

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE t1 SET c=c+1 WHERE a=1;

更为确切的说,爆发空洞难点还跟innodb_autoinc_lock_mode本条MySQL配置相关。该配置在MySQL5.1引入,是为着提高auto_increment字段的出现质量引入的,暗中认可值为1。该值能够布署为0(traditional lock mode),1(consecutive lock mode),2(interleaved lock mode),除了0基本不发生空洞外,配置其余值都以唯恐有auto_increment空洞的,不难总括如下,更详尽的可以参考
innodb-auto-increment-handling

  • 1)如若事情回滚了,则无论是0,1,2都会促成工作中选择过的auto_increment的值浪费。

  • 2)假若设置为0,是traditional lock mode,则任意插入语句都会加
    AUTO-INC 锁,基本不会发出空洞,除了第11中学的rollback情状外。

  • 3)就算设置为1要么2的时候,simple inserts话语(simple
    inserts指的是那种能够先行明确插入行数的说话,比如INSE奥迪Q7T/REPLACE INTO
    等插入单行只怕多行的讲话,语句中不包涵嵌套子查询)不会有空洞。但是对于bulk inserts(bulk
    inserts指的是先期不能显著插入行数的说话,比如INSECR-VT/REPLACE INTO …
    SELECT FROM…, LOAD DATA等)和mixed-mode inserts(指的是simple
    inserts类型中稍微行钦点了auto_increment列的值多少尚未点名,比如:INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d')INSERT ... ON DUPLICATE KEY UPDATE那种话语)会优分auto_increment值,导致有的浪费。
    尤其是设置为2的时候,在执行任意插入语句都不会加 AUTO-INC
    锁,从而在言语执行进程中都想必发生空洞。

1.2加锁粒度:意向锁

InnoDB援救多粒度锁,也正是行锁与表锁的存活。意向锁正是InnoDB使用的表级锁,评释了工作之后对于那个表所必要行级锁的品类(S|X)。因而意向锁也分为Intention
shared(IS)和Intention exclusive(IX)。

For
example,SELECT ... LOCK IN SHARE MODE
sets an IS lock and
SELECT ... FOR UPDATE
sets an IX lock.

反过来说,在获得S|X锁之前,必要得到相应的IS(或IX)|IX锁。
而那一个锁的相容表如下:

X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

3 一种错误示范

那为了减小第四节中的auto_increment空洞难题,一种艺术正是INSE奥迪Q3T前先判断下用户是还是不是留存,不设有才实施插入语句,不然用户每一回登录都会招致auto_increment值被荒废。方案如下:

with transaction:
    user = SELECT * FROM user WHERE mobile = '15012345678' FOR UPDATE;
    if not user:
       INSERT INTO user(mobile, last_login_time) VALUES('15012345678', NOW()) 
    UPDATE user SET last_login_time = NOW();

其一代码乍看是不曾难点了,mobile是unique
key,那样的FOR UPDATE犹如木不常常,那是多个排他锁,2个session对那条记下加了排他锁,其余session不可能对那条记下加锁和修改(不能LOCK IN SHARE MODE 以及 UPDATE
等,要小心下SELECT FOR UPDATE只在事情中恐怕autocommit关闭的景况下才会加锁)。可是,那只在记录存在的场地下才是对记录加X锁,没有Gap锁。而只要这一个记录不存在,则对第3个不满意条件的笔录加Gap锁,保障没有满足条件的笔录插入。

如果mobile=15012345678那条记下不设有,并发的五个session都能够进入SELECT ... FOR UPDATE,因为都以加的Gap锁(X
locks gap before
rec),Gap锁之间是合营的。此时,个中任意一个session再履行
INSERT INTO user(mobile, last_login_time) VALUES('15012345678', NOW())语句会因为加insert intention lock(注:插入意向锁是一种独特的Gap锁,不是MySQL的表级意向锁IS,IX等)超时而执行破产。其实此时的Gap锁不只是锁住了
15012345678 那条记下,借使表中有其余的笔录,会将只怕插入 15012345678
的距离都锁住,MySQL加锁详细分析能够见参考资料5。

1.3加锁类型

4 消除方案

为此,假若要优化auto_increment的荒废难点,又要制止上一节提到的死锁难题,依然多少事情要做的。可行的两种方法如下:

  • 照旧正是干脆一点,在询问用户是或不是留存时一向用GET_LOCK(mobile),通过字符串锁而不是FOR UPDATE来幸免上一节提到的标题。
  • 要么正是先不加FOR UPDATE询问一遍用户表,借使用户不存在,然后再INSERT IGNORE INTO user ...。多三次查询,前边的逻辑不变。
  • 当然,percona的这篇小说avoiding-auto-increment-holes-on-innodb-with-insert-ignore还有个很tricky的方式来制止auto_increment的架空难题,有趣味的能够参考。

MySQL Innodb假如出现了一部分加锁难题,能够通过上边那多少个指令来增派分析。

show engine innodb status;
select * from information_schema.innodb_locks;
select * from information_schema.innodb_lock_waits;
select * from information_schema.innodb_trx;

Record Lock

Record
lock是在目录项上的锁,例如上边包车型大巴SQL会将拥有c1=10的行全体锁住,无法insert、update、delete

SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;

对此尚未索引的表,InnoDB也会创建三个掩蔽的聚簇索引。

READ COMMITTED只有Record Lock没有Gap Lock和Next-key Lock,所以locking
read(即LOCK IN SHARE MODEFOR UPDATE)、UPDATE和DELETE用的都以Record
Lock
REPEATABLE READ则有Record Lock、Gap Lock和Next-key Lock

InnoDB使用行级锁时,是当它寻找或扫描二个表的目录,在它境遇的要命索引记录上加上共享或独占锁,所以InnoDB的行级锁实际上就是索引记录锁(Record
Lock)。

https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html\#innodb-record-locks
https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html\#isolevel\_read-committed

5 参考资料

Gap Lock

Gap
Lock是将索引记录之间的限制加锁的锁,索引值在这段范围内的笔录不可能insert,如下SQL将锁住10<=c1<=20

SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;

Gap
Lock能够是一段索引值、单个索引值大概空,那是在品质和并发度之间权衡的结果,所以只有部分工作隔开等级使用了。
Gap
Lock在使用唯一索引查询单行结果的时候并不会被用到,但当以此唯一索引是一道索引,并且询问条件只囊括了一些索引列的时候仍然会被使用的。例如下边包车型客车SQL只会利用3个Record
Lock,假使id有唯一索引的话,并不影响从前索引值上的插入。

SELECT  *  FROM child WHERE id =  100;

当id没有索引,只怕不是唯一索引的时候,那么索引值从前的到上1个索引值之间的界定也会被锁。
Gap Lock只会堵住在这么些gap范围内的插入操作,所以Gap X-Lock与Gap
S-Lock的职能是千篇一律的,并不会争论。
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html\#innodb-gap-locks

Next-key Lock

Next-key Lock是在某三个索引记录上的Record
Lock和这一个目录记录此前的那段范围的Gap Lock的咬合。
就此一旦Session A拥有1个目录记录奥迪Q5上的共享|独占Next-key Lock,Session
B就无法在揽胜极光从前的这段索引记录范围内插入新的目录记录。
例如二个目录拥有十 、1① 、1三 、20多少个值,那么恐怕的Next-key
Lock就包蕴了如下的间距

(-infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, infinity)

InnoDB的私下认可事务隔绝级别是REPETABLE READ,InnoDB使用Next-key
Lock来搜寻和扫描索引,能够预防Phantom Rows。
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html\#innodb-next-key-locks
https://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html

Insert Intention Lock

Insert Intention
Lock是insert操作在插入行(获取该行的X锁)在此之前运用的一种Gap
Lock,多个Session假如要插入同三个Gap,但倘假诺例外的目录地方那么是不会争辩的。
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html\#innodb-insert-intention-locks

AUTO-INC Lock

AUTO-INC Lock是业务往有Auto
Increment字段的表插入记录时使用的一种表级锁,五个插入的事体必要等待来保证主键值的三番五次性。
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html\#innodb-auto-inc-locks
https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html\#sysvar\_innodb\_autoinc\_lock\_mode

2.Transaction Model

多版本(multi-versioning)数据库与两品级加锁(two-phase
locking)的咬合。暗许是行级锁以及无锁的一致性读(nonlocking consistent
reads)。

2.1Transaction Isolation Levels

隔绝性是数据库在面对多个业务同时推行修改只怕查询时,调节品质、可信赖性、一致性以及结果的可重现性的平衡的要害。
共有如下多少个级别:

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

InnoDB默认是REPEATABLE READ

REPEATABLE READ

  1. 同二个事务全数的Consistent
    reads(约等于默许景况,也正是不加锁)使用本事务第三遍读时创立的快速照相,也便是说同1个工作中的各种SELECT互相具有一致性(也便是可另行读,不会看到同时发出的其他工作对于数据的改动)。
  2. Locking reads(SELECT WITH FOEnclave UPDATE O本田CR-V LOCK IN SHARE
    MODE),UPDATE,DELETE语句,会依据语句是不是在唯一索引上使用唯一的条件而挑选分化的锁。

    • 唯一索引上的唯一准绳,InnoDB会采纳Record Lock把这些index
      Record锁住,而不是Gap Lock。
    • 此外的情事下,InnoDB会利用Gap Lock或Next-Key
      Lock将围观的目录范围给锁住,以阻止其余Session在那段范围插入记录。

READ COMMITTED

  1. 每七个Consistent
    read,尽管是在同3个作业中,都会重设读取最新的快速照相(所以会并发不可重复读的题材)。
  2. Locking reads,UPDATE,DELETE语句,InnoDB只会选取Record
    Lock锁住那么些索引值,不会锁住Gap,也正是同意锁住的笔录附近的值的插入(会有幻读的标题),Gap
    Locking只会在外键检查和重复键检查中应用。
  • 对此UPDATE、DELETE语句,InnoDB只会保持它供给更新或删除的行的锁,对于并不般配的行的Record
    Locks,会在MySQL总计完WHERE语句后获释。
  • 对于二个UPDATE语句,假设3个行已经被锁,InnoDB使用三个半一致性读(semi-consistent
    read),重返最新提交到MySQL的数量版本,固然那么些行匹配UPDATE的WHERE字句,那么MySQL会重读那些行,并加锁或然等待锁。

READ UNCOMMITTED

SELECT语句不会加锁,恐怕会读到贰个行稍早的数量版本,由此在那么些级别上,读是不等同的。也正是脏读。别的地点这一个级别和READ
COMMITTED是接近的。

SERIALIZABLE

其一级别类似于REPEATABLE READ

  • autocommit disabled,InnoDB会隐性地把全体SELECT转换为SELECT IN SHARE
    MODE
  • antocommit enabled,SELECT即是和谐的事情

2.2autocommit、commit、rollback

在InnoDB,全体的用户活动都发出在工作中,如若autocommit开启了,各样SQL语句都会融洽组合3个作业,MySQL暗许为每一种Session开启autocommit,所以各个SQL语句执行完并没有出错的话,MySQL都会实施二遍commit。若是语句重回错误,那么会基于错误执行commit\rollback。

  1. 对于开启了autocommit的Session,能够经过START TRANSACTION或者BEGIN语句来打开二个多语句的作业,然后通过COMMITROLLBACK来收场工作。
  2. 假定autocommit关闭了,那么session永远地处三个敞开的工作中,一个COMMITROLLBACK语句会甘休最近的事务然后打开新的事情。(要是session结束时并未显式地付出最终的事体,那么MySQL会回滚)

一些语句会隐式地交给业务。
一个COMMIT言语阐明当前工作的修改已经持久化,并且对此外session可知;而一个ROLLBACK话语撤废了脚下事情做的装有修改。COMMIT与ROLLBACK会释放具有当前政工的InnoDB锁。

2.3Consistent nonblocking read

snapshot

某七个一定时刻的数据表示,尽管其余工作提交了修改也维持不变,特定的隔绝级别使用那几个来贯彻一致性读(consistent
read)。

consistent read

是采取快速照相(snapshot)消息来展现查询结果的二个读操作,也就代表InnoDB使用multi-versioning来显示某些时刻数据库快照的询问结果。那几个查询能看出那个时刻在此以前交付的工作修改,而不会看到同样时刻其余业务实行的修改,例外是能收看本事务在此以前交付的改动。假使查询的数额已经被其余工作修改,那么原来数据会通过undo
log的内容来重建(恢复生机)。那一个技术防止了部分锁带来的面世难题。
REPEATABLE
READ级别,snapshot是举行本事务第二回读操作时的多寡,唯有工作提交之后才能博取1个新本子的snapshot。
READ COMMITTED级别,snapshot在每便consistent读操作时重设。
Consistent
read是InnoDB在汉兰达C|奥迪Q7中华V级别处理SELECT语句时的私下认可格局,因为consistent
read不会给它访问的表加锁,其他session能够在三个consistent
read操作时自由地修改这几个表。
假使暗许的级别上,当您执行二个consistent
read时,InnoDB会给您的业务三个时间点,你的查询看来的数据库就是其一时半刻间点的数据库。尽管其余作业在这么些时间点之后剔除了一行并交给,你看看的数据库中那一行并不会被删掉,插入与更新也类似。

snapshot状态适用于SELECT语句,而不是DML语句,要是事务A插入或更新了有的行并提交,那么RAV4牧马人级别的别的事务B固然无法透过询问看来那一个变化,但事务B的DELETE/UPDATE语句也是会影响到刚刚提交的这多少个行,要是产生了那种意况,那么这么些变迁对于近期事务B就会可知,例如:

SELECT  COUNT(c1)  FROM t1 WHERE c1 =  'xyz';  
-- Returns 0: no rows match.  
DELETE  FROM t1 WHERE c1 =  'xyz';  
-- Deletes several rows recently committed by other transaction.  
SELECT  COUNT(c2)  FROM t1 WHERE c2 =  'abc';  
-- Returns 0: no rows match.  
UPDATE t1 SET c2 =  'cba'  WHERE c2 =  'abc';  
-- Affects 10 rows: another txn just committed 10 rows with 'abc' values.  
SELECT  COUNT(c2)  FROM t1 WHERE c2 =  'cba';  
-- Returns 10: this txn can now see the rows it just updated.

你能够经过付出业务来推动时间点。
那也等于所谓的Multi-versioned concurrency control。
下边包车型大巴事例中,session A唯有在session
B提交了插入操作并且本人也交给之后才能看到B插入的行,因为唯有在A提交以往A的小时点才能穿越B的交付。

             Session A              Session B

           SET autocommit=0;      SET autocommit=0;
time
|          SELECT * FROM t;
|          empty set
|                                 INSERT INTO t VALUES (1, 2);
|
v          SELECT * FROM t;
           empty set
                                  COMMIT;

           SELECT * FROM t;
           empty set

           COMMIT;

           SELECT * FROM t;
           ---------------------
           |    1    |    2    |
           ---------------------

假定你需求随时看到最新气象的数据库,使用奥迪Q5C级别或许locking read。

Consistent read对于特定DDL语句也不见效:

  • DROP TABLE,因为MySQL不可能使用二个去除了的表。
  • ALTELX570TABLE,因为那几个语句会生成二个临时复制表,然后删除原表,当你再一次履行八个consistent
    read的时候,新表里的行对于您的snapshot来说是不设有的,所以事务会报错。

2.4Locking Reads

要是你在工作中询问数据,然后开始展览插队也许更新,普通的SELECT语句无法提供丰富的珍惜,其余事情能够立异或然去除你刚刚查询的数据行。InnoDB扶助三种locking
reads来提供额外的保安:

  • SELECT…LOCK IN SHARE MODE
    给要读得行上加共享锁,别的的事情能够读这个行,但唯有您的事体提交以后才能修改它们。假若此外作业修改了那一个行可是没有付诸,那么你的查询须求等待那个事情结束然后使用新型的值。
  • SELECT…FOR UPDATE
    给行以及有关的目录记录加排他锁,与UPDATE语句看似。别的业务对于那个行的立异、Locking
    Reads、或然某个隔开分离级别下的读都会卡住。Consistent
    reads会忽视记录上的锁。
    富有被Locking reads设置的锁会在事情提交或回滚的时候释放。

SELECT FOR
UPDATE对于行的加锁只有在autocommit禁用的时候使得,能够经过STARAV4T
TRANSACTION也许将autocommit设为0来剥夺。

3.Locks set by different SQL Statements in InnoDB

Locking read、UPDATE、DELETE平日会给处理SQL进程中持有扫描到的Index
Record加上Record
Lock。它并不会在意WHERE语句是或不是将这几个行排除了。InnoDB不会铭记WHERE条件,只精通它扫描过的index范围。加的锁一般的话是Next-key
Lock,同时也会阻塞对Record前边的Gap实行插队的操作。但是,gap
Locking能够被显式地剥夺,事务隔断等级也会潜移默化所选拔的锁。
假使叁个查询用了非聚簇索引并且加的Record
Lock也是排它锁,InnoDB也会取出对应的聚簇索引,并在上头加锁。
比方您的话语没有适度的目录使用,那么MySQL必须扫描整个表来处理语句,那么表中的每一行都会被加锁,也就会阻塞别的用户对于那么些表全部的插入,所以给表建立好的目录很重点,避防查询时环顾很多不须求的行。
InnoDB加锁的状态如下:

  • SELECT…FROM是consistent
    read,不加锁除非隔绝级别设为SE中华VIALIZABLE。SEENVISIONIALIZABLE级别下,查询会给它碰着的目录记录加Next-key
    Lock,不过在应用唯一索引查询唯一的行时只会给索引记录加Record Lock。

  • SELECT…FROM…LOCK IN SHARE
    MODE给它蒙受的装有索引记录加共享Next-key
    Lock,可是在利用唯一索引查询唯一的行时只会给索引记录加Record Lock。

  • SELECT…FROM…FOXC60 UPDATE给它遭遇的有所索引记录加排它Next-key
    Lock,可是在运用唯一索引查询唯一的行时只会给索引记录加Record
    Lock。
    对此查询时境遇的目录记录,SELECT-FOQashqai-UPDATE会阻塞其余session举行SELECT-IN-SHARE大概某个级别下的读。Consistent
    read会忽视它多少视图上的笔录上的有所锁。

  • UPDATE…WHERE…给它蒙受的拥有索引记录加排它Next-key
    Lock,但是在动用唯一索引查询唯一的行时只会给索引记录加Record Lock。

  • 当UPDATE修改了3个聚簇索引记录,那么相关的非聚簇索引记录上的隐式锁会被拿掉。UPDATE操作也会把受到震慑的非聚簇索引记录上的共享锁拿掉,当执行插入新的非聚簇索引记录前再度值扫描或许插入新的非聚簇索引记录时。

  • DELETE FROM…WHERE…给它碰到的有着索引记录加排它Next-key
    Lock,不过在使用唯一索引查询唯一的行时只会给索引记录加Record Lock。

  • INSEQX56T会给插入的行加上二个排它锁。这一个锁是三个索引Record
    Lock,不是Next-key Lock(也正是没有Gap
    Lock)并且不会阻拦别的作业往插入行在此以前的Gap中插入记录。
    插入行在此之前,会加一种Insert intention Gap
    Lock,表明打算要插入,那样多个插入同三个Gap的事情假如不是要插入到同2个职位那就不须求等待。
    若果发生duplicate key
    error,会加1个共享锁在顶牛的行上。详见链接里的INSELANDT
    https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html

  • INSELX570T…ON DUPLICATE KEY UPDATE与简短的INSEHighlanderT不相同,当发生duplicate
    key error发生的时候,会加二个排它锁在须要改进的行上。

  • REPLACE

  • INSEPRADOT INTO T SELECT…FROM S WHERE…加二个排它index Record
    Lock在每3个要插入到T的行上。详见文书档案。

  • AUTO_INCREMENT 详见文书档案。

  • LOCK TABLES
    会加表锁,但那是在比InnoDB层更高的MySQL层加的锁。InnoDB在innodb_table_locks = 1(the
    default) and
    autocommit = 0的情状下能感知到表锁,而MySQL层一贯能感知到行锁。

4.Phantom Rows

5.Deadlocks

相关文章