如何进行innodb事务锁的研究
1. select * for update 语句添加排他行锁。
2.当行计划使用索引常量查找或索引范围扫描(在索引覆盖查询的情况下)时, select ... from table_name where ... forupdate 语句将在主键上添加排它行锁。
3.当select .. for update语句使用全索引扫描时,使用覆盖索引时也会对主键的所有记录加排它行锁。
4.当update语句执行计划使用索引常量搜索或者索引范围扫描时,除了给辅助索引加排他行锁外,还会给主键对应的记录加排他行锁(即使使用覆盖索引)以这种方式)。
5.当更新语句执行计划使用辅助索引的全扫描时,除了对辅助索引中的所有记录加排它行锁外,还会对主键中的所有记录加排它行锁(即使是覆盖索引)是这样使用的)。
6.测试辅助索引为唯一索引时是否会出现间隙锁
准备测试数据:
CREATE TABLE t5 (
aint(11) NOT NULL ,
b intnot null,
cint not null,
主键 (`a`),
唯一键(b) ,
UNIQUE key(c)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
;
插入 t5 值(1, 1,1);
插入t5值(2,2,2);
插入t5值(3,3,3);
插入t5值(4,4,4);
插入t5值(5,5,5);
插入t5值(6,6,6);
插入t5值(7,7,7);
mysql>从t5中选择*;
+---+---+- --+
|一个 |乙| c|
+- --+---+---+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
| 5 | 5 | 5 |
| 6 | 6 | 6 |
| 7 | 7 | 7 |
+---+---+---+
7 行一组(0.00 秒)
1. select * for update 语句添加排他行锁。
--会话1
mysql> select@@global.tx_isolation,@@tx_isolation;
+------------ ----------+-----------------+
| @@global.tx_isolation |@@tx_isolation |
+------------------------+-------- ----------+
|可重复读取|可重复读取 |
+------------------------+--- -------------- ---+
集合中的 1 行(0.00 秒)
set sessioninnodb_lock_wait_timeout=1000000;
- -session 2
mysql > 选择@@global.tx_isolation,@@tx_isolation;
+-------------------- ----+------ -----------+
| @@global.tx_isolation |@@tx_isolation |
+- ----------------------+-------- ----------+
|可重复读取|可重复读取 |
+------------------------+-------------------+
集合中的 1 行(0.00 秒)
mysql> set sessioninnodb_lock_wait_timeout=1000000;
查询正常,0 行受影响(0.00 秒)
--SESSION 1
mysql> begin;
查询正常,0 行受影响(0.00 秒)
mysql> select * from t3 where a=5 forupdate;
+---+
|一个 |
+---+
| 5 |
+---+
集合中的 1 行(0.00 秒)
--会话 2
mysql> 开始;
查询正常,0 行受影响(0.00 秒)
mysql> select * from t3 where a=5 forupdate; --blocked
< p>--SESSION 3 查看锁信息mysql> select * from innodb_locks\G
************ ********** ****** 1.行**************************** **
lock_id:324675084:253:3:6
lock_trx_id:324675084
lock_mode:X
lock_type:RECORD p>
lock_table: `test`.`t3`
lock_index: PRIMARY
lock_space: 253
lock_page: 3
锁记录:6
锁数据:5
**************** ************* *** 2.行********************************
lock_id:324675083:253:3:6
lock_trx_id:324675083
lock_mode:X
lock_type:RECORD
lock_table:`测试`.`t3`
lock_index:主
lock_space:253
lock_page:3
lock_rec:6
< p> lock_data: 52 rows in set (0.00 sec)
结论:
通过实验我们发现 select * from t3 where a =5for update添加独占行锁。
2.当行计划使用索引常量查找或索引范围扫描(在索引覆盖查询的情况下)时, select ... from table_name where ... forupdate 语句将在主键上添加排它行锁。
mysql> 解释 select b from t5 whereb=5 for update\G
************************ ** ***** 1.行****************************
; p> select_type:SIMPLE
表:t5
类型:const
possible_keys: b
key: b
key_len: 4
ref: const
rows: 1
Extra: NULL
集合中的 1 行(0.00 秒)
执行计划使用索引常量搜索。
--会话1
mysql>开始;
mysql>从t5中选择b,其中b=5进行更新;
+- --+
| b |
+---+
| 5 |
+---+
集合中的 1 行(0.00 秒)
--SESSION 2
mysql> select来自 t5 的 c,其中 c=5 用于更新; --blocked
--SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r .trx_wait_started,CURRENT_TIMESTAMP) AS wait_time ,
r.`trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
b.trx_id AS_trx_id,b.`trx_mysql_thread_id` ASblocking_thread,
blocking SUBSTRING(p.host,1,INSTR(p.host,':')-1) ASblocking_host,
SUBSTRING(p.host,INSTR(p.host,':')+1) AS 阻塞端口,
IF(p.command="Sleep",p.time,0) ASidle_in_trx,
b.`trx_query` ASblocking_query
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema。`INNODB_TRX`AS b ON b.trx_id=w.blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w .requesting_trx_id
INNER JOIN information_schema。 `INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema。`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
******************************** ** 1.行******** **********************
waiting_trx_id:324675156
waiting_thread:2
wait_time :77
waiting_query:从 t5 中选择 c,其中 c=5 进行更新
waiting_table_lock:`test`.`t5`
waiting_index_lock:PRIMARY
blocking_trx_id:324675155
blocking_thread:1
blocking_host:
blocking_port:localhost
idle_in_trx:150
blocking_query: NULL
集合中的 1 行(0.00 秒)
mysql>select * from innodb_locks\G
******************************** 1.行**** ****************** **********
lock_id:324675156:255:3:6
lock_trx_id: 324675156
lock_mode:X
lock_type: RECORD
lock_table: `test`.`t5`
lock_index: PRIMARY
lock_space:255
lock_page:3
lock_rec:6
lock_data:5
*** ********************* *** 2.行************************ ******
lock_id:324675155:255:3:6
lock_trx_id:324675155
lock_mode:X
lock_type: RECORD
lock_table: `test`.`t5`
< p> lock_index: PRIMARYlock_space: 255
lock_page: 3< /p>
lock_rec: 6
lock_data: 5
< p>集合中2行(0.00秒)回滚SESSION1和SESSION 2的事务< /p>
--SESSINO 1
mysql> begin;
查询正常,0 行受影响(0.00 秒)
mysql> select b from t5 其中 b=5 用于更新;
+---+
< p>| b |+---+
| 5 |
+---+
组中 1 行(0.00 秒)
--SESSION2
mysql> begin;
查询正常,0 行受影响(0.00 秒)
mysql > select b from t5 where b=5 forupdate; --Blocked
--SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF( SECOND,r .trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
b.trx_id ASblocking_trx_id,b.`trx_mysql_thread_id`ASblocking_thread,
SUBSTRING(p.host,1,INSTR(p.host,':')-1) ASblocking_host,
SUBSTRING(p.host,INSTR(p.host,':')+1) ASblocking_port,
IF(p.command="Sleep",p.time,0 ) ASidle_in_trx ,
b.`trx_query` AS 阻塞查询
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id =w.blocking_trx_id
INNER JOIN information_schema.`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema .`INNODB_LOCKS` AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC \ G
******************************** 1.行******** **** ****************
waiting_trx_id: 324675159
waiting_thread: 2
wait_time: 8< /p>
Waiting_query:从 t5 中选择 b,其中 b=5 进行更新
waiting_table_lock: `test`.`t5`
waiting_index_lock: b
blocking_trx_id:324675158
blocking_thread:1
blocking_host:
blocking_port:localhost
idle_in_trx:21
blocking_query: NULL
集合中的 1 行(0.00 秒)
mysql> select * from innodb_locks\G
** ******** ***************** 1.行************************ *****< /p>
lock_id:324675159:255:4:6
lock_trx_id:324675159
lock_mode:X
lock_type:RECORD
< p> lock_table: `test`.`t5`lock_index: b
lock_space: 255
lock_page: 4
lock_rec: 6
lock_data: 5
**************************** * 2.行***** *************************
lock_id:324675158:255:4:6
lock_trx_id: 324675158
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index:b
lock_space: 255
lock_page: 4
lock_rec: 6
lock_data: 5
集合中的 2 行 (0.00 sec)
我们看到select b from t5 where b=5 for update SQL语句给辅助索引b的索引键为5的索引项添加了排它行锁。 。
通过上面两个例子,我们可以看到SESSION 1执行的SQL的执行计划使用了索引常量搜索。这条SQL只会对辅助索引b=5的记录加排它行锁,
同时也会对主键(a=5)对应的记录加排它行锁)。
3. select .. for update语句使用全索引扫描时,如果使用覆盖索引,会加排它锁ed到辅助索引的所有索引项,并且排除行将添加到主键的所有记录。锁。
mysql> 解释 select b from t5 forupdate\G
**************************** * 1.行********************************
id:1
select_type:SIMPLE
表:t5
类型:索引
possible_keys:NULL
键:b
key_len: 4
ref: NULL
rows: 7
额外:使用索引
集合中的 1 行(0.00 秒)
mysql> 解释 select C from t5 forupdate\G
**************************** ****** 1.行********************************
id: 1< /p>
select_type: SIMPLE
表:t5
类型:索引
possible_keys: NULL
键:C < /p>
Key_len: 4
Ref: null
ROWS: 7
额外:USING Index
1 行set (0.00 sec)
上面两个SQL执行计划都是使用覆盖索引来进行全索引扫描。
--SESSION 1
mysql> begin;
查询正常,0 行受影响(0.00 sec)
mysql>从t5中选择b进行更新;
+---+
| b |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
+---+
--SESSION 2
mysql> begin;
查询正常,0 行受影响( 0.00秒)
mysql>从t5中选择b进行更新; --blocked
--SESSION 3 查看锁信息
< p>SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,TIMESTAMPDIFF(SECOND,r .trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query ,l.`lock_table` AS waiting_table_lock,
SUBSTRING(p.host,1,INSTR(p.1)主机,':')-1) AS 阻塞_主机,
SUBSTRING(p.host,INSTR(p.host,':')+1) AS 阻塞_端口,
IF( p.command="睡眠",p.time,0) ASidle_in_trx,
b.`trx_query` AS 阻塞查询
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id=w .blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema。`INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id< /p>
左连接信息_架构。 `PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
***************** ****** ********** 1.行********************************
waiting_trx_id:324675162
waiting_thread:2
wait_time:19
waiting_query:从t5中选择b进行更新
< p>waiting_table_lock:`test`.`t5`waiting_index_lock:b
blocking_trx_id:324675161
blocking_thread:1
blocking_host:
blocking_port:localhost
idle_in_trx:29
blocking_query:NULL
集合中的1行(0.00秒)
< p>mysql>从innodb_locks\G中选择**************************** 1.行************ ****************** p>
lock_id:324675162:255:4:2
lock_trx_id:324675162
lock_mode:/p>
lock_page:4
lock_rec :2
lock_data:1
************* ************* 2.行* ******************************
lock_id:324675161:255:4:2
< p>lock_trx_id:324675161lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index: b
lock_space:255
lock_page:4
lock_rec:2
lock_data:1
2行in set (0.00 sec)
SESSION 2在索引键值为1的辅助索引b的索引条目上被阻塞。
SESSION 1和SESSION 2回滚事务
--SESSINO 1
mysql> begin;
查询正常,0行受影响(0.00秒)
mysql>从t5中选择b进行更新;
mysql> p>
+---+
| b |
+ ---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
+---+
集合中的 7 行(0.00 秒)
--SESSION 2
mysql>begin;
查询正常,0行受影响(0.00秒)
mysql> select b from t5 where b=7 for update; --Blocked
--SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
Timestampdiff (Second, R .TRX_WAIT_STARTED, CURRENT_TIMESTAMP) as wait_time,
R.`trx_qury, L.`Lock_table` AS Waiting_table_lock,
L .lock_index AS waiting_index_lock,
b .trx_id ASblocking_trx_id,b.`trx_mysql_thread_id`ASblocking_thread,
SUBSTRING(p.host,1,INSTR(p.host,':')-1) ASblocking_host,
SUBSTRING(p.host,INSTR (p.host,':')+1) ASblocking_port,
IF(p.command="Sleep",p.time,0) ASidle_in_trx,< /p>
b. `trx_query` ASblocking_query
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id=w.blocking_trx_id
INNER JOIN information_schema.`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema.`INNODB_LOCKS` AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G< /p>
**************** ********** 1. 行**************** **************
waiting_trx_id:324675164
waiting_thread:2
wait_time:41
< p> waiting_query:从 t5 中选择 b,其中 b=7 进行更新waiting_table_lock:`test`.`t5`
waiting_index_lock:b
blocking_trx_id:324675163
阻塞线程:1
阻塞主机:
阻塞端口:本地主机
Idle_in_trx:57
阻塞查询:NULL< /p>
集合中的 1 行(0.00 秒)
mysql> select * from innodb_locks\G
**************** ************** 1.行**************** ************** p>
lock_id:324675164:255:4:8
lock_trx_id:324675164
lock_mode:X
lock_type:RECORD
lock_table: `test`.`t5`
lock_index: b
lock_space: 255
< p> lock_page: 4lock_rec: 8
lock_data:7
**************************** 2. 行**************** ********* ****
lock_id:324675163:255:4:8
lock_trx_id:324675163
lock_mode:X< /p>
lock_type: RECORD
lock_table: `test`.`t5`
lock_index: b
lock_space: 255
< p> lock_page: 4lock_rec: 8
lock_data: 7
集合中有 2 行(0.00 秒)
SESSION 2 是阻塞在索引项7的辅助索引b的索引键值上。
结合SESSION 2阻塞在辅助索引b中索引键值为1的索引项上的情况,可以确定该SQL select b from t5 for update是在辅助索引b的所有索引条目上加了排它行锁。
SESSION 1 和 SESSION 2 回滚事务。
--SESSION 1
mysql> begin;
查询正常,0 行受影响(0.00 秒)
mysql> select b从 t5 开始更新;
+---+
| b |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6|
| 7 |
+---+
集合中的 7 行(0.00 秒)
--SESSION 2
mysql> 开始;
查询正常,0 行受影响(0.00 秒)
mysql> select c from t5for update; --Blocked
--SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF (SECOND,r .trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
P>B.TRX_ID As Blocking_trx_id, B.B.`TRX_MYSQL_THREAD_ID` As Blocking_Thread,
Substring (P.HOST, 1, Instr (P.Host, ':')-1) asblocking_ho ST,
p>SUBSTRING(p.host,INSTR(p.host,':')+1) ASblocking_port,
IF(p.command="Sleep",p.time, 0) ASidle_in_trx,
b.`trx_query`ASblocking_query
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b .trx_id=w.blocking_trx_id
内连接 information_schema.`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema。`INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema。` PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
******************** ********** 1.行************ ******************
waiting_trx_id: 324675166
waiting_thread: 2
wait_time: 48
waiting_query: 从t5中选择c进行更新
waiting_table_lock: `test `.`t5`
waiting_index_lock:主
blocking_trx_id:324675165
blocking_thread:1
blocking_host:
blocking_port:localhost
idle_in_trx:65
blocking_query:NULL
集合中的1行(0.00秒)
mysql>选择*来自 innodb_locks\G
* **************************** 1. 行******** ************** ******
lock_id:324675166:255:3:2
lock_trx_id:324675166
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_i索引:主
lock_space:255
lock_page:3
lock_rec:2
lock_data:1
************************** ** ** 2.行******************** *************
lock_id:324675165:255:3:2
lock_trx_id:324675165
lock_mode:X< /p>
lock_type: RECORD
lock_table: `test`.`t5`
lock_index: PRIMARY
lock_space: 255
< p> lock_page: 3lock_rec: 2
lock_data: 1
集合中的 2 行(0.00 秒)
SESSION 2 是阻塞在主键值为1的索引项上。
SESSION 1和SESSION 2回滚事务。
--SESSION 1
mysql> begin;
查询正常,0 行受影响(0.00 秒)
mysql> select b从t5开始更新;
+---+
| b |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
+---+
集合中的 7 行(0.00 秒)
--SESSION 2
mysql> 开始;
查询正常,0 行受影响(0.00 秒)
mysql> select c from t5 where c=7 foru更新; --blocked
- -SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r .trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
b.trx_id ASblocking_trx_id,b.`trx_mysql_thread_id`ASblocking_thread,
SUBSTRING(p.host,1,INSTR(p.host,':')-1) ASblocking_host,
SUBSTRING(p.host,INSTR(p.host,':')+1 ) ASblocking_port,
IF(p.command="Sleep",p.time,0) ASidle_in_trx ,
b.`trx_query` AS 阻塞查询
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id =w.blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema。`INNODB_LOCKS`AS l ON w.requested_lock_id=l。 lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id =b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
******************** ****** * 1.行********************************
waiting_trx_id : 324675168
waiting_thread: 2
wait_time: 44
waiting_query: 从 t5 中选择 c,其中 c=7 进行更新
waiting_table_lock: `test`.`t5`
waiting_index_lock:主
blocking_trx_id:324675167
blocking_thread:1
blocking_host:
blocking_port:localhost
idle_in_trx:63
blocking_query:NULL
集合中的1行(0.00秒)
mysql>
mysql>从innodb_locks\G中选择*
**************************** ** 1.行**************** ************
lock_id:324675168:255:3:8< /p>
lock_trx_id: 324675168
lock_mode: X p>
lock_type: RECORD
lock_table: `test`.`t5`
< p>lock_index:主lock_space:255
lock_page:3
lock_rec:8
lock_data:7
< p>************************ ******** 2.行**********************************lock_id:324675167:255:3:8
lock_trx_id:324675167 p>
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index:PRIMARY
lock_space: 255 p>
lock_page: 3
lock_rec: 8
lock_data: 7
集合中 2 行(0.00 秒)< /p>
SESSION 2 被阻塞在主键值为 7 的索引项上。
结合 SESSION 2 被阻塞在主键索引键值为 7 的索引项上的情况1、可以确定SQL select b from t5 for update在主键的所有索引项上都被阻塞。添加了独占行锁。
结合select b from t5 for update,该SQL对辅助索引b的所有索引项加排他行锁,并确定select .. for update语句使用辅助索引(覆盖索引)< /p>
执行索引全扫描时,会对辅助索引的所有索引条目和所有索引条目添加排它行锁主键的类型。
4.当update语句执行计划使用索引常量搜索或索引范围扫描时,除了对辅助索引对应的索引条目加排它行锁外,还会对主键对应的记录加排它行锁(即使使用覆盖索引也是如此)。
4.1 SQL语句的执行计划
sql_1
mysql>explain update t5 set b=b\G
**** ********************** 1. 行************************ ** *
id:1
select_type:SIMPLE
表:t5
类型:索引
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 7
额外: usingtemporary
1 row in set (0.00 sec)
sql_1 执行计划 Type:index 表示按索引顺序执行全表扫描。它的优点是避免了排序,缺点是把全表扫描的连续IO变成了随机IO。
sql_2
mysql> 解释 select b from t5\G
************************ ** ****** 1.行****************************
p>
select_type:SIMPLE
表:t5
类型:索引
possible_keys:NULL
键:b
key_len: 4
ref: NULL
rows: 7
额外:使用索引
集合中的 1 行(0.00 秒)< /p>
SQL_2 执行计划使用覆盖索引。 type:index, key: b, Extra: 使用索引使用覆盖索引全扫描。
SQL_3
mysql> 解释更新 t5 set c=c\G
***************** ***** ********** 1.行****************************
select_type: SIMPLE
表: t5
类型: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
行: 7
额外:在执行计划中使用临时
1 row in set (0.00 sec)
SQL_3 type:index 意味着按照索引顺序进行 优点全表扫描的优点是避免了排序,但缺点是把全表扫描的连续IO变成了随机IO。
SQL_4
mysql> 解释更新 t5 set b=b whereb=5\G
**************** ************** 1.行********************************
id:1
select_type:SIMPLE
表:t5
类型:范围
possible_keys:b
key: b
key_len: 4
ref: const
rows: 1
额外:使用 where
1 row in set (0.00 sec)
SQL_4 虽然只更新了一条记录,但执行计划并没有使用常量检索,而是使用索引范围扫描。
SQL_5
mysql> 解释 select b from t5 whereb=5 for update\G
**************** ** ****************** 1. 行**************************
1
选择_类型:简单
< p> 表:t5类型:const
可能的键:b
键:b
Key_len:4
< p> Ref: CONSTROWS: 1
额外: Null
集合中的 1 行(0.00 秒)
SQL_5 是相当于 SQL_4 的 SELECT 语句。 SQL_5 使用常量检索。由此推断UPDATE语句
不能使用常量检索。即使 UPDATE 仅对主键中的一行记录进行操作,也不会使用常量检索。
SQL_6
mysql> 解释更新 t5 set c=c wherec=5\G
**************** ************** 1.行********************************
id:1
select_type:SIMPLE
表:t5
类型:范围
possible_keys:c
key: c
key_len: 4
ref: const
rows: 1
额外:使用 where
一组 1 行(0.00 秒)
eSQL_6的执行计划是对辅助索引C进行索引范围扫描。
SQL_7
mysql>解释update t5 set b=b where bin (1,3)\G
************ ********************* 1.行******** **********************
id:1
select_type:SIMPLE
表: t5
类型:范围
可能的键:b
键:b
key_len:4
参考: const
rows: 2
额外:使用 where;使用临时
集合中的1行(0.00秒)
SQL_7通过对辅助索引b进行索引范围扫描访问了2条记录,最终获得了所需的数据。
SQL_8
mysql> 解释 update t5 set b=b where bin (1,3,5)\G
******** ****************** 1.行****************************
id:1
select_type:SIMPLE
表:t5
类型:索引
possible_keys:b
key: PRIMARY
key_len: 4
ref: NULL
rows: 7
额外:使用在哪里;使用临时
集合中的 1 行(0.00 秒)
SQL_8 按索引顺序执行全表扫描。它的优点是避免了排序,缺点是把全表扫描的连续IO变成了随机IO。
4.2锁分析
--SESSION 1
mysql> use test
mysql> begin;
mysql> update t5 set b=b where b in(1,3);
--SESSION 2
mysql> use test;
mysql> begin ;
mysql> update t5 set c=c where c in(1,3); --已阻止
--会话 3
选择 r。 trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r.trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query,l.`lock_table ` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
b.trx_id ASblocking_trx_id,b.`trx_mysql_thread_id` ASblocking_thread,
SUBSTRING(p.host ,1,INSTR(p.host,':')-1) AS 阻塞_主机,
SUBSTRING( p.host,INSTR(p.host,':')+1) AS 阻塞_端口, p>
IF(p.command="睡眠",p.time,0) ASidle_in_trx,
b.`trx_query` AS 阻塞查询
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id= w.blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema。`INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
****** **** ********************* 1. 行************************ ********
waiting_trx_id: 324675599 --SESSION 2的事务ID,等待锁的事务ID
waiting_thread: 2 --MSYQL等待锁的线程ID< /p>
wait_time: 30
waiting_query : update t5 set c=c where c in (1,3)
waiting_table_lock: `test`.`t5` p>
waiting_index_lock: PRIMARY
blocking_trx_id: 324675598 --SESSION 1的事务ID,持有锁的事务ID
blocking_thread: 1 --持有锁的MYSQL线程ID
blocking_host:
blocking_port:localhost
idle_in_trx:52
blocking_query:NULL
集合中的 1 行(0.12 秒)
mysql> select * from innodb_locks\G
***************** ************* 1.行************ ******************
lock_id: 324675599:255:3:2
lock_trx_id: 324675599
lock_mode: X
lock_type: RECORD
lock_table: `test`.`t5`
lock_index: PRIMARY
lock_space: 255
lock_page: 3
lock_rec: 2< /p>
lock_data: 1 -- SESSION 2 在主键值为 1 的索引项上被阻止
***************** ********** 2.行** **************************
lock_id: 324675598:255:3:2
lock_trx_id:324675598
lock_mode:X
lock_type:RECORD
lock_table:`测试`。 `t5`
lock_index:主
lock_space:255
lock_page:3
lock_rec:2
lock_data: 1 --SESSION 1 持有主键值为 1 的索引 Exclusive项目上的行锁
集合中的 2 行(0.00 秒)
--SESSION 4
mysql>begin;
mysql>更新 t5 设置 c=c,其中 c=3; --Blocked
--SESSION 5
mysql> begin;
查询正常,0 行受影响(0.00 秒)
mysql > update t5 set b=b where b=2;
查询正常,0 行受影响(0.00 秒)
匹配行:1 已更改:0 警告:0
SESSION 5的UPDATE语句没有被阻塞
--SESSION 3查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r.trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.` TRX_QURY` As Waiting_query,L.`Lock_table` as WAITING_TABLE_LOCK,
L.LOCK_INDEX作为 WAITING_INDEX_LOCK,
B.TRX_ID 作为 BLOCKING_TRX_ID,B.`TRX_MYSQL_THREAD_ID` 作为 Blocking_thread,
SUBSTRING(p.host,1,INSTR(p.host,':')- 1) AS 阻塞_主机,
SUBSTRING(p.host,INSTR(p.host,':' )+1) AS 阻塞_端口,
IF(p.command="Sleep" ,p.time,0) ASidle_in_trx,
b.`trx_query` AS 阻塞查询
FROM information_schema.`INNODB_LOCK_WAITS`AS w
内部连接 information_schema.`INNODB_TRX`ASb ON b.trx_id = w.blocking_trx_id< /p>
INNER JOIN information_schema.`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema.`INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
********** ****************** 1.行************************ ******< /p>
Waiting_trx_id: 324675599 --等待锁的事务ID(SESSION 2的事务ID)
Waiting_thread: 2 --等待锁的MYSQL线程ID(MYSQL线程ID) SESSION 2)
wait_time: 1081
waiting_query: update t5 set c=c where c in (1,3)
waiting_table_lock: ` test`。 `t5`
waiting_index_lock: PRIMARY
blocking_trx_id: 324675598 --持有锁的事务ID(SESS的事务IDION 1)
blocking_thread: 1 --持有锁的MYSQL线程ID(SESSION 1的MSYQL线程ID)
blocking_host:
blocking_port:localhost< /p>
idle_in_trx:1103
blocking_query:NULL
************************* ***** 2.行********************************
Waiting_trx_id: 324675601 --等待锁的事务ID(SESSION 4的事务ID)
Waiting_thread: 4 --等待锁的MYSQL线程ID(SESSION 4的MYSQL线程ID)
wait_time: 63
waiting_query: update t5 set c=c where c=3
waiting_table_lock: `test`.`t5`
waiting_index_lock: PRIMARY< /p>
blocking_trx_id: 324675598 --持有锁的事务ID(SESSION 1的事务ID)
blocking_thread: 1 --持有锁的MYSQL线程ID(SESSION的MSYQL) 1) 线程 ID)
blocking_host:
blocking_port: localhost
idle_in_trx: 1103
blocking_query: NULL
2 行一组(0.01 秒)
mysql> 从 innodb_locks\G 中选择*
************ ************** 1.行****** **********************
lock_id:324675601:255:3:4
lock_trx_id:324675601
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index:PRIMARY
lock_space: 255
lock_page: 3
lock_rec: 4
lock_data: 3 --SESSION 4被主键阻塞在索引条目中值 3
************************ ****** 2. 行******** **********************
lock_id:324675598:255:3:4
lock_trx_id:324675598 p>
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index:PRIMARY
lock_space: 255
lock_page: 3
lock_rec: 4
lock_data:3 p>
********* ****************** 3.行****************************
lock_id:324675599:255:3:2
lock_trx_id:324675599
lock_mode:X
lock_type:RECORD
lock_table: `test`.`t5`
lock_index: PRIMARY
lock_space: 255
lock_page: 3
lock_rec: 2
lock_data: 1 -- SESSION 2 在主键值为 1 的索引项处被阻塞
**************************** 4.行** ************* ************
lock_id:324675598:255:3:2
lock_trx_id:324675598
lock_mode:X p>
lock_type:记录
lock_table:`test`.`t5`
lock_index:PRIMARY
lock_space:255
lock_page: 3
lock_rec: 2
lock_data: 1
4 rows in set (0.00 sec)
通过上述测试,我们可以看到,当辅助索引为唯一索引时,SQL语句的执行计划是索引访问扫描或者常量检索。当事务符合WHERE字过滤条件的辅助索引项和满足条件的主键索引项加排它行锁
,索引项不会加锁不满足过滤条件。
5.当update语句执行计划使用full辅助索引的扫描,除了对辅助索引中的所有记录加排它行锁外,还会对主键中的所有记录加排它行锁(即使使用了覆盖索引)。
5.1 SQL执行计划
SQL_1
mysql>解释update t5 set b=b where bin(1,3,5)\G
************************************ 1. 行 ************** *************
ID:1
select_type:SIMPLE
表:t5
类型:索引
possible_keys:b
键:PRIMARY
key_len:4
引用:NULL
行数:7
额外:使用 where;使用临时
集合中的 1 行(0.00 秒)
SQL_1 按索引顺序执行全表扫描。它的优点是避免了排序,缺点是把全表扫描的连续IO变成了随机IO。按索引顺序执行全表扫描会在所有主键索引条目上添加排他行锁。
因为主键索引页子叶为INNODB实际上是表的数据页,它意味着整个表中的所有主键索引条目都会被扫描。独占行锁被添加到记录中。
SQL_2
mysql> 解释 update t5 set c=c where cin (1,3)\G
************ ** ********************** 1. 行****************************
id:1
select_type:SIMPLE
表:t5
类型:范围
possible_keys:c
key: c
key_len: 4
ref: const
rows: 2
额外:使用在哪里;使用临时
集合中的 1 行(0.00 秒)
SQL_2 执行计划使用索引范围扫描。
5.2 锁分析
--SESSION 1
mysql> begin;
查询正常,0行受影响(0.00秒)< /p>
mysql> update t5 set b=b where b in(1,3,5);
查询正常,0 行受影响(0.00 秒)
行匹配:3 更改:0 警告:0
--SESSION 2
mysql> begin;
查询正常,0 行受影响(0.00 秒) p> p>
mysql> update t5 set c=c where c in(1,3); --被阻止
--SESSION 4
mysql> use test
数据库已更改
mysql> begin;
查询正常,0行受影响(0.00 秒)
mysql> update t5 set c=c where c=7; -- 阻塞
SESSION 1执行SQL_1,按照索引顺序使用全表扫描,并对主键的所有索引项加排它行锁,因此SESSION 4被阻塞。
--SESSIO 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r.trx_wait_started, CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
b. trx_id ASblocking_trx_id,b.`trx_mysql_thread_id`ASblocking_thread,
SUBSTRING(p.host,1,INSTR(p.host,':')-1) ASblocking_host,
SUBSTRING(p.host,INSTR(p.host,':')+1) ASblocking_port,
IF(p.command="Sleep",p.time,0) ASidle_in_trx,
p>
p>
b.`trx_query` ASblocking_query
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id=w。 blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema。`INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id p> p>
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
****** ** ********************** 1. 行**************************** **
Waiting_trx_id: 324676114 --等待锁的事务ID(SESSION 2的事务ID)
Waiting_thread: 2 --等待锁的MYSQL线程ID( SESSION 的 MYSQL 线程 ID 2)
wait_time: 1212
waiting_query: update t5 set c=c where c in (1,3)
waiting_table_lock: `test`.`t5`
waiting_index_lock: PRIMARY
blocking_trx_id: 324676113 --持有锁的事务ID(SESSION 1的事务ID)
blocking_thread: 1 --MYSQL 威胁d 持有锁的ID(SESSION 1的MSYQL线程ID)
blocking_host:
blocking_port: localhost
idle_in_trx: 1224
blocking_query: NULL
******** ****************** 2. 行********* *********************
waiting_trx_id: 324676115 --等待锁的事务ID(SESSION 4的事务ID) p>
Waiting_thread: 4 --等待锁的MYSQL线程ID(SESSION 4的MYSQL线程ID)
wait_time: 12
waiting_query: update t5 set c =c where c=7
waiting_table_lock: `test`.`t5`
waiting_index_lock: PRIMARY
blocking_trx_id: 324676113 --持有的事务ID lock(SESSION 1的事务ID)
blocking_thread: 1 --持有锁的MYSQL线程ID(SESSION 1的MSYQL线程ID)
blocking_host:
blocking_port:localhost
idle_in_trx:1224
blocking_query:NULL
集合中的2行(0.00秒)
我们看到 SESSION 1 阻止 SESSION 2 和 S会话4.
mysql>从innodb_locks\G中选择*
**************************** ***** 1 .行********************************
lock_id: 324676115:255:3:8 --SESSION 4 事务ID
lock_trx_id:324676115
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`< / p>
lock_index: PRIMARY
lock_space:255
lock_page:3
lock_rec:8
lock_data:7 - SESSION 4 在主键值为 7 的索引项处被阻塞
******************************** 2 .行* **********************************
lock_id: 324676113:255:3:8< /p>
lock_trx_id: 324676113
lock_mode: X
lock_type: RECORD
lock_table: `test`.`t5`
< p>lock_index:主lock_space:255
lock_page:3
lock_rec:8
lock_data:7
< p>******************************** 3.行******** ********* ************lock_id: 324676114:255:3:2 --SESSION 2的交易ID
lock_trx_id: 324676114
< p>lock_mode:X锁定_type:记录
lock_table:`test`.`t5`
lock_index:PRIMARY
lock_space:255
lock_page:3< /p>
lock_rec: 2
lock_data: 1 --SESSION 2 被阻塞在主键值为 1 的索引项上
********* ********************* 4.行************ ************** *****
lock_id:324676113:255:3:2
lock_trx_id:324676113
lock_mode:X
lock_type:记录
lock_table: `test`.`t5`
lock_index: PRIMARY
lock_space: 255
lock_page: 3
>lock_rec: 2
lock_data: 1
4 rows in set (0.00 sec)
上面的测试证明,执行全表扫描index order 会对所有主键索引项加排他行锁,因为 INNODB 主键索引页子叶实际上是表的数据页,所以对整个表的所有记录加排他行锁
。
6.测试辅助索引为唯一索引时是否会出现间隙锁
6.1 查看执行情况计划
mysql> 解释更新 t5 set b=b 其中b>1 和 b<4\G
***************** ********** 1.行**** **************************
id:1
select_type:SIMPLE
表:t5
类型:范围
possible_keys:b
key: b
key_len: 4
ref: const
rows: 1
额外:使用 where;使用临时
集合中的1行(0.00秒)
6.2锁定测试
--SESSION 1
mysql> begin;< /p>
查询正常,0 行受影响(0.00 秒)
mysql> update t5 set b=b where b>1and b<4;
查询正常,0受影响的行(0.01 秒)
匹配的行:2 已更改:0 警告:0
--SESSION 2
mysql> begin;
< p>mysql> 更新 t5 设置 b=b 其中 b=1; --未阻塞mysql> update t5 set b=b where b=4; --notblocking阻塞
虽然SESSION 1的SQL语句不需要更新b=4的记录,但是在b=4的索引项上加了排他行锁。
--SESSION 4
mysql> update t5 set b=b where b=5; --不阻塞d
--SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r.trx_wait_started ,CURRENT_TIMESTAMP) AS wait_time,
r. `trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_indexAS waiting_index_lock,
b.trx_id AS waiting_trx_id,b.`trx_mysql_thread_id` AS waiting_thread,
SUBSTRING(p.host,1,INSTR(p.host,':')- 1) ASblocking_host,
SUBSTRING(p.host,INSTR(p.host,':') )+1) ASblocking_port,
IF(p.command="Sleep" ,p.time,0) ASidle_in_trx,
b.`trx_query` ASblocking_query
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema。 `INNODB_TRX`AS b ON b.trx_id=w.blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOIN information_schema。`INNODB_LOCKS `AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
ORDER BY wait_time DESC\G
************************ ********** 1.行********************************
waiting_trx_id:324676117
waiting_thread:2
wait_time:137
waiting_query:更新t5设置b=b,其中b=4
waiting_table_lock :`test`.`t5`
waiting_index_lock:b
blocking_trx_id:324676116
blocking_thread:1
blocking_host:
blocking_port:localhost
idle_in_trx:278
blocking_query:NULL
集合中的1行(0.00秒)
mysql > 从 innodb_locks\G 中选择 *
******************************** 1.行*** ********************** **********
lock_id:324676117:255:4:5
>lock_trx_id:324676117
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index: b
lock_space:255
lock_page: 4
lock_rec: 5
lock_data: 4
********** ************** 2.行************************ ********
lock_id:324676116:255:4:5lock_trx_id:324676116
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index:b
lock_space:255
lock_page:4
lock_rec:5
lock_data:4
2 rows in set (0.00 sec)
锁信息中没有间隙锁,只有独占行锁。测试表明,在WHERE子句中使用范围条件过滤时,辅助索引为唯一索引时不会出现间隙锁,但会锁定范围条件中数值最大的索引项(SQL语句
其实这个记录是不需要的)。
--SESSINO 1
mysql> begin;
mysql> update t5 set b=b where b>6;
行匹配:1 更改:0 警告:0
--SESSSION 2
mysql> 开始;
mysql> 插入 t5 值(8,8,8 ); --阻塞
--SESSION 3 查看锁信息
SELECT r.trx_id ASwaiting_trx_id,r.`trx_mysql_thread_id` AS waiting_thread,
TIMESTAMPDIFF(SECOND,r .trx_wait_started,CURRENT_TIMESTAMP) AS wait_time,
r.`trx_query` AS waiting_query,l.`lock_table` AS waiting_table_lock,
l.lock_index AS waiting_index_lock,
B.TRX_ID As BLOCKING_TRX_ID, B.`TRX_Mysql_Thread_id` as Blocking_thread,
Substring (P.Host, 1, Instr(p.Host, ':')-1) ASblocking_host,
< p> SUBSTRING(p.host,INSTR(p.host,':')+1) ASblocking_port,IF(p.command="Sleep",p.time,0) ASidle_in_trx,
b.`trx_query` AS 阻塞查询
FROM information_schema.`INNODB_LOCK_WAITS`AS w
INNER JOIN information_schema.`INNODB_TRX`AS b ON b.trx_id= w.blocking_trx_id
INNER JOIN information_schema。`INNODB_TRX`AS r ON r.trx_id = w.requesting_trx_id
INNER JOINinformation_schema。`INNODB_LOCKS`AS l ON w.requested_lock_id=l.lock_id
LEFT JOIN information_schema.`PROCESSLIST`AS p ON p.id=b.trx_mysql_thread_id
p>ORDER BY wait_time DESC\G
**** ********************** 1.行** ********************** ****
waiting_trx_id:324676121--等待锁的事务ID(SESSION 2的事务ID)
Waiting_thread: 2 --等待锁的MYSQL线程ID(SESSION 2的MYSQL线程ID)
< p> Wait_time: 13waiting_query: 插入 t5 值(8 ,8,8)
waiting_table_lock: `test`.`t5`
waiting_index_lock: b
blocking_trx_id: 324676120 --持有锁的事务ID(SESSION 1的事务ID)
blocking_thread:1 --持有锁的MYSQL线程ID(SESSION的MSYQL线程ID) 1)
blocking_host:
blocking_port:localhost
idle_in_trx:51
blocking_query:NULL
1行in set (0.00 sec)
mysql> select * from innodb_locks\G
******** ************** ***** 1.行****************************
lock_id:324676121:255:4: 1
lock_trx_id:324676121
lock_mode:X
lock_type:RECORD
lock_table:`test`.`t5`
lock_index:b
lock_space:255
lock_page:4
lock_rec:1
lock_data: 最高伪记录 --SESSION 2 被阻塞在表示数据页最后一行的伪记录上
******************** ************** 2.行********************************< /p>
lock_id:324676120:255:4:1
lock_trx_id:324676120
lock_mode:X
lock_type:RECORD
< p> lock_table:`test`.`t5`lock_index:b
lock_space:255
lock_page:4
lock_rec: 1
lock_data:supremum伪记录
set中2行(0.00秒)
当WHERE子句中的范围查询条件较大时输入最后一个如果数据页中的最后一行的虚拟记录被添加了排他行锁,则无法向表中插入大于原最后一行主键值的新记录。
总结:
当辅助索引为唯一索引且SQL语句执行计划为索引访问扫描或常量检索时,只会执行事务d 对满足WHERE子句过滤条件的辅助索引项加排他行锁,对满足条件的主键索引项加排他行锁,对不满足过滤条件的索引项不加锁。
按照索引顺序执行全表扫描,会在主键的所有主键索引条目上添加排他行锁。因为INNODB的主键索引页子叶实际上就是表的数据页,所以它也会对整个表的所有主键索引项加排他行锁。独占行锁被添加到记录中。
当表上没有索引时(没有明确定义的主键,只有INNODB提供的隐藏主键),INNODB会进行全表扫描,并对表中的所有记录加排他行锁桌子。当表上存在主键索引时,执行计划按索引顺序使用全表扫描,对所有主键索引条目添加排他行锁。
在WHERE子句中使用范围条件过滤时,辅助索引为唯一索引时不会产生间隙锁,但会锁定范围条件中数值最大的索引项(SQL语句其实这个记录是不需要的)。
当WHERE子句中的范围查询条件大于表中最后一行时,会对数据页最后一行的伪记录加排他行锁,导致无法查询将大于原始最后一行的主键值插入到表中。新纪录。
看完上面的内容,你是不是对如何进行innodb事务锁的研究有了进一步的了解呢?如果您想了解更多知识或相关内容,请关注行业资讯频道。感谢您的支持。
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > 如何进行innodb事务锁的研究