前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL Locking

MySQL Locking

作者头像
Dylan Liu
发布2019-07-01 12:57:14
8430
发布2019-07-01 12:57:14
举报
文章被收录于专栏:dylanliudylanliu

Abstract

看到孤独烟回答粉丝的一个问题, 就想要研究一下MySQL 锁的情况。下面是对MySQL manual locking的一个笔记。

Share & Exclusive Lock

  • A shared (S) lock permits the transaction that holds the lock to read a row.
  • An exclusive (X) lock permits the transaction that holds the lock to update or delete a row.

Intention Lock

  • Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table.
  • SELECT ... LOCK IN SHARE MODE sets an IS lock, and SELECT ... FOR UPDATE sets an IX lock.(after version 8.0, share mode used this way select ... for share, consistent with update)

X

S

IX

IS

X

Conflict

Conflict

Conflict

Conflict

S

Conflict

Compatible

Conflict

Compatible

IX

Conflict

Conflict

Compatible

Compatible

IS

Conflict

Compatible

Compatible

Compatible

The intention locking protocol is as follows:

  • Before a transaction can acquire a shared lock on a row in a table, it must first acquire an IS lock or stronger on the table.
  • Before a transaction can acquire an exclusive lock on a row in a table, it must first acquire an IX lock on the table.

Record Lock

  • A record lock is a lock on an index record.
  • Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking

Example:

代码语言:javascript
复制
CREATE TABLE `tt` (
  `a` int(11) NOT NULL DEFAULT '0',
  `b` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL,
  `c` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

insert into tt values (1, 'aaa', 'ccc');
insert into tt values (2, 'bbb', 'ccc');
insert into tt values (3, 'ccc', 'ccc');


start transaction;
select * from tt where a = 1 for update;

show engine innodb status;

可以看到如下输出,在 table 上有一个 IX 锁,在行上有一个 X 的 record lock.

代码语言:javascript
复制
2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 127707691, OS thread handle 0x7efbeb65d700, query id 4117992277 10.16.163.157 mams_test
TABLE LOCK table `test1`.`tt` trx id A06213D6 lock mode IX
RECORD LOCKS space id 6784 page no 3 n bits 72 index `PRIMARY` of table `test1`.`tt` trx id A06213D6 lock_mode X locks rec but not gap
Record lock, heap no 6 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000a0600c90; asc    `  ;;
 2: len 7; hex 780000c61b1e0f; asc x      ;;
 3: len 3; hex 646464; asc ddd;;
 4: SQL NULL;

ps: 执行show engine innodb status之前需要先将lock 监控打开,需要创建两张表,具体信息可见Enabling InnoDB Monitors

代码语言:javascript
复制
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
CREATE TABLE innodb_lock_monitor (a INT) ENGINE=INNODB;

无index Example:

代码语言:javascript
复制
create table ttp (a int, b varchar(10));
insert into ttp values (1, 'cc');
insert into ttp values (1, 'dd');

start transaction;
select * from ttp where b = 'dd' for update;

show engine innodb status;

输出如下,可以看到MySQL自动生成了一个clustered index,而且由于没有索引,这次将表里的两条数据全部加了 X 锁:

代码语言:javascript
复制
TABLE LOCK table `test1`.`ttp` trx id A0622BA2 lock mode IX
RECORD LOCKS space id 6789 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test1`.`ttp` trx id A0622BA2 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000001ae524d; asc     RM;;
 1: len 6; hex 0000a0622b13; asc    b+ ;;
 2: len 7; hex e1000014d20110; asc        ;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6363; asc cc;;

Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000001ae524e; asc     RN;;
 1: len 6; hex 0000a0622b2b; asc    b++;;
 2: len 7; hex f9000084630110; asc     c  ;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6464; asc dd;;

Gap Lock

  • A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record.
  • Used in REPEATABLE READ and SERIALIZABLE isolation level. You can disable gap lock explicitly by changing the isolation level to READ COMMITTED
  • Gap locking is not needed for statements that lock rows using a unique indexto search for a unique row. (This does not include the case that the search condition includes only some columns of a multiple-column unique index; in that case, gap locking does occur.)
  • Gap locks in InnoDB are “purely inhibitive”, which means that their only purpose is to prevent other transactions from inserting to the gap.Gap locks can co-exist. A gap lock taken by one transaction does not prevent another transaction from taking a gap lock on the same gap. There is no difference between shared and exclusive gap locks. They do not conflict with each other, and they perform the same function.
  • Gap locking can be disabled explicitly.
    • change the transaction isolation level to READ COMMITTED.
    • set innodb_locks_unsafe_for_binlog = 1(not in 8.0 doc)

Example:

代码语言:javascript
复制
create table ttp (a int, b varchar(10));
insert into ttp values (1, 'cc');
insert into ttp values (2, 'dd');
insert into ttp values (20, 'dd');
insert into ttp values (25, 'dd');
create index idx_a on ttp(a); -- 必不可少

delete from ttp where a = 23;

show engine innodb status 显示如下:

代码语言:javascript
复制
TABLE LOCK table `test1`.`ttp` trx id A0640DCF lock mode IX
RECORD LOCKS space id 6789 page no 4 n bits 72 index `idx_a` of table `test1`.`ttp` trx id A0640DCF lock_mode X locks gap before rec
Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000019; asc     ;;
 1: len 6; hex 000001ae5251; asc     RQ;;

执行insert into ttp values(22, '');``insert into ttp values(24, '');都不可以,但是insert into ttp values(25, '');是OK的,说明不是一个next-key lock.

Next-key Lock

  • A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record.
  • InnoDB performs row-level locking in such a way that when it searches or scans a table index(which prevents phantom rows), it sets shared or exclusive locks on the index records it encounters.
  • A next-key lock is an index-record lock plus a gap lock on the gap preceding the index record.

next-key lock range example: Suppose that an index contains the values 10, 11, 13, and 20.

代码语言:javascript
复制
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)

