- 场景:注册问题吧 , 查询某个主键id是否存在,第一次查询不存在,即将插入新数据时【刚好另一个人插入了该主键id】,导致这边注册失败
![「MySQL高级篇」MySQL锁机制 && 事务](http://img.zhejianglong.com/231019/0403145329-10.png)
文章插图
- 幻读在“当前读”下才会出现 。
- 幻读仅专指“新插入的行”【update的不算】
数据库的隔离级别有4个 , 由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏写、脏读、不可重复读、幻读这几类问题 。
隔离级别丢失更新脏读不可重复读幻读Read uncommitted×√√√Read committed××√√Repeatable read(默认)×××√Serializable(串行化)××××
备注 : √ 代表可能出现 , × 代表不会出现。
- 读未提交:别人修改了某行数据,还未提交我们就能看到 。
- 读已提交:别人修改了某行数据,得等到提交后我们才能看到 。-- 解决脏读
- 可重复读:别人修改了某行数据,我们也不去读那一行数据,还是读我们当前事务最初的那个未被修改的值 。-- 解决不可重复读
- 串行化:对于同一行记录,“写”会加“写锁”,“读”会加“读锁” 。当出现读写锁冲突的时候 , 后访问的事务必须等前一个事务执行完成,才能继续执行 。
![「MySQL高级篇」MySQL锁机制 && 事务](http://img.zhejianglong.com/231019/0403143506-11.png)
文章插图
- 读未提交:v1=v2=v3=2;B还未提交,A就可以看到了 。
- 读已提交:v1=1,v2=v3=2;等到B提交后,A才能看到 。
- 可重复读:v1=v2=1,v3=2;也就是说,所谓的可重复读,是说在当前事务提交之前,只会读取当前事务最初的值 , 而不去读取其他的事务;
- 串行化:v1=1,v2=1,v3=2;事务A中查询得到值1的时候,就会加了“读锁”,会阻塞其他事务对该行的写操作(上文我们已经有提及到相关的读锁和写锁,忘记了的小伙伴可以翻阅上文看看)所以在事务B执行“将1改成2”的时候,会被锁住 。直到事务A提交后 , 事务B才可以继续执行 。
show variables like 'tx_isolation';
![「MySQL高级篇」MySQL锁机制 && 事务](http://img.zhejianglong.com/231019/0403142A4-12.png)
文章插图
InnoDB 的行锁模式InnoDB 实现了以下两种类型的行锁 。
- 共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁 , 都能访问到数据,但是只能读不能修改 。
- 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改 。
对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加**排他锁**(X);
对于普通SELECT语句,InnoDB不会加任何锁;
可以通过以下语句显示给记录集加共享锁或排他锁。
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE(悲观锁)即手动锁定一行
悲观锁和乐观锁悲观锁:事务必须排队执行 。数据锁住了,不允许并发 。(行级锁:select后面添加for update) 乐观锁:支持并发,事务也不需要排队,只不过需要一个版本号 。![「MySQL高级篇」MySQL锁机制 && 事务](http://img.zhejianglong.com/231019/040314A23-13.png)
文章插图
案例准备工作
create table test_innodb_lock( id int(11), name varchar(16), sex varchar(1))engine = innodb default charset=utf8;insert into test_innodb_lock values(1,'100','1');insert into test_innodb_lock values(3,'3','1');insert into test_innodb_lock values(4,'400','0');insert into test_innodb_lock values(5,'500','1');insert into test_innodb_lock values(6,'600','0');insert into test_innodb_lock values(7,'700','0');insert into test_innodb_lock values(8,'800','1');insert into test_innodb_lock values(9,'900','1');insert into test_innodb_lock values(1,'200','0');create index idx_test_innodb_lock_id on test_innodb_lock(id);create index idx_test_innodb_lock_name on test_innodb_lock(name);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 【MySQL】Navicat15 安装
- 「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景
- 31 《吐血整理》高级系列教程-吃透Fiddler抓包教程-Fiddler如何抓取Android系统中Flutter应用程序的包
- 「MySQL高级篇」MySQL索引原理,设计原则
- 我的世界怎么用附魔台附魔书(我的世界用高级附魔台怎么附魔)
- MySQL 索引失效-模糊查询,最左匹配原则,OR条件等。
- 30 《吐血整理》高级系列教程-吃透Fiddler抓包教程-Fiddler如何抓取Android7.0以上的Https包-番外篇
- MySQL 全局锁、表级锁、行级锁,你搞清楚了吗?
- llinux下mysql建库、新建用户、用户授权、修改用户密码
- RedHat7.6安装mysql8步骤