[MySQL]-行锁、表锁、间隙锁详解学习

158 阅读1分钟

MySQL行锁、表锁、间隙锁详解学习

环境准备

创建表

CREATE DATABASE TEST_INNODB;
use TEST_INNODB;
create table TEST_INNODB_LOCK(
    a INT(11) primary key ,
    b VARCHAR(20)
) ENGINE INNODB DEFAULT CHARSET = UTF8;
# 插入数据
insert into TEST_INNODB_LOCK values(1,'a');
insert into TEST_INNODB_LOCK values(2,'b');
insert into TEST_INNODB_LOCK value (3,'c');
insert into TEST_INNODB_LOCK value (4,'d');

结果

创建索引

CREATE INDEX INDEX_LOCK_A ON TEST_INNODB_LOCK(a);
CREATE INDEX INDEX_LOCK_B ON TEST_INNODB_LOCK(b);
# 自动提交变成手动提交
set autocommit = 0;

演示行锁(写&读)

  1. 在一个窗口控制台执行:
update test_innodb_lock set b='a1' where a = 1;

结果

  1. 新的控制台窗口: 结果:

新开的窗口控制台看到的是旧数据,这是因为 a = 1 的这行记录被 之前的窗口执行的 SQL语句抢到了锁,且没有执行 commit 提交操作。所以后面的窗口控制台看到的是旧数据。这就是 MySQL 隔离级别中的"读已提交"。

4.在的旧的窗口控制台执行

commit;

结果:

新的控制台窗口已经读取到最新数据

行锁(写&写)

  1. 一个控制台窗口console执行
update test_innodb_lock set b='a2' where a = 1;
select * from test_innodb_lock;

这时候并没有 commit 提交,锁是console持有的

  1. console_1 也执行修改

console_1 一直处于阻塞状态,因为console还没有执行 commit,还持有锁。console_1 抢不到 a = 1 这行记录的锁,因此一直阻塞等待。

  1. console执行commit 操作 执行update成功!

表锁

  • 当索引失效的时候,行锁会升级成表锁
  • 索引失效的场景:
    • 对索引自动 or
    • 手动的换型。比如 integer变成就变成了 String