title: Mysql复习总结
categories:
- 秋招面试
tags: - 面试
- mysql
<Excerpt in index | 首页摘要>
别问 问就是为了面试豁出了老命
<The rest of contents | 余下全文>
数据库特性
- 原子性
- 一致性
- 隔离性
- 持久性
原子性
所谓原子性就是事务的执行,要么全部成功,要么全部失败。
一致性
事务操作的完整性约束不会破坏,是原子性的一种表现,例如A向B转账,不会发生A金额发生变化,但是B金额不会发生变化的情况
隔离性
事务之间的操作是互相隔离的,且不受彼此的影响
持久性
事务完成后,所有数据保存在数据库中,持久存在,且不能回滚。
Mysql事务所存在的问题
- 脏读 (Select没有规矩)
事务A插入了一条数据,但是还没有提交,结果事务B去读取数据表,发现了数据A要插入的数据,就是脏读
- 不可重复读 (Update没有规矩)
事务A首次读某条数据为a,但是事务b此时更新了该条数据为b,结果A再次读取这条数据的时候就变成了b,就是不可重复读
- 幻读 (insert,delete没有规矩)
事务A读取了数据表,事务B又插入了几条数据,当事务A再次读取数据表的时候,发现数据多了几条,就是幻读
数据库隔离级别
- 未提交读
事务之间可以读取到事务未提交的数据 (完美的符合了上面出现的所有问题)
- 提交读
事务必须提交之后,提交的数据才可以被其它的事务所看到。
- 可重复读
悲观锁读,若一个事务A读取该条数据,那么不管其它的事务如何去更改这条数据,那么事务A依然读取到的是第一次读取到的数据。
- 串行化
事务操作一个一个按照顺序来,慢是最大的问题
Mysql中的log
- bin log
记录数据库的变更操作,例如delete,insert,update等操作,不会记录select,用于数据的恢复和复制,
记录形式为 一些sql语句还有一些事务id等内容
- redo log
[图片上传失败...(image-1255ac-1594521199607)]
数据的读取或者说是修改操作,是先找到页,再读到内存,如果发生修改,读到内存后,还没来得及刷到磁盘,数据库gg了,那么数据容易丢失,但是redo log会记录页的变更内容,那么恢复数据库的话,就不会丢失数据了。
- undo log
和redo log相反,在读到内存的时候,undo log还会记录相反的内容,比如redo是insert那么undo就是要记录delete的操作,记录的和binlog一样,属于逻辑变化
bin log VS redo log
- binlog记录的是sql的语句等内容,redolog记录的则是XX页在XX行改了XX数据
- binlog存在于所有的数据库系统,redo则是innodb的独家内容
- redolog 和 binlog 必须数据都一致才算是正常,要不然都会回滚
MVCC
多版本并发控制,其实就是为每一条数据都填设一个版本号,因此提交读和重复读所读取的数据都是其中的快照读的一种
ACID如何被保证的
- 原子性如何保证
如果事务失败则使用undolog进行会滚
- 隔离性如何保证
MVCC,即多版本并发控制(Multi Version Concurrency Control),一个行记录数据有多个版本对快照数据。 => 也就是快照读
- 持久性如何保证
redolog用于保证其持久性
存储引擎 (Innodb 和 MyISAM)
- InnoDB支持事务,但是MyISAM不支持事务
- InnoDB支持外键,但是MyISAM不支持外键
- InnoDB是行级锁,但是MyISAM是表级锁
- InnoDB是聚集索引(数据文件和索引是绑定的,也就是说,先查到索引,之后才可以查到数据),但是MyISAM是非聚集索引(也就是说数据和索引是相互分开的,索引直接链接着数据的地址)
(换句话说:InnoDB下,索引就真的是索引,辅助索引则是数据的指针;但是MyISAM的主索引和辅助索引则都是数据指针) - InnoDB不支持全文搜索,但是MyISAM则支持全文搜索 (!mysql5.7之后innoDB也是可以支持全文搜索的)
- 面试考的比较少了,但是可以看看
- InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描,而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可
- MyISAM表格可以被压缩后进行查询操作
InnoDB的自适应hash算法((Adaptive Hash Index, AHI))
InnoDB存储引擎会自动根据访问的频率和模式来自动地为某些热点页建立哈希索引
InnoDB存储引擎会监控对表上各索引页的查询。如果观察到建立哈希索引可以带来速度提升,则建立哈希索引
InnoDB为什么推荐使用自增ID作为主键?
自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。
数据结构 - 查找树,红黑树,b树和b+树
查找树是不平衡的,举个例子来说,如果是插入(1,2,3,4,5),那么数据查找在查找树中会全部在一边,构成一个链表
红黑树是平衡的,但是红黑树是一颗二叉树,深度问题还是没有解决
b树在一定程度上其实已经解决了前两个的问题,简单的说就是:多叉的平衡树;但是b+树需要指定叶子节点的最大值,因此是无法也不能更好的始应数据库的需求
b+树是b树的升级版,b+树的非叶子节点只存储数据索引,且从左向右也是从小到大的排列,这样就可以更多的让索引存储,之后在叶子节点才是真正的数据部分,且每个叶子节点的最后会是指针指向旁边的叶子节点
索引
索引类型
- 普通索引
就是最基本的添加一个索引,用于加速查找
- 唯一索引
列值必须唯一,可以为空值,加速查找
- 主键索引
利用主键作为索引,而且不可以为空,加速查找
- 覆盖索引
就是查查找的数据也是索引值
- 组合索引
几列合并成一个索引,但是遵循最左原则
- 全文索引
全文分词查找,innoDB是做不到的,需要第三方,比如es等
索引带来的问题
使用索引的时候不可以随便使用,过度的使用索引会导致消耗大量的资源,热点核心业务的数据应该多使用索引
索引会浪费磁盘空间,不要创建非必要的索引,插入、更新、删除需要维护索引,带来额外的开销,索引过多,修改表的时候重构索引性能差
但是索引使用的时候可以减少查询次数,提高效率
查询的顺序
- from 从哪个表查询
- where 初步过滤条件
- group by 过滤后进行分组[重点]
- having 对分组后的数据进行二次过滤[重点]
- select 查看哪些结果字段
- order by 按照怎样的顺序进行排序返回[重点]
数据库设计三范式
- 1NF : 原子性 字段不可再分,否则就不是关系数据库
- 2NF : 唯一性 每一个主键是唯一的
- 3NF : 要求一个数据库表中不包含已在其他表中已包含的非主关键字信息, 例如 存在一个课程表,课程表中有课程号(Cno),课程名(Cname),学分(Ccredit),那么在学生信息表中就没必要再把课程名,学分再存储到学生表中,这样会造成数据的冗余