For the last interval, the next-key lock locks the gap above the largest value in the index and the “supremum” pseudo-record having a value higher than any value actually in the index. The supremum is not a real index record, so, in effect, this next-key lock locks only the gap following the largest index value.

Example:

代码语言:javascript
复制
select * from ttp where a> 20 for update;

show engine innodb status shows:

代码语言:javascript
复制
TABLE LOCK table `test1`.`ttp` trx id A067CC23 lock mode IX
RECORD LOCKS space id 6789 page no 4 n bits 80 index `idx_a` of table `test1`.`ttp` trx id A067CC23 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Insert Intention Locks

  • An insert intention lock is a type of gap lock set by INSERT operations prior to row insertion.
  • This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.

Example:

代码语言:javascript
复制
session1:
start transaction;
select * from tt where a > 100 for update;


session2:
start transaction;
insert into tt(a) values (91); --waiting

show engine innodb status;shows

代码语言:javascript
复制
insert into tt(a) values (91)
------- TRX HAS BEEN WAITING 4 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6784 page no 3 n bits 80 index `PRIMARY` of table `test1`.`tt` trx id A068EAF9 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000066; asc    f;;
 1: len 6; hex 0000a068e94a; asc    h J;;
 2: len 7; hex d600005a94011d; asc    Z   ;;
 3: SQL NULL;
 4: SQL NULL;

------------------
TABLE LOCK table `test1`.`tt` trx id A068EAF9 lock mode IX
RECORD LOCKS space id 6784 page no 3 n bits 80 index `PRIMARY` of table `test1`.`tt` trx id A068EAF9 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000066; asc    f;;
 1: len 6; hex 0000a068e94a; asc    h J;;
 2: len 7; hex d600005a94011d; asc    Z   ;;
 3: SQL NULL;
 4: SQL NULL;

---TRANSACTION A068E9BF, ACTIVE 66 sec
2 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 127963261, OS thread handle 0x7efbf5bb0700, query id 4122875322 10.16.163.157 mams_test
TABLE LOCK table `test1`.`tt` trx id A068E9BF lock mode IX
RECORD LOCKS space id 6784 page no 3 n bits 80 index `PRIMARY` of table `test1`.`tt` trx id A068E9BF lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000066; asc    f;;
 1: len 6; hex 0000a068e94a; asc    h J;;
 2: len 7; hex d600005a94011d; asc    Z   ;;
 3: SQL NULL;
 4: SQL NULL;

compatiblity table:

acquiring ↓/acquired→

Gap

Insert Intention

Record

Gap

Compatible

Compatible

Compatible

Insert Intention

Conflict

Compatible

Compatible

Record

Conflict

Compatible

Compatible

AUTO-INC Locks

  • An AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns.

Extended Read

SELECT statements will not lock any rows while running which is generally correct, however there a notable exception – INSERT INTO table1 SELECT * FROM table2. This statement will perform locking read (shared locks) for table2 table. It also applies to similar tables with where clause and joins.

from INSERT INTO … SELECT Performance with Innodb tables.

If a non-INSERT write operation is more likely to not match any row because the INSERT part is yet to come on the transaction, don’t do it or use REPLACE INTO or use READ-COMMITTED transaction isolation.

from One more InnoDB gap lock to avoid

REPEATABLE READ For locking reads (SELECT with FOR UPDATE or LOCK IN SHARE MODE), UPDATE, and DELETE statements, locking depends on whether the statement uses a unique index with a unique search condition, or a range-type search condition.

  • For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it.
  • For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key locks to block insertions by other sessions into the gaps covered by the range. For information about gap locks and next-key locks.

from Transaction Isolation Levels

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Abstract
  • Share & Exclusive Lock
  • Intention Lock
  • Record Lock
  • Gap Lock
  • Next-key Lock
  • Insert Intention Locks
  • AUTO-INC Locks
  • Extended Read
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档