MySQL —— 锁
表锁
添加表锁
lock table t10 write;
查看表锁
show OPEN TABLES where In_use > 0;
关闭表锁
## 方法一:找到锁进程,kill id ;
show processlist;
## 方法二
unlock table;
意向锁
验证意向锁
对记录r加上一个行锁,然后对整张表加锁。
对行记录进行加锁
select * from t10 where name = 'zhang' for update;
开启另一个session,对表加上写锁。当前事务进入阻塞状态,一直到上一个事务提交,释放掉排它锁。
lock table t10 write;
解决数据丢失更新问题
数据丢失更新问题,指的是业务上,T1对r进行读取操作,得到数据score = 1,T2也对r进行读取操作,得到数据score = 1,T1对r进行更新score +1,T2也对r进行更新 score + 1,最后的记过是socre = 2;发生丢失更新的问题。
解决方法是 使用 select....for update
。
begin;
select classid into @classid from student where stuid = 1 for update;
update student set classid=@classid + 1 where stuid = 1;
commit;
间隙锁
创建表插入数据
CREATE TABLE `innodb_lock` (
`a` int(10) NOT NULL,
`b` varchar(255) NOT NULL DEFAULT '',
KEY `index_a` (`a`),
KEY `index_b` (`b`)
) ENGINE=InnoDB;
INSERT INTO `innodb_lock` VALUES ('1', 'b2');
INSERT INTO `innodb_lock` VALUES ('3', '3');
INSERT INTO `innodb_lock` VALUES ('4', '4000');
INSERT INTO `innodb_lock` VALUES ('5', '5000');
INSERT INTO `innodb_lock` VALUES ('6', '6000');
INSERT INTO `innodb_lock` VALUES ('7', '7000');
INSERT INTO `innodb_lock` VALUES ('8', '8000');
INSERT INTO `innodb_lock` VALUES ('9', '9000');
开启一个session,开启事务
set autocommit=0;
update innodb_lock set b = 'haha' where a>1 and a<6;
开启另一个session,开启事务,执行插入语句,会发现存在间隙锁。插入语句陷入阻塞。
set autocommit=0;
insert into innodb_lock values(2,'2000');
Next-key锁
它是间隙锁和普通行锁的一种组合。
单纯只是间隙锁的话,如果记录中只有id=50,则一个事务执行select * from t where id > 49 for update
,另一个事务执行修改id = 50的记录是可以操作成功,不阻塞的。因为间隙锁,锁的是不包含记录本身,只锁区间范围内不存在的记录。
而Next-key锁,则是既锁不存在的记录,又锁存在的记录。
select..for update
什么情况下会锁表
主键不明确,查询非主键时会锁表。这条语句不管查没查到结果,都会锁表。
SELECT * FROM student WHERE stuaddress='beijing' FOR UPDATE;
主键不明确,锁表。
select * from student where stuid <> 1 for update;
关于作者
后端程序员,五年开发经验,从事互联网金融方向。技术公众号「清泉白石」。如果您在阅读文章时有什么疑问或者发现文章的错误,欢迎在公众号里给我留言。