第三讲: 事务的隔离性
在MySQL中,事务支持是在引擎层实现的。MySQL是一个支持多引擎的系统,但并不是所有的引擎都支持事务。比如MySQL原生的MyISAM引擎就不支持事务,这也是MyISAM被InnoDB取代
的重要原因之一。
事务,特性ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一
致性、隔离性、持久性)。
事物的隔离性级别:
“隔离性”:SQL标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )。
- 读未提交:一个事务还没提交时,它做的变更就能被别的事务看到。
- 读提交:一个事务提交之后,它做的变更才会被其他事务看到。
- 可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
- 串行:顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
第四、五讲:索引
索引的数据结构形式:
索引的出现是为了提高查询效率,主要实现方式有三种,分别是哈希表、有序数组和搜索树。
- 因为不是有序的,所以哈希索引做区间查询的速度是很慢。如果你现在要找身份证号在[ID_card_X, ID_card_Y]这个区间的所有用户,就必须全部扫描一遍了。所以,哈希表这种结构适用于只有等值查询的场景 哈希表这种结构适用于只有等值查询的场景.
- 有序数组在等值查询和范围查询场景中的性能就都非常优秀。但是,在需要更新数据的时候,你往中间插入一个记录就必须得挪动后面所有的记录,成本太高。有序数组索引只适用于静态存储引擎,这类不会再修改的数据。
- 为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该
- 使用二叉树,而是要使用“N叉”树。这里,“N叉”树中的“N”取决于数据块的大小。
InnoDB 的索引模型
InnoDB使用了B+树索引模型,每一个索引在InnoDB里面对应一棵B+树。
索引类型分为主键索引和非主键索引。
- 主键索引的叶子节点存的是整行数据。在InnoDB里,主键索引也被称为聚簇索引(clustered index)。
- 非主键索引的叶子节点内容是主键的值。在InnoDB里,非主键索引也被称为二级索引(secondary index)。
基于主键索引和普通索引的查询有什么区别?
- 如果语句是select *fromTwhere ID=500,即主键查询方式,则只需要搜索ID这棵B+树;
- 如果语句是select *fromTwhere k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID的值为500,再到ID索引树搜索一次。这个过程称为回表。基于非主键索引的查询需要多扫描一棵索引树。
索引维护
1. 性能考虑:
- 自增主键的插入数据模式,正符合了我们前面提到的递增插入的场景。每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂。
- 有业务逻辑的字段做主键,则往往不容易保证有序插入,这样写数据成本相对较高(因为在数据列中间插入数据,容易造成节点分裂)。
2. 存储空间考虑:主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。
所以,从性能和存储空间方面考量,自增主键往往是更合理的选择。
适合用业务字段直接做主键情景(典型的KV场景):1. 只有一个索引;2. 该索引必须是唯一索引。
数据库索引的概念,包括了覆盖索引、前缀索引、索引下推。
由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有
可能经过索引优化,避免回表过程呢?
覆盖索引
在查询里面,索引k已经“覆盖了”我们的查询需求,我们称为覆盖索引。 由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
前缀索引
在建立联合索引的时候,如何安排索引内的字段顺序?
最左前缀原则:B+树这种索引结构,可以利用索引的“最左前缀”,来定位记录。
第一,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。第二,考虑的原则就是空间
索引下推
在MySQL 5.6之前,只能从ID3开始一个个回表。到主键索引上找出数据行,再对比字段值。
而MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。