MySQL面经

Posted fsdshuron

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL面经相关的知识,希望对你有一定的参考价值。

内容援引自JavaGuide、哔哩哔哩黑马程序员数据库从入门到精通,感谢各位大神原创分享

数据库Mysql

常见的关系型数据库包括mysqlSQL ServerOracle、常见的非关系型数据库RedisMongDB等。

特点

Mysql开源免费,生态完善,支持事务、高可用(读写分离、分库分表)。

基础架构:
  • 服务层:连接器、查询缓存(移除)、分析器、优化器、执行器;通用日志模块binlog
  • 存储引擎层:插件式存储引擎(为表设置存储引擎),支持InnoDBMyISAM等;InnoDB包括redologundolog日志
存储引擎

使用插件式存储引擎,默认InnoDB支持事务、行锁、外键,数据恢复(redolog),MyISAM不支持事务、采用表锁、不支持外键,不支持数据恢复。此外InnoDB主键使用聚簇索引,叶子节点保存记录,MyISAM使用非聚簇索引,叶子节点保存记录的地址,两者均为B+ Tree。

MySQL索引

用于快速查询或快速定位排序的数据结构,常见的索引结构包括Hash树、B树、B+树、红黑树。InnoDB和MyISAM均使用B+树作为索引结构。

索引优缺点

优点:加快检索速度,创建唯一索引保证数据唯一性。缺点:创建、维护索引时间开销,且索引占物理存储空间。

索引结构

  • 为什么不使用hash?
    可能出现哈希碰撞(拉链式)、不支持顺序查找和范围查找。
  • 为什么不使用B树?
    B树节点存索引和数据,B+树只有叶子节点存储索引和数据且构成双向链表,其它节点存储索引,故相同数据量下B树高度更高,查询效率更低,且不支持范围查找。
  • 为什么不使用红黑树?
    红黑树是自平衡二叉查找树,树过高造成大量的磁盘 IO。
  • B+树一般不超过3层,能存储多少数据?
    最小存储单元一页16KB,叶子节点存索引和记录,假设索引和一条记录占1KB,则一页可存16K/1K=16条记录,非叶子节点存索引和指针,假设主键索引为bigint占8字节,指针占6字节,则一个节点可存16k/(8+4)=1170 个指针,两层的B+树可存1170*16条记录,三层的B+树可存1170*1170*16条记录,约两千万数据量。

索引的类别

​ 索引相关的概念包括聚簇索引、非聚簇索引、主键索引、辅助索引、唯一索引、普通索引、联合索引、覆盖索引、前缀索引、全文索引。
​ 聚簇索引,叶子节点保存索引和记录,非聚簇索引叶子节点保存索引和记录相关值(记录地址或主键),且InnoDB存储引擎非聚簇索引不一定需要回表查询(覆盖索引)
​ 主键索引,非null,不可重复,没有显示指定时检查是否存在非null的唯一索引,存在则将该字段作为主键索引否则默认创建6字节的自增索引。设计表时不建议使用过长字段作为主键,不建议使用非单调字段作为主键(引发索引频繁分裂,这解释了为什么不宜使用UUID作为主键)。
​ 联合索引,多个字段一起创建索引,索引使用要求满足最左匹配原则,缺失停止匹配,范围查询右侧字段停止匹配

# 创建(a,b,c)联合索引 等值查询中a、ab、abc均可使用索引,b、bc、c不可使用索引,全部为等值查询时字段顺序对是否使用索引不产生影响;
# 以下语句a,b走索引,c不走索引,建议将区分度高的字段放最左侧以过滤更多数据
select * from t where a=1 and b > 1 and c=1;  
# 如果是建立(a,c,b)联合索引,则a,b,c都走索引

​ 索引下推:非聚簇索引遍历过程中,根据索引中包含的字段过滤不符合条件的记录,减少回表次数。

正确使用索引

  • 是否有必要创建索引,很少查询的表没必要创建索引,频繁更新的字段不适合创建索引;
  • 为哪些字段创建索引,为查询字段,排序字段和分组字段创建索引,优先创建联合索引且区分度高的字段放在左侧(可能产生覆盖索引效果,避免回表,且可以过滤较多记录),字符串类型的字段可优先考虑前缀索引;
  • 避免索引失效,如隐式类型转换、在字段上进行函数操作、or逻辑中某条件字段没有索引则涉及的索引全部失效

索引优化

  • SQL提示,在SQL语句中加入人为提示优化操作use indexignore indexforce index,注意use index仅是建议,不代表优化器会选择的执行计划;
  • 插入数据,批量插入、手动提交事务、主键顺序插入
  • 主键 优化,减少主键长度、主键递增、避免对主键进行修改
  • update优化,InnoDB行锁针对索引,有索引时锁行,没有索引锁表
#id有主键索引,锁行;
update student set no = \'123\' where id = 1; 
#name没有索引,锁表
update student set no = \'123\' where name = \'test\'; 
  • order by优化,多字段排序且一个升序一个降序,要注意创建索引时索引的升序和降序
  • limit优化,覆盖索引、子查询、联表查询
# 优化前
SELECT * FROM xxx limit 1000000,20
# 子查询优化
SELECT * FROM xxx WHERE ID >=(select id from xxx limit 1000000, 1) limit 20;
# 联表优化
SELECT * FROM xxx a JOIN (select id from xxx limit 1000000, 20) b ON a.ID = b.id;
MySQL事务

ACID原则,原子性、一致性、隔离性、持久性

​ 其中一致性是目的,原子性是指要么都执行,要么都不执行,隔离性是指并发事务的独立性,持久性是指事务被提交后可持久化。

