ACID
- A:原子性
- C:如果事务是一致的,数据库是一致的,那么结束时也必须是一致的
- I:隔离性
- D:事务提交之后会持久化
原子性
- Logging
记录所有动作到undo log - Shadow Paging
事务运行的时候,拷贝那些用到的page,然后在上面执行事务,当事务提交后,用这些page替换原来的page
一致性
- 数据库一致性
- 事务一致性
https://www.zhihu.com/question/31346392
隔离性
多个事务同时执行时,每个事务无法读到别的事务的中间结果。
如何判断两个事务存在冲突?
- 依赖图
锁
- 锁的类型
- 共享锁
- 排他锁
- 锁控制协议:两阶段锁
- 检测
锁管理器维护一个waits-for图,用来追踪每个事务等待要获取的锁,每个节点是一个事务,如果事务A正在等待事务B的锁,他们之间就有一个箭头,当存在环形结构就说明存在死锁。
检测周期可以设置一个可容忍的系统值。 - 处理
选择一个事务,回滚,选择的标准可以是:- 时间戳
- 查询数
- 被锁住的item数量
- 需要回滚的事务数量
- 预防
根据时间来确定优先级 - 锁的层次
数据库中有成千上万个tuple,我们不能直接管理这些,因此我们需要一些更高层次的抽象锁,让我们同一时间管理更少的锁。
基于时间戳顺序的控制
基于两阶段锁是一种悲观锁,基于时间戳顺序是一种乐观锁。
我们需要向每个tuple添加两个时间戳:
- 写时间戳:最近对tuple写的事务的时间戳
- 读时间戳:最近对tuple读的事务的时间戳
在读阶段,确保自己的时间戳不小于tuple的写时间戳,在写阶段,要确保事务的时间戳小于tuple的写时间戳和读时间戳。有一种优化叫做托马斯写入规则:
基于时间戳的并发控制是不可恢复的。如果事务大多时间很短并且不会发生冲突,那么可以考虑这种病发控制协议。
- 乐观并发控制协议
偷懒,看下别人的总结
MVCC
- 并发控制协议
- 基于时间戳的控制
- 乐观并发控制
- 两阶段锁
- 版本存储
通过版本链(version chain)存储,索引指向链表头,有三种方法: - 垃圾回收
- 索引管理
- 辅助索引的更新
- 逻辑指针:每个tuple对应一个固定的id,这个id不变,我们去改变中间层,也就是将逻辑指针映射到物理指针的这一层,辅助索引保存的是主键索引的副本,每次去查找的时候实际上做两次操作,一次去查找主键,一次根据主键去查找这是的物理数据。
- 物理指针:直接修改物理指针去更新链表头
- 辅助索引的更新
未找到相关的 Issues 进行评论
请联系 @haoqinx 初始化创建