锁的分类(一)
-
简介
-
从数据操作的类型划分
:读锁、写锁
读锁 :也称为 共享锁 、英文用 S 表示。针对同一份数据,多个事务的读操作可以同时进行而不会互相影响,相互不阻塞的。
写锁 :也称为 排他锁 、英文用 X 表示。当前写操作没有完成前,它会阻断其他写锁和读锁。这样就能确保在给定的时间里,只有一个事务能执行写入,
并防止其他用户读取正在写入的同一资源。
对于 InnoDB 引擎,读锁和写锁既可以加在表上,也可以加在行上
2个读锁是兼容的
1个读锁1个写锁是不兼容的
2个写锁是不兼容的
- 锁定读
# 读的时候加S锁
SELECT ... LOCK IN SHARE MODE;
# 写法2
SELECT ... FOR SHARE;
# 读的时候加X锁
SELECT ... FOR UPDATE;
- 代码案例
# 案例1:开启2个共享锁
# 打开1个mysql页面
# 开启1个事务
begin
# 读user表的时候加S锁
select * from user for share;
# 当前事务未关闭时,打开第2个mysql页面
# 开启第2个事务
begin
# 读user表的时候加S锁
select * from user for share;
# 可以读取到数据
# 案例2:开启1个共享锁,开启1个排他锁
# 打开1个mysql页面
# 开启1个事务
begin
# 读user表的时候加X锁
select * from user for update;
# 当前事务未关闭时,打开第2个mysql页面
# 开启第2个事务
begin
# 读user表的时候加X锁
select * from user for update;
# 这时第2个mysql页面中会阻塞,因为共享锁和排他锁是不兼容的
# 需要关闭第1个事务
commit
# 这时第2个mysql页面中才查询到数据
- NOWAIT、SKIP LOCKED语法
# 在SELECT ...FOR UPDATE或SELECT ...FOR SHARE后面添加NOWAIT、SKIP LOCKED语法
# NOWAIT会立即报错返回
# SKIP LOCKED也会立即返回,只是返回的结果中不包含被锁定的行
- 代码案例
# 案例1:使用NOWAIT
# 打开1个mysql页面
# 开启1个事务
begin
# 读user表的时候加X锁
select * from user for update;
# 当前事务未关闭时,打开第2个mysql页面
# 开启第2个事务
begin
# 读user表的时候加X锁
select * from user for update nowait;
# 这时第2个mysql页面中,因为共享锁和排他锁是不兼容的,会直接返回报错信息
# 案例1:使用SKIP LOCKED
# 打开1个mysql页面
# 开启1个事务
begin
# 读user表的时候加X锁
select * from user for update;
# 当前事务未关闭时,打开第2个mysql页面
# 开启第2个事务
begin
# 读user表的时候加X锁
select * from user for update skip locked;
# 这时第2个mysql页面中,因为共享锁和排他锁是不兼容的,会直接返回没有锁定的行