Skip to content

Commit c6cf244

Browse files
新增最新面试资料
1 parent 4748d91 commit c6cf244

File tree

7 files changed

+12997
-1638
lines changed

7 files changed

+12997
-1638
lines changed

docs/dataStructures-algorithms/高频算法题目总结.md

Lines changed: 6106 additions & 1619 deletions
Large diffs are not rendered by default.

docs/database/MySQL面试题一.md

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ i++;
197197

198198
如果我们需要避免不可重复读的问题的发生,那么我们可以使用**Next-Key Lock算法**(设置事务的隔离级别为`READ REPEATABLE`)来避免,在MySQL中,不可重复读问题就是Phantom Problem,也就是**幻像问题**
199199

200+
#### 幻读
201+
202+
幻读本质上也属于不可重复读的情况,会话 A 读取某个范围的数据,会话 B 在这个范围内**插入**新的数据,会话 A 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
203+
200204
#### 丢失更新
201205

202206
**丢失更新:** 指的是一个事务的更新操作会被另外一个事务的更新操作所覆盖,从而导致数据的不一致。在当前数据库的任何隔离级别下都不会导致丢失更新问题,要出现这个问题,在多用户计算机系统环境下有可能出现这种问题。
@@ -233,7 +237,37 @@ i++;
233237

