mysql
学习一下后台的数据库,客户端好像是有sqllite的。应该对以后还是有帮助的
题目:
查询
- mysql在收到指令的时候,会对其语义分析,语法分析,然后进行普遍的优化,然后再执行
存储
数据库是怎么存储在硬盘中的?
- 按照页的单位来进行读取,每一个页的大小是16KB,这样可以减少磁盘IO的性能损耗
- 如果表中数据量比较大的情况下,会按照区块划分,每一个大小是1MB,16kb的页来说,那么就是64个页为一区
索引
查询数据库的目录,感觉主键就可以当成一个索引,
二级索引
- 一个表只有一个主键索引,但是查询的时候可能不光会查询这个索引结构
- 对于主键索引来说,叶子节点存储的是实际数据,但是二级索引来说,叶子节点存储的是主键值,而不是实际数据。叶子节点存储的是主键,然后再次根据主键查询,查询真正的数据,所以会
回表
(所以这里会发生两次查询)
联合索引
- 一般来说,是按照一个索引来选择表的构建的,联合索引是按照两个关键字进行匹配 -> 多个字段合成一个索引
- 联合索引存在
最左匹配
原则,按照最左优先的顺序进行索引匹配,如果说不遵循,索引就会失效。
索引下推
索引下推
: Mysql对数据查询进行优化,可以减少回表的次数(在二级索引的时候直接进行判断,不需要再次回表)
索引失效的例子
这里如果查询的时候,如果没有走索引,那么就会走全表扫描。时间就会浪费
这个好像可以在type
里面看,走的是索引还是索引失效的,可以进行判断
- 使用
like %xx
或者like %xx%
这样的模糊匹配,就会导致索引失效,走全表扫描- 存储结构不是这样存储的,是按照数值有序存储,这样肯定失效,只能走全表扫描
- 对索引使用函数
- 索引保存的是初始值,而不是计算过后的数值,所以这里就寄了,
- 但是新版本添加了函数索引,
- 对索引进行表达式计算
- 对索引隐式类型转换
- 联合索引非最右排序
B+树
mysql中存储数据的结构是使用B+树这个数据结构,他有以下优点
- 所有的数据都存储在叶子节点上,那么对于数据来说,磁盘IO比较平均的,每次访问的时间大致是相同的
- 在叶子节点中,叶子节点是双向链表的,那么就可以支持范围查询
- 查询,删除等操作都是\(logn\)的时间复杂度,比较平均
事务
mysql数据库中的操作是不可分割的,要么全部执行成功,要么全部失败,不会出现中间状况,这就是一个事务
特性
- 原子性:对于所有操作来说,要么成功,要么不成功,不会出现中间两个不同的环环节,如果出现错误,那么会进行回滚,回滚到事务开始前的状态。
- 一致性:双方操作完之后,数据保证一定的约束,比如说双方进行转账的时候,转帐前和转账后其数据总和是保持一致的
- 隔离性:多个并发事务同时保持对数据进行读写的能力,隔离性可以防止多个事务由于交叉而导致的数据的不一致,
- 持久性:数据操作完之后,修改是永久的,即使系统故障也不会丢失
隔离级别
并发事务会导致事务的出现脏读,不可重复读,幻读的情况。反正我是记不清楚。。(
- 脏读:读到其他事务未提交的数据
- 对单个数据进行上锁
- 不可重复读:前后读的数据不一致 (数据)
- 幻读:前后读取的记录数量不一致 (记录数量,数据集)
- 记录数量不一致,一般是范围,那么可以对这个范围上一个锁
严重程度:脏读 > 不可重复读 > 幻读
对其,MySQL有以下隔离水平:
- 串行化:很简单,会有锁,如果出现冲突,因为锁的存在,事务B必须等待事务A完成之后才能执行,
- 可重复读:一个事务执行过程的数据,一直等到这个事务开启时看到的数据是一致的
- 读提交:一个事务提交之后,做的变更才能被其他事务看到
- 读未提交:一个事务还没提交,其做的改变已经被其他事务看到
隔离水平高低: 串行化 > 可重复读 > 读提交 > 读未提交
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | ✅ | ✅ | ✅ |
读已提交 | ❌ | ✅ | ✅ |
可重复读 | ❌ | ❌ | ✅ |
串行化 | ❌ | ❌ | ❌ |
可重复读是Mysql InnoDb引擎默认的隔离方式
避免幻读
Mysql的默认隔离级别是可重复读,虽然解决不了幻读,但是可以解决很大一部分幻读。
- 针对快照读(select),通过MVCC解决幻读
- 当前读入(select ... for update): 通过next-key(记录锁 + 间隙锁)方式解决幻读
- 因为幻读是针对一个范围的读入错误,那么就对这一个范围加锁其实就行了
Read View
相当于对于个读的事务的一个快照,在开启一个事务之前,就有一个Read View,在整个事务之间,都会使用整个Read View这个快照
锁
- 全局锁
- 数据库处于只读状态,如果有更改的情况,那么就就会被堵塞