MySQL 复习总结(MySQL面试必过!!!)

注:本篇是看了别人写的一些面试题,然后记录一下面试题的连接以及自己对面试题部分知识点的理解

 

我首先看的文章是下面这个,真的是太多了,有的没有说的很深,需要再进一步学习下。可以先看下面链接这篇文章,我是看了这个文章写的面试题,把一些不是很清晰记录到这篇博客了。

https://blog.csdn.net/ThinkWon/article/details/104778621

 

 

1.MySQL text长度

mysql的text是65535的字节限制,而pg是不限制的、

2.覆盖索引**聚簇索引(https://blog.csdn.net/alexdamiao/article/details/51934917)

索引覆盖指的是,select 的列在索引中完全包括了,从二级索引拿就行了,不用再查一遍聚簇索引了。
聚簇索引中的每个叶子节点包含主键值、事务ID、回滚指针(rollback pointer用于事务和MVCC)和余下的列。
对于非主键索引---包含了主键值。通过二级索引查询首先查到是主键值,然后InnoDB再根据查到的主键值通过主键索引找到相应的数据块。
主键会创建聚簇索引。

https://blog.csdn.net/universsky2015/article/details/102712058   这个里面的图清晰的解释了。


innodb分主键索引和辅助索引,除了主键索引都是辅助索引(二级索引),都是使用的B+树,B+树数据解节点可以存储更多的键值,然后叶子节点存储data这样就查的很快,B+树非常的矮胖,这样减少IO次数。
如果查辅助索引的话,辅助索引的叶子节点data存储的是主键值,这样就转到查询主键索引了,而索引覆盖指的是 select 项只有你查询的索引键值,不在查主键索引了。

联合索引的B+树存储结构:每个之前存一个键的数据节点,现在存储多个键(联合索引中的键),然后根据联合索引的顺序进行依次键排序,最后叶子节点存储的仍是主键值。


3.左连接

会取所有左表数据,加上右表数据,其中右边要是在一个 on 条件的连接字段上有多条记录,就生成多条(左边重复,右表不重复)。
如果不建立索引会导致左连接是双重for循环,及其消耗性能

5.5之后版本 默认有一个缓存块嵌套循环Block Nested-Loop,这个会缓存多条左表记录,减少IO次数。

4.innodb特性

插入缓存:针对非聚簇索引(非主键索引)。
多个参数:
innodb_change_buffer_max_size 参数设置 Insert Buffer 的最大内存使用量      
InnoDB_flush_log_at_trx_commit  设置 InnoDB 在事务提交后的日志写入频率 因为持久化是先从内存写到binlog 再同步到磁盘的。
0:1s钟写入到日志文件并刷新到磁盘。
1:每次事务提交都被写入到日志文件并刷新到磁盘(默认)
2:每次事务提交都被写入到日志文件但不刷新到磁盘
sync_binlog:MySQL server 在 binary log 每写入 sync_binlog 次后,刷写到磁盘。

二次写
skip_innodb_doublewrite  默认是开启的。
如果数据库发生宕机时,可以通过重做日志对该页进行恢复,但是如果该页本身已经损坏了,进行重做恢复是没有意义的。因此引入了"二次写"方案,提高数据页的稳定性。

doublewrite 的整个流程如下:

对缓存池的脏页进行刷新时,不直接写入磁盘,而是通过 memcpy 函数将脏页复制到内存中的 doublewrite buffer。
将内存中的 doublewrite buffer 写入共享表空间的物理磁盘上(备份)。
将 doublewrite buffer 中的数据真正的刷新到表磁盘中。
如果写 doublewrite buffer 失败,那么这些数据不会写到磁盘,innodb 会载入磁盘原始数据和 redo 日志比较,并重新刷到 doublewrite buffer。
如果写 doublewrite buffer 成功,但是刷新到磁盘失败,那么 innodb 就不会通过redo日志来恢复了,而是直接刷新 double write buffer 中的数据到磁盘。
skip_innodb_double_written 参数可以用来禁止 doublewrite(二次写) 功能。

自适应哈希索引
Innodb存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,二级索引成为热数据,建立哈希索引可以带来速度的提升
innodb_adaptive_hash_index | ON 

5.b&b+树


多路平衡查找树。
只能逐一加载每一个磁盘页。
对于树来说,IO次数就是树的高度,而“矮胖”就是b树的特征之一,它的每个节点最多包含m个孩子,m称为b树的阶,m的大小取决于磁盘页的大小。
b树,数据节点存数据, b+树,只有叶子节点存数据,其余数据节点存的都是键值。

6.exists 和 in 


in 走索引,  exists 走 BNL 缓存块嵌套循环Block Nested-Loop  5.5版本之后的mysql
not in 和not exists:如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not extsts的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

7. innodb的锁  https://segmentfault.com/a/1190000014133576

innodb的所有行锁算法都是基于索引的。没有索引的where就全表加锁。

记录锁  锁行
gap间隙锁  锁区域
next-key锁  锁区域+行

排他锁和共享锁
给行加完排它锁前后都不能有没释放的排它锁或者共享锁,否则加锁失败,例如 悲观锁 select for update 就给行/表加排它锁了。

加共享锁 当前读  select where ? lock in share mode;  这样别的事务在当前事务没提交前,不能加排他锁/更新。这样读的话就是最新数据了。

还有一种方式是 快照读  就是不加共享锁,那么其他事务可以加排它锁,读的只是一个快照了。
InnoDB默认的RR事务隔离级别下,不显式加『lock in share mode』与『for update』的『select』操作都属于快照读,保证事务执行过程中只有第一次读之前提交的修改和自己的修改可见,其他的均不可见;

MVCC 相当于一个行级锁的变种,很多情况下避免了加锁操作。
保存着两个额外的系统版本号,使大多数读操作都可以不用加锁。这样设计使得读操作简单,性能强,并且保证只会读取到符合标准的行。不足之处是没行记录都需要额外的存储空间,需要做更多的检查工作,以及一些额外的维护工作。
MVCC目的是让读写不冲突。记录版本号,版本号每创建一个事务就会++。mvcc具体作用就是在写事务没有提交的情况下,我们也可以进行读


8.乐观锁与悲观锁

乐观锁的实现大致是  数据库加一个版本号version字段,然后做更新操作的时候先查一下
select version from task where id = xxx;
update task set value = newValue,version =  versionValue + 1   where version = versionValue;

悲观锁 (更新/插入多的环境)
begin ;
select res_id from tab where id = 1 for update
update tab set status = 1 where res_id = <res_id>
commit;
FOR UPDATE 仅适用于InnoDB,且必须在事务区块(start sta/COMMIT)中才能生效。 只有明确select for update 的语句中明确id才是行锁,否则表锁。

https://blog.csdn.net/She_lock/article/details/82022431


9.mysql一次SQL查询的具体过程

客户端创建sql --- 查询缓存(一般关掉) --- SQL解析、预处理 查询优化器 --- 存储引擎API执行查询


 

 

参照:

https://blog.csdn.net/ThinkWon/article/details/104778621           一坨面试题

https://blog.csdn.net/alexdamiao/article/details/51934917           聚簇索引&&覆盖索引

https://blog.csdn.net/universsky2015/article/details/102712058   聚簇索引

https://segmentfault.com/a/1190000014133576                            innodb锁

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章