并发事务的问题,脏读、不可重复读、幻读

​ 脏读是指事务A读取事务B未提交的数据,不可重复读是指事务A多次读某条记录的读取结果不同,幻读是指幻读指事务A读取某一范围的数据行,事务B在该范围内插入了新行,事务A再读取该范围的数据行时,出现幻影行

并发事务控制,锁+MVCC

​ MySQL中通过读写锁实现并发控制,读锁为共享锁,写锁为排它锁,读读兼容,读写或写写互斥。按粒度MySQL锁又可划分为表锁和行锁,其中表锁不会出现死锁,锁冲突概率高,并发性能低;行锁针对索引字段加锁,会出现死锁,并发度高,行锁 又包括记录锁、间隙锁、临键锁。

  • 行锁发生死锁的场景描述
事务A 事务B
1、delete from xxxx where id = 1;
2、delete from xxxx where id = 2;
3、delete from xxxx where id = 2;
事务A等事务B释放记录2行锁
4、delete from xxxx where id = 1;
事务B等事务A释放记录1行锁
  • MVCC 多版本并发控制

​ MySQL的隔离级别包括读未提交(脏读、不可重复读、幻读风险),读已提交(不可重复读,幻读风险),可重复读(默认隔离级别,幻读风险)和可串行化。特殊的,InnoDB实现的可重复读隔离级别可解决幻读风险,快照读由MVCC机制保证,当前读使用临键锁保证。
​ 在读已提交和可重复读隔离级别下,执行普通select会使用一致性非锁定读MVCC,读记录的快照数据;执行insertdeleteupdateselect...lock in share modeselect...for update会使用锁定读,读取记录的最新数据,并对读取到的记录加锁,即当前读。
​ MVCC机制的实现依赖隐藏字段、Read Viewundo log,InnoDB存储引擎为记录添加默认主键(主键不存在且不存在非空的唯一索引时默认添加)、事务id回滚指针3个隐藏字段;读已提交隔离级别下每次select查询前创建Read View,可重复读隔离级别下事务开始第一次select前创建Read View,Read View用于可见性判断,主要包括m_low_limit_idm_up_limit_idm_idsm_creator_trx_id字段,根据数据可见性算法(比较记录的事务id和Read View中字段)若当前记录对该事务不可见则使用回滚指针进行数据回滚。

三大日志

​ Mysql日志包括查询日志、慢查询日志、错误日志和binlog日志、redolog日志、undolog日志,其中binlog支持数据备份和主从同步,rodolog支持数据 恢复以保证持久性,undolog支持事务回滚以保证原子性和支持MVCC多版本并发控制。

binlog - MySQL

​ binlog日志支持数据备份和主从同步,包括三种记录格式statementrowmixed,其中statement记录SQL语句(获得时间戳等SQL语句容易导致数据备份不一致或主从数据不一致),row记录SQL语句和操作数以规避以上问题,但占用内存,折中方案mixed由MySQL判断是否会引起数据不一致,选择statement或row。
​ binlog的刷盘策略:1)事务提交将binlog cache写入到page cache,系统自行决定刷盘;2)事务提交进行刷盘;3)折中方案,提交事务binlog cache写入到page cache,提交N个事务进行刷盘;

redolog - InnoDB

​ redolog日志支持数据恢复,保证事务的持久性。Mysql数据以页16KB为单位(页、段、区、表),查询记录时从磁盘加载数据页放入缓冲池Buffer pool中,后续查询优先在缓冲池中查找,未命中再从磁盘加载,减少IO开销。更新记录时,更新缓存数据,将数据页上的更新记录到redolog buffer中,根据一定的刷盘策略进行持久化。
​ rodolog刷盘策略:1)事务提交不进行刷盘(Mysql实例挂或宕机可能会有一秒数据的丢失);2)事务提交将redolog buffer写入page cache中(Mysql实例挂没有数据丢失,宕机可能会有一秒的数据丢失);3)事务提交刷盘(Mysql实例挂或宕机不会有数据丢失)。兜底措施后台线程每隔1s将redolog buffer写入到page cache,然后进行刷盘;redolog buffer占用内存到一定阈值后台线程主动刷盘。
​ 为什么要使用redolog,而不是直接将修改的数据页刷盘?通常数据更新只影响数据页中的少量记录,且数据页刷盘是随机写,刷盘成本高。采用redolog记录更新属于顺序写,刷盘成本低,有利于提高数据库的并发能力。
两阶段提交:redolog prepare - binlog - redolog commit。

  • redolog-宕机-binlog,主从结构中,主使用redolog数据恢复,从使用binlog数据恢复,主从数据不一致。
  • binlog-宕机-redolog,主从结构中主使用redolog,从使用binlog,主从数据不一致。
  • 两阶段提交,redolog prepare - 宕机 - binlog - redolog commit,redolog有事务记录,binlog没有事务记录,事务回滚;redolog prepare - binlog - 宕机 - redolog commit,redolog有事务记录,binlog也有对应的事务记录,提交事务恢复 数据。

undolog

​ undolog日志支持事务回滚和MVCC,保证事务的原子性和隔离性。

MySQL执行计划

explain sql

以上是关于MySQL面经的主要内容,如果未能解决你的问题,请参考以下文章

硬核!MySQL数据库面经大全——双非上岸阿里巴巴系列

面经-阿里Lazada电面

大三后端暑期实习面经总结——MySQL篇

大三后端暑期实习面经总结——MySQL篇

mysql培训文档,分享面经!

golang 面经积累