暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

按在地上摩擦面试官之mysql篇四(精讲)

Java八股文宝典 2021-04-20
325






点击上方蓝字关注我们





相信看完mysql前面部分的文章,有了个清晰的认识,但是还是少考虑了一些东西,高并发的时候,数据库是怎么样工作的,对于大部分程序员来说,高并发的时候第一个想到的是加锁,数据库同样也是利用锁机制来实现并发访问。

 面试点:mysql你知道有哪些锁?

一张图了解锁

🔽

▪锁的粒度


a. 表级锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

例子:例如在回家的火车上,你在卧铺车厢想去硬座车厢上厕所,表级锁意味着去往硬座车厢的门关着了,不能进入了。


b.页级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

例子:例如在回家的火车上,你在卧铺车厢想去硬座车厢上厕所,页级锁意味着去往硬座车厢的终于开了,可是这面的厕所也有一个锁,只能去对面。


c.行级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低

例子:例如在回家的火车上,你在卧铺车厢想去硬座车厢上厕所,页级锁意味着去往硬座车厢的终于开了,可是这面的厕所都有人了,只能去对面。去对面发现有两个锁。每个锁代表一个行锁。


对于不同的存储引擎拥有锁级的粒度不一样,以及实现也不一样.

▪MyISAM表级锁


MyISAM只有表级锁,表级模式包括:

a.表共享读锁 (Table Read Lock):不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;


b.表独占写锁 (Table Write Lock):会阻塞其他用户对同一表的读和写操作;

▪ InnoDB行级锁和表级锁


InnoDB 实现了以下两种类型的行锁:

♦共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。


♦排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

首先想一个问题:当我想给一个表加一个排他锁,这时候都需要满足什么条件?


1, 表的排他锁和行的排他锁不能共存,有个事务A对行数据加了排他锁想要修改,事务B对表加排他锁可以修改表中每一行数据这样就形成了冲突。


2, 如果行有排他锁,我想加表的排他锁需要每一行检查是否存在排他锁,会影响性能。


这时出现了意向锁。看看意向锁是如何解决问题的?

InnoDB 实现了以下类型表锁


♦意向锁

· 意向共享锁(IS):事务有意向对表中的某些行加共享锁(S锁)。

-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。

SELECT column FROM table ... LOCK IN SHARE MODE;


· 意向排他锁(IX)事务有意向对表中的某些行加排他锁(X锁)

-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。

SELECT column FROM table ... FOR UPDATE;

通过上述图表看到意向锁之间是兼容的,只有意向共享锁和普通共享锁是兼容的。


注意:这里的排他 共享锁指的都是表锁!!!意向锁不会与行级的共享 排他锁互斥!!!

现在我们回到刚才 users 表的例子:

事务 T1 获取了某一行的排他锁,并未提交:

SELECT column FROM table WHERE id = 1 FOR UPDATE;

复制代码

此时 table表存在两把锁:table表上的意向排他锁与 id 为 1 的数据行上的排他锁。

事务 T2 想要获取 table表的共享锁:

LOCK TABLES table READ;

复制代码

此时事务 T2 检测事务 T1 持有 table 表的意向排他锁,就可以得知事务 T1 必然持有该表中某些数据行的排他锁,那么事务 T2 对 table 表的加锁请求就会被排斥(阻塞),而无需去检测表中的每一行数据是否存在排他锁。大大的提高了性能。从火车车厢这面就看到了是否锁着了,无需一个一个看锁着没有。


意向锁的并发性

面试点:意向锁有什么作用?

我们最后看看意向锁存在的意义,是如何提高并发的,如果你看完下面的例子你就会明白的。


首先我们准备一个简单的表 student 表的例子来概括一下意向锁的意义(减少锁的范围,让更小范围进行加锁,即保证数据的一致性,又增加并发):

事务 A 先获取了某一行的排他锁,并未提交:

SELECT * FROM student WHERE id = 3 FOR UPDATE;

复制代码

1. 事务 A 获取 id 为 3 ,史珍香的数据行上的排他锁。

2. 事务 A 获取了 student 表上的意向排他锁,存储引擎自动添加意向排它锁。

之后事务 B 想要获取 student表的共享锁:


LOCK TABLES student READ;

复制代码

1. 事务 B 检测到事务 A 持有 student表的意向排他锁。

2. 事务 B 对 student表的加锁请求被阻塞(排斥)。

最后事务 C 也想获取 student表中某一行的排他锁:


SELECT * FROM student WHERE id = 1 FOR UPDATE;

复制代码

1. 事务 C 申请 student表的意向排他锁。

2. 事务 C 检测到事务 A 持有 student表的意向排他锁。

3. 因为意向锁之间并不互斥,所以事务 C 获取到了 student表的意向排他锁。

4. 因为id 为 1 的数据行上不存在任何排他锁,最终事务 C 成功获取到了该数据行上的排他锁。

♦排他锁(X)


♦共享锁(S)

▪MVCC行级锁


上面的锁如果你都掌握可能面过了大部分公司,要想更深入那么你需要知道下面的问题?

如果一行数据有排它锁,这时有我只是想查看下数据,都不让,岂不是太残酷了。性能也太差了。这时会有一个方案能解决就是这行数据在上排它锁之前,先考出来一份,我们读取备份出来的数据不就行了么。这个就是一致性的非锁定读。


注意:由于事物的隔离级别不同,导致生成快照的时机不同,这样会出现读取的时候快照的版本不同。


一行记录可能有不止一个快照数据,一般称这种技术为行多版本技术。由此带来的并发控制,称之为多版本并发控制(Multi Version Concurrency Control,MCVCC)

▪行锁的三种算法


a.Record Lock :单个记录上的锁 

锁总会锁住索引记录,锁住的时key。如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB会使用隐式的主键进行锁定。


b.Gap Lock:间隙锁,锁定一个范围,但不包含记录本身

锁定索引记录间隙,确保索引记录的间隙不变

间隙锁时针对事务隔离级别为可重复读或以上级别而配的


Gap Lock在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读

c.Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身


在Next-Key Lock 算法下,InnoDB对于行的查询都是采用这种锁定的算法。可以有效的防止幻读。


当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock 进行优化,将其降级为 Record Lock,即仅锁住索引本身,而不是范围。


当查询的索引为辅助索引时,默认使用Next-Key Locking技术进行加锁,锁定范围是前一个索引到后一个索引之间范围。

▪解决 Phantom Problem


在默认的事务隔离级别下,即REPEATABLE READ下,InnoDB存储引擎次采用Next-Key Locking机制来避免Phantom Problem(幻读问题).这点可能不同与其他的数据库,比如Oracle数据库,因为其可能需要在SERIALIZABLE的事务隔离级别下才能解决Phantom Problem。


Phantom Problem 是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次SQL语句可能会返回之前不存在的行。


set session tx_isolation='read-committed'; 设置事务隔离级别为不可重复读


上一篇

OS:您读到了这里,说明你已经耐得住烦躁了,如今沉下心来学习的人多。你可以识别下方二维码和山虎一起学习,一起进步。无论是工作问题还是生活问题,只要我知道的都可以帮助和你一起分析。

大家好,我是山虎,喜欢数学,编码,算法,股票,AI。经历过一次失败的创业。东西不要死记硬背,要做到自己真正的理解。年轻人就要折腾,年轻人就要折腾,年轻人就要折腾。原创不易,帮忙转发。

JAVA八股文

随时欢迎与我讨论各种问题










点个在看你最好看

文章转载自Java八股文宝典,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论