文章目录
- MySQL 锁机制
- 表锁
- 读锁
- 场景一
- 场景二
- 场景三
- 总结
- 写锁
- 场景一
- 场景二
- 场景三
- 总结
- 行锁
- 场景一
- 场景二
- 总结
- 间隙锁
- 缺点
- 如何锁定一行
MySQL 锁机制
表锁
读锁
查看哪些表被加锁了
语法:show open tables
添加读锁
read 读锁关键字 | write 写锁关键字
语法:lock table 表名 read
解锁
语法:unlock table
场景一
当查询一加了读锁后,查询一无法进行查询其它表
-- 给student添加读锁
lock table student read
-- 当我们再去查询user表时,直接报错
select * from user
场景二
当我们去修改时,也会报错,因为加的是读锁
update student set StudentName = '小花3' where Id = 1
场景三
查询二(新建查询)中可以去查询其它表,但是修改当前表会进入阻塞状态(一直进行查询,指到解锁之后)
update student set StudentName = 'XXX5' where Id = 1
总结
加了表锁之后,查询1无法进行查询其它表(相当于这次借的钱没还,下次又来借钱,肯定是不借),查询1不能修改当前已经被锁表和其它表,会导致报错,除非解锁后回复正常操作
在查询1加了表锁之后,查询2可以查询其它表,但不能修改其它表和当前已经锁的表,修改当前锁的表会导致一直阻塞,除非解锁后回复正常操作
写锁
场景一
--给student添加写锁
lock table student write;
查询一:可以查询当前student,但是不能查询其它表(user…)
场景二
查询一:可以修改当前表,不能修改其它表
update student set StudentName = 'XXX2' where Id = 1
场景三
查询二:不可以查询当前student,可以查询其它表(user…)
select * from student
总结
查询一添加写锁后,查询一:可以查询当前student,但是不能查询其它表(user…),查询一:可以修改当前表,不能修改其它表,查询二:不可以查询当前student,可以查询其它表(user…)
行锁
场景一
查询一和查询二分别设置关闭自动提交
语法:set autocommit = 0;
设置(打开)自动提交
语法:set autocommit = 1;
当查询一修改完数据后,查询二中无法进行查看
查询二:执行完commit后
查询一:执行完commit后,再次查询既可看到更新后的数据
场景二
当查询二修改数据后,未进行commit时,查询一不能修改当前查询二修改的那台未进行commit时的数据,否则导致阻塞,只能等待
只要当查询二commit后,查询一才能看到更改后的数据
总结
当双方同时修改同一行数据时,修改完后必须要进行手动提交commit,对方才可以看到你修改的数据,否则你修改完后,别人是看不到的,别人也无法修改当前这条数据,否则就会出现阻塞
间隙锁
间隙锁
当我们用范围条件检索数据,并请求共享或排他锁时,InnODB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录
这种锁机制就是所谓的间隙锁(Next-Key锁)
缺点
当锁定一个范用键值之后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据。在某些场景下这可能会对性能造成很大的危害(造成间隙锁后,锁定键值范围内的数据无法插入和修改)
如何锁定一行
当前查询一窗口的某行数据被锁定时,查询二窗口无法进行修改数据,当查询一修改完提交后,查询二可以修改
语法:selectfrom test_innodb_lock where a=8 for update
只需加上 for update 关键字即可