在线分布式数据库原理与实践

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35974759/article/details/89010922

事务简介

并发

优势:容易理解
劣势:性能较低
容易理解的模型性能都不好,性能好的模型都不容易理解。

一个事务单元

例子: Bob只有100块要全部给Smith(0元)
分析:线程①操作Bob的账号时,会加锁,当有其他线程②③要操作时只能等待,保持数据的 一致性
如果没有加锁,当①从Bob账号中减少100,而Smith账号要等2ms才能到账,那在这2ms期间如果②去访问Bob账号,发现Bob里面是0元,Smith也是0元,就出现了一致性的问题,是不能接受的。
线程②③要么是看到Bob有100块,要么是看到Smith有100块,这就是数据库的另一特性 持久性
而一个事务要么成功,要么失败,不会存在Bob减少了100块,而Smith收不到这100块的情况,这也是数据库的另一特性 原子性
在这里插入图片描述
哪些地方用到了事务?

  • 写数据、读数据、建立索引、删除表,每个操作都是一个事务。

一组事务单元

例如:① 事务1:Bob给Smith100块,②事务2:Smith给Joe100块
分析:事务2会等待事务1完成后才会开启。
在这里插入图片描述

事务单元之间的Happen-Before关系

读写 写读 读读 写写

如何已最快的速度完成事务?又能保证上面四种操作的逻辑顺序?

方式1: 排队法

在这里插入图片描述
优势:不会冲突、不会死锁
劣势:性能低

方式2: 排他锁

将一个事务拆分成多个事务,给每个事务加锁,前提是两个事务不能操作同一数据
例如Bob给Smith100, Alice给Joe100块。
反例:Bob给Smith100, Smith给Joe100块。
在这里插入图片描述

方式3: 读写锁

在这里插入图片描述
只给写加锁,读不加锁(隔离性破坏了一致性
优势:性能提高
劣势:多次读取的数据可能不一致

方式4: MVCC

写的时候会有一个log记录下当前位置,读的时候会检查是不是跟当前写的匹配,当前写的不匹配,会往前查找,直到查到为止。
本质就是copy on write, 能够做到写不阻塞读(写的时候可以并发的读)
(目前主流数据库采用的是这种的方式)
在这里插入图片描述
优势:性能很高。
代价:系统的复杂度变高

事务常见的问题

  1. 谁先谁后?
    一个读请求应该读哪个写之后的数据呢?
    逻辑时间戳 SCN(Oracle) Trx_id(Innodb) …

  2. 故障恢复
    ① 业务数据不匹配
    如:转账中账户余额不足,就需要回滚,执行业务的反向操作。
    ② 系统崩溃
    在这里插入图片描述
    如:给Smith账户增加100时,服务器crash了,重启服务器后会有一个recovery的过程,处于这个过程中的时候其他应用是无法访问的。

  3. 死锁与死锁检测
    产生死锁的原因: 1.两个线程 2.不同方向 3.相同资源
    在这里插入图片描述
    单机事务解决方案:
    ① 尽可能不死锁
    碰撞检测
    把事务单元和事务单元的锁记录下来,当新申请的锁进来的时候检测有没有已经申请过锁,如果锁已经申请,并没有释放,那么会释放一边的锁。
    ③ 等锁超时

    扫描二维码关注公众号,回复: 6209867 查看本文章

分布式解决方案:

事务的ACID

原子性:Undo日志回滚到之前的版本

一致性:Can(Happen-Before):所有操作完成之后才会可见,否则不可见。
强一致性:加锁,将多个事务顺序执行,并发不高。
在这里插入图片描述
隔离性:

  • 以性能为理由,破坏一致性
  • 排它锁: 序列化读写(Serializable)
  • 读写锁:
    • 可重复读,读锁不能被写锁升级
    • 读已提交(read commited)读锁能被写锁升级
  • mvcc: 快照读的情况下能保证在读到一致性的同时实现读为提交
    持久性:提交完成后数据就会放入磁盘或网络中的磁盘中。
    • RAID的持久性

写写有没有可能并行呢?

猜你喜欢

转载自blog.csdn.net/qq_35974759/article/details/89010922