分布式数据库
事务
- 什么是事务?
- 事务就是并发 + 锁
- 事务就是为了保证数据的一致性,ACID保证事务的完整性
- 事务单元
- 商品要建立一个基于GMT_Modified的索引
- 从数据库中写入一行记录,同时更新这行记录的所有索引。
- 删除整章表
- Etc
- 事务单元之间的Happen-before关系
- 读写 写读 读读 写写
- 如何以更快的速度完成?又能保证上面四种操作的逻辑顺序?
- 排队法 优点: 不需要冲突控制,缺点:太慢
- 排他锁
- 读写锁 读读 和 读写做优化
- MVCC 多版本并发控制 主流数据库实现的方法
本质来说就是copy on write 能够做到写不阻塞读。
在写的时候可以做并发读。读读,读写,写读都不冲突。
系统实现很复杂。
事务处理常见问题
- 多个事务,谁先谁后?
- 一个读请求应该读哪一个写之后的数据?(MVCC)
- 解决方法: 逻辑时间戳数据的自增号,写一次加一
SCN(Oracle)
Trx_id(Innodb)
Etc
- 如何恢复故障?
- 业务属性不匹配 恢复: 记住执行操作的反操作的log,然后进行回滚
系统崩溃 恢复: 数据恢复,系统没有恢复完成时,不可以对外提供服务
- 碰到死锁了怎么办?
- 死锁检测和死锁;死锁产生的原因:两个线程,不同方向,相同的资源
- 死锁的解决方案:尽可能不死锁,碰撞检测,等锁超时
深入单机事务
- 事务的ACID
- 原子性
一个事务要么同时成功,要么同时失败
undo日志回滚到之前的版本
例子:ver1 Bob有100元,Smith有0元
ver2 Bob有0元,Smith有0元
(undo: Bob有100元,Smith有0元)
ver3 Bob有0元,Smith有100元
(undo: Bob有0元,Smith有0元)
一致性
Can(Happen before), 保证能看到系统内的所有更改。
两个事务同时发生,处理不同事务的读写并行,就是处理一致性的重要问题。-
隔离性
以性能为理由,对一致性的破坏。
序列化读写(Serializable) 排他锁 单位时间内只有一个事务可以执行。
读写锁:可重复读(Repeatable Read)
读锁不能被写锁升级,只能做到读读并行读已提交(Read Committed)
读锁可以被写锁升级,读读并行,读写并写(写读不能)
出现了不可重复读读未提交(Read Uncommited)
只加写锁,读不加锁
读读并行,
读写并行
写读并行
问题:
可能读到写过程中的数据隔离性小结:
SQL92标准定义的隔离性
序列化,可重复读,读已提交,读未提交
隔离性扩展:
快照(Snapshot Isolation)
多版本并发控制(MVCC)
核心思想:
copy on write + 无锁编程。快照隔离性:
- 针对读多写少场景优化
- 并行度能达到或超过读未提交,而隔离级别很高
- 快照读的情况能保证读到一致性的同时实现读未提交
- 实现了MVCC的系统,快照读几乎等同于序列化读
写写有没有可能并行?
事务就是多个不同的命令组装到一起的过程。
持久性
事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中。
RAID的持久性:
数据丢失的可能:1磁盘的物理损坏。2每一次commit都要fsync到磁盘中----->系统性能的下降。持久性 ---> 延迟
RAID Controller要保证同时成功和失败。
1.提交请求到内存后返回(内存的数据容易丢失)
2.如何将内存的数据打包到磁盘(Group Commit提升系统的吞吐量)
持久性(扩展:持久性保证策略)
核心目的:提升并行度
- 单机事务的典型异常对应策略
业务属性不匹配
回滚-
系统DOWN机
事务的原子性操作只有一个标记commit
commit完成时,之后的请求必须正常的完成
重启后进入recovery模式:提交后事务单元继续完成提交
未提交事务单元回滚
Recovery
- 过程是原子性操作,要保证ACID
- 进程挂掉,重启recovery
- 记录日志,保证不会出现数据丢失
- 事务的调优原则
在不影响业务应用的前提下
- 减少锁的覆盖范围
- Myisam表锁 --> Innodb 行锁
- 原位锁 --> MVCC版本
- 增加锁上可并行的线程数
- 读锁写锁分离、允许并行读取数据
- 多线程并行读取
- 允许更多人读取
- 选择正确锁类型
- 悲观锁:使线程到blocking状态,通知信息Ok的状态切换回等待状态,适合并发争抢比较严重的场景
- 乐观锁:适合并发争抢不太严重的场景
- 单机事务拾疑
-
事务单元扩展
事务单元商品要建立一个基于GMT_Modified的索引
从数据库中读取一行记录
删除整张表
向数据库中写入一行记录,同时更新这行记录
Etc
一组事务单元
Bob给Smith100
Joe领了100
Smith给了Bob100
Two Phase lock
BeginTrx Read from A(lockA) Read from B(lockB) A - 100 B + 100 Commit(unlockA,unlockB)
-
死锁扩展 - U锁(更新锁)
- 可重复读隔离级别下:
Tx1 申请A读锁成功 Tx2 申请A读锁成功 Tx1 申请A读锁升级-等待Tx2读锁释放 Tx2 申请A读锁升级为写锁-等待Tx1读锁释放
- Update set A = A-1 where id = 100 多个线程会死锁
- U 锁:
当探测到有写操作的时候,自动将读锁升级为写锁。
-
MVCC拾遗
- 针对读多写少的场景优化
- 并行度能达到或超过读未提交,而隔离级别很高
分布式事务
目标:像传统单机事务一样的操作,可按需无限扩展
分布式数据库的尝试与问题
- 什么是事务
无论怎么伪装:我们在玩的仍然是个图灵机。 - 网络带来的,网络失去的
- 基于锁的事务实现中遇到的问题
- 从2PL到2PC
- 分布式事务异常处理
- 分布式日志记录
- 分布式事务延迟变大问题
- 结合MVCC的事务实现中遇到的问题
- 分布式顺序问题
本文为https://www.imooc.com/learn/272的课程笔记,如有侵权立删。