这篇文章源自于对秋招面试点的复习,在阿里数据大佬的提点下,总结MySQL的面试知识点主要有以下几点,以后要是想到还会不定时更新,其中知识大部分来自于书本、视频和优秀博客的总结,还有一些图不愿意自己做也是直接复制的。如果有什么错误和补充也希望大家能多多的指出来(文章超长预警)。
1 事务
参考博文:https://www.cnblogs.com/kismetv/p/10331633.html
事务:事务是访问和更新数据库的程序执行的一个逻辑单元;事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。作为一个关系型数据库,MySQL支持事务。
事务的特性(ACID):
- 原子性(Automicity):即整个事务是最小的一个执行单元,不可再分。事务的操作要么完成,要么都不做;如果事务中一个sql语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。
- 一致性(Consistency):即事务执行前后的状态变化是一致的。
- 隔离性(Isolation):隔离性是指事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(Durability):即事务执行完之后,结果是持久的,哪怕发生宕机,结果仍然是事务完成之后的状态
读操作可能会存在的问题:ACID事务特性,能够很好地保证单个事务的数据准确性。但是,在并发的情况下,多个事务共同操作一个数据库时,可能会产生脏读、不可重复读、幻读问题
- 脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据),这种现象是脏读。
- 不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。
- 幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这种现象称为幻读。不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,后者是数据的行数变了。
事务的隔离级别:克服产生脏读、幻读等问题的方法是提高事务的隔离级别。SQL标准中定义了四种隔离级别,一般来说,隔离级别越低,开销越低,可支持并发性越高,但隔离性越差。隔离级别与会产生的问题如下:
读未提交隔离级别最低、可支持并发度最高,无法克服脏读、不可重复读和幻读任何一种问题;读已提交可以克服脏读现象
可重复读克服脏读和不可重复读;可串行化(序列化)可以克服全部三种问题,但是可串行化强制事务串行,并发效率很低,只有当对数据一致性要求极高且可以接受没有并发时使用,因此使用也较少。因此在大多数数据库系统中,默认的隔离级别是读已提交(RC:ORACLE,SQLSERVER)或可重复读(RR:MYSQL)
现在互联网工程一般默认选择RC,主要原因有:
1 在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多!
此时执行语句“select * from test where id <3 for update” ,在RR隔离级别下,存在间隙锁,可以锁住(2,5)这个间隙,防止其他事务插入数据!而在RC隔离级别下,不存在间隙锁,其他事务是可以插入数据!
2 在RR隔离级别下,条件列未命中索引会锁表!而在RC隔离级别下,只锁行。
在RC隔离级别下,其先走聚簇索引,进行全部扫描加锁,但是MySQL做了优化,在MySQL Server过滤条件,发现不满足后,会调用unlock_row方法,把不满足条件的记录放锁。而在RR隔离级别下,会直接把整张表加锁。
MVCC(Multi-Version Concurrency Control,即多版本的并发控制协议):在Mysql中,通过MVCC来利用RR解决脏读、不可重复读、幻读等问题。
数据的读取可以分为两种:快照读和当前读。快照读适用于简单的select语句,当前读是基于临键锁(行锁 + 间歇锁)来实现的,适用于 insert,update,delete, select ... for update, select ... lock in share mode 语句,以及加锁了的 select 语句
- mysql默认是快照读
- 出现(delete、update、insert)时改为当前读,最新的数据也会被读取。
第一步:mysql会为每一条数据,隐式加上两个字段,一个是创建