234238
![](http://image.ouyangsihai.cn/Fh1arOgS78BnrjBXKwGw8NSP27uM)
235239

240+
### MVCC 实现原理
241+
242+
在理解 MVCC 的实现原理之前,需要先带大家了解一下 **版本链**
243+
244+
我们都知道,在 InnoDB 每个事务都有一个唯一的事务 ID(transaction id),该 ID 是在启动一个事务时申请的并且严格顺序递增。
245+
246+
另外,数据表中的每行数据都是有多个版本的,每次事务更新都会生成新的版本,并且把本次事务的 transaction id 赋值给这个数据版本的事务 ID(row trx_id)。
247+
248+
除此之外,还有一个 roll_pointer指针,该指针 ROLL_PTR 把一个数据行的所有快照版本记录连接起来。
249+
250+
undo log 的回滚机制也是依靠这个版本链,每次对记录进行改动,都会记录一条undo日志,每条undo日志也都有一个roll_pointer属性(INSERT操作对应的undo日志没有该属性,因为该记录并没有更早的版本),可以将这些undo日志都连起来,串成一个链表,所以现在的情况就像下图一样:
251+
252+
![](http://image.ouyangsihai.cn/Fidy__nsyaUj1N3MGfGlu1hjbYMM)
253+
254+
有了上面的知识储备,所谓的 MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用**读已提交(READ COMMITTD)****可重复读(REPEATABLE READ)** 这两种隔离级别的事务在执行普通的 SELECT 操作时访问记录的版本链的过程,这样子可以使不同事务的读-写、写-读操作并发执行,从而提升系统性能。
255+
256+
这两个隔离级别的一个很大不同就是:生成 ReadView 的时机不同,READ COMMITTD 在每一次进行普通 SELECT 操作前都会生成一个 ReadView,而 REPEATABLE READ 只在第一次进行普通 SELECT 操作前生成一个ReadView,数据的可重复读其实就是 ReadView 的重复使用。
236257

258+
#### **ReadView**
259+
260+
MVCC 维护了一个 ReadView 结构,主要包含了当前系统未提交的事务列表 TRX_IDs {TRX_ID_1, TRX_ID_2, ...},还有该列表的最小值 TRX_ID_MIN 和 TRX_ID_MAX。
261+
262+
在进行 SELECT 操作时,根据数据行快照的 TRX_ID 与 TRX_ID_MIN 和 TRX_ID_MAX 之间的关系,从而判断数据行快照是否可以使用:
263+
264+
- TRX_ID < TRX_ID_MIN,表示该数据行快照时在当前所有未提交事务之前进行更改的,因此可以使用。
265+
- TRX_ID > TRX_ID_MAX,表示该数据行快照是在事务启动之后被更改的,因此不可使用。
266+
- TRX_ID_MIN <= TRX_ID <= TRX_ID_MAX,需要根据隔离级别再进行判断:
267+
- 提交读:如果 TRX_ID 在 TRX_IDs 列表中,表示该数据行快照对应的事务还未提交,则该快照不可使用。否则表示已经提交,可以使用。
268+
- 可重复读:都不可以使用。因为如果可以使用的话,那么其它事务也可以读到这个数据行快照并进行修改,那么当前事务再去读这个数据行得到的值就会发生改变,也就是出现了不可重复读问题。
269+
270+
在数据行快照不可使用的情况下,需要沿着 Undo Log 的回滚指针 ROLL_PTR 找到下一个快照,再进行上面的判断。
237271
### 锁相关
238272

239273
> 数据库中锁机制,说说数据库中锁的类型
@@ -258,10 +292,17 @@ InnoDB存储引擎中存在着不同类型的锁,下面一一介绍一下。
258292

259293
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB存储引擎支持一种额外的锁方式,就称为**意向锁**,意向锁在 InnoDB 中是**表级锁**,意向锁分为:
260294

261-
262295
- 意向共享锁:表达一个事务想要获取一张表中某几行的共享锁。
263296
- 意向排他锁:表达一个事务想要获取一张表中某几行的排他锁。
264297

298+
在存在行级锁和表级锁的情况下,事务 T 想要对表 A 加 X 锁,就需要先检测是否有其它事务对表 A 或者表 A 中的任意一行加了锁,那么就需要对表 A 的每一行都检测一次,这是非常耗时的。
299+
300+
意向锁在原来的 X/S 锁之上引入了 IX/IS,IX/IS 都是表锁,用来表示一个事务想要在表中的某个数据行上加 X 锁或 S 锁。有以下两个规定:
301+
302+
- 一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁;
303+
- 一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁。
304+
305+
通过引入意向锁,事务 T 想要对表 A 加 X 锁,只需要先检测是否有其它事务对表 A 加了 X/IX/S/IS 锁,如果加了就表示有其它事务正在使用这个表或者表中某一行的锁,因此事务 T 加 X 锁失败。
265306

266307
另外,这些锁之间的并不是一定可以共存的,有些锁之间是不兼容的,所谓**兼容性**就是指事务 A 获得一个某行某种锁之后,事务 B 同样的在这个行上尝试获取某种锁,如果能立即获取,则称锁兼容,反之叫冲突。
267308

@@ -276,6 +317,8 @@ InnoDB存储引擎中存在着不同类型的锁,下面一一介绍一下。
276317

277318
![](http://image.ouyangsihai.cn/Fgf-Pg6JPVJ7CmPyrdcow_5q-VZm)
278319

320+
**注意:** 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁。
321+
279322
> MySQL中锁的粒度
280323
281324
在数据库中,锁的粒度的不同可以分为表锁、页锁、行锁,这些锁的粒度之间也是会发生升级的,**锁升级**的意思就是讲当前锁的粒度降低,数据库可以把一个表的1000个行锁升级为一个页锁,或者将页锁升级为表锁,下面分别介绍一下这三种锁的粒度(参考自博客:https://blog.csdn.net/baolingye/article/details/102506072)。
@@ -696,5 +739,45 @@ MyISAM引擎会把表自增主键的最大id记录到数据文件中,做了持
696739

697740
关系型数据库的优势在于支持更加复杂的sql操作、事务支持和使用表结构更加易于维护。
698741

742+
> binlog、redo log和undo log
743+
744+
redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。
745+
746+
比如 MySQL 实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的**持久性与完整性**
747+
748+
redo log 记录的是数据的物理变化。
749+
750+
751+
binlog 记录了数据库表结构和表数据变更,比如update/delete/insert/truncate/create。它不会记录select(因为这没有对表没有进行变更),存储着每条变更的SQL语句(当然从下面的图看来看,不止SQL,还有XID「事务Id」等等)。
752+
753+
主要有两个作用:**复制和恢复数据**
754+
755+
- MySQL在公司使用的时候往往都是一主多从结构的,从服务器需要与主服务器的数据保持一致,这就是通过binlog来实现的
756+
757+
- 数据库的数据被干掉了,我们可以通过binlog来对数据进行恢复。
758+
759+
undo log主要有两个作用:**回滚和多版本控制(MVCC)**
760+
761+
在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚
762+
763+
undo log 主要存储的也是**逻辑日志**,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。
764+
765+
这也应该容易理解,毕竟回滚嘛,跟需要修改的操作相反就好,这样就能达到回滚的目的。因为支持回滚操作,所以我们就能保证**原子性**
766+
767+
> mysql 优化思路
768+
769+
https://mp.weixin.qq.com/s/jtuLb8uAIHJNvNpwcIZfpA
770+
771+
https://www.cnblogs.com/jay-huaxiao/p/12995510.html
772+
773+
> mysql 语法和复杂语句练习题
774+
775+
- 常用语法
776+
777+
https://www.jb51.net/article/156898.htm
778+
www.cyc2018.xyz/算法/基础/算法 - 排序.html
699779

780+
- 练习题
700781

782+
https://www.jianshu.com/p/476b52ee4f1b
783+
www.cyc2018.xyz/算法/基础/算法 - 排序.html

0 commit comments

Comments
 (0)