Mysql锁

行锁

行锁(record lock): 请注意它是针对索引的锁(所以如果没有索引时,最终行锁就会导致整个表都会被锁住)

行锁种类

共享锁(S Lock): 也叫读锁
  1. 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁,即写操作

上锁方式

select * from tableName limit 1 //基于MVCC方式,不上锁

select * from tableName lock in share mode;//读锁(显示)

排它锁(X Lock): 也叫写锁

允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享锁和排他锁 即读和写

上锁方式

insert、update、delete //上写锁(隐式)

select * from tableName for update;//写锁(显示)

意向共享锁(IS)

1.一个事务给一个数据行加共享锁时,必须先获得表的IS锁

意向排它锁(IX)

1.一个事务给一个数据行加排他锁时,必须先获得该表的IX锁

行锁的实现算法

不同算法实现不同的读锁或者写错

Record Lock 锁

单个行记录上的锁
Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表建立的时候没有设置任何一个索引,这时InnoDB存储引擎会使用隐式的主键来进行锁定

使用方式: 根据主键/唯一键锁定确定的记录

update table set xx=xx where id =1//id 唯一索引

select * from tableName where id=1 lock in share mode

Gap Lock 锁:也叫间隙锁

针对索引之间的间隙加锁。需要注意,这仅仅是会影响间隙的插入,不会影响更新

使用方式:普通索引或者范围查询

update table set xx=xx where userName = ‘张三’//userName普通索引

select * from tableName where userName=‘张三’ lock in share mode //userName普通索引

Select * from emp where empid > 100 for update; //范围查询,会对mpid值大于为100所有记录全部枷锁

案例分析

id 唯一索引
uid 普通索引

iduidname
110李四
520王二
1030张三
1525王五
案例一:
START TRANSACTION;
SELECT * from ti WHERE uid=20 for update; 
或
update ti set nane="李四二"  where uid=20;
解释:UID为普通索引,UID会根据大小排序,即20的前后是【10,25】此时:INSERT 语句的UID在【10,25】都是无法插入的,但是更新除了uid=20其他都可以正常更新。
即间隙范围:【10,25】

案例二:
START TRANSACTION;
SELECT * from ti WHERE uid=10 for update; 
间隙范围:【10,20】

Next-key Lock 锁

同时锁住数据+间隙锁
在Repeatable Read隔离级别下,Next-key Lock 算法是默认的行记录锁定算法。

使用方式:同间隙锁一样

三种方式区别
  • 行锁针对确定的记录
  • 间隙锁是两个确定记录之间的范围,即包含行锁的记录;
  • next key lock则是除了间隙还包括确定的记录

参考资料:
https://blog.csdn.net/python8989/article/details/113918316
https://www.cnblogs.com/yaochunhui/p/14186371.html
https://learnku.com/articles/39212
https://segmentfault.com/a/1190000011164489
https://blog.csdn.net/qq_40378034/article/details/90904573
模拟数据;

CREATE TABLE `tn` (
  `id` int(11) unsigned NOT NULL,
  `uid` int(11) unsigned NOT NULL
) ENGINE=InnoDB;
 
CREATE TABLE `tu` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `u_uid` (`uid`)
) ENGINE=InnoDB;

CREATE TABLE `ti` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `u_uid` (`uid`)
) ENGINE=InnoDB;
 
INSERT INTO `tn` (`id`, `uid`) VALUES (1, 10), (5, 20), (10, 30);
INSERT INTO `tu` (`id`, `uid`) VALUES (1, 10), (5, 20), (10, 30);
INSERT INTO `ti` (`id`, `uid`) VALUES (1, 10), (5, 20), (10, 30);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值