跳转至

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这个快照

  • 全局锁
    • 数据库处于只读状态,如果有更改的情况,那么就就会被堵塞