一、事务与隔离级别
1. 事务的ACID特性
- 原子性:事务内操作要么全部成功,要么全部回滚。
- 一致性:事务执行前后数据逻辑完整性不变(如账户总额一致)。
- 隔离性:并发事务之间互不干扰。
- 持久性:事务提交后数据永久存储。
2. 事务隔离级别与问题
- 读未提交:可能脏读、不可重复读、幻读。
- 读已提交:解决脏读,仍可能不可重复读(如Oracle默认)。
- 可重复读:解决不可重复读,仍可能幻读(如MySQL默认)。
- 串行化:完全隔离,性能最低。
二、锁与并发控制
1. 锁类型
- 共享锁(S锁):允许读,阻止写。
- 排他锁(X锁):禁止其他事务读写。
- 行级锁:粒度更细,减少锁冲突(InnoDB支持)
数据结构:B+树的层级优化
1. 树形结构减少磁盘I/O
- 索引采用B+树结构,3层即可支持亿级数据查询。例如:根节点存储范围指针,中间节点划分数据区间,叶子节点形成有序链表存储实际数据地址。
- 对比普通二叉树,B+树每个节点(磁盘块)可存储更多索引项,大幅降低树的高度。例如:单个磁盘块可存上千个索引项,百万级数据仅需3次磁盘IO即可定位数据。
2. 有序链表支持高效范围查询
- B+树叶子节点通过指针连接,实现WHERE age > 20 AND age < 30类范围查询的快速遍历,而哈希索引仅支持等值查询
三、存储机制:减少数据扫描量
数据库索引的原理,为什么要用 B+树,为什么不用二叉树?
可以从几个维度去看这个问题,查询是否够快,效率是否稳定,存储数据多少,以及查找磁盘次数,为什么不是二叉树,为什么不是平衡二叉树,为什么不是B树,而偏偏是B+树呢?
为什么不是一般二叉树?
如果二叉树特殊化为一个链表,相当于全表扫描。平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。
为什么不是平衡二叉树呢?
我们知道,在内存比在磁盘的数据,查询效率快得多。如果树这种数据结构作为索引,那我们每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块,
但是平衡二叉树可是每个节点只存储一个键值和数据的,
如果是B树,可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就降下来啦,查询效率就快啦。
那为什么不是B树而是B+树呢?
1)B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。
innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。
2)B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。
MVCC实现原理
MVCC的实现原理主要依赖于记录中的三个隐藏字段、undo log、ReadView来实现[1]]。
### 隐藏字段
每行记录除了自定义的字段外,还有数据库隐式定义的DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID等字段[1]]:
- DB_TRX_ID:6字节,记录最近修改事务id,即创建这条记录或者最后一次修改该记录的事务id。
- DB_ROLL_PTR:7字节,回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个旧版本。
- DB_ROW_ID:6字节,隐藏的主键,如果数据表没有主键,那么InnoDB会自动生成一个6字节的row_id