事务的ACID

来源:互联网 发布:seo软件利搜 编辑:程序博客网 时间:2024/06/10 04:35

这是对沈询大神讲解的事务 的笔记。

课程链接

事务简介

事务的本质是并发

ACID保证事务的完整性

事务也称为单个事务单元。    例如         转账:A-->B 100元A账户减少100,B账户增加100。        在此操作过程中必须要保证完整,一致。这就是一个事务单元。    除了转账的问题还有一些也是事务单元:        * 建立索引        * 从数据库中读取一条数据        * 向数据库中写入一条数据,同时更新这行记录的所有索引        * 删除 整张表一组事务单元 :    多个事务单元之间的happen-before关系:        * 读写        * 写读        * 读读        * 写写

如何对一组事务单元的关系进行排序是很重要的

  1. 序列化读写1
  2. 排它锁[^2]
  3. 读写锁[^3]
  4. MVCC

MVCC: copy on write针对写读场景的优化。 在写的时候,依旧可以进行并发读。
它可以做到 读读不冲突,读写不冲突,写读不冲突。
本质是每一次数据写入都放入一个log里面

隔离性是对一致性的一种破坏

处理事务的常见思路

事务处理的常见问题

  • 多个事务单元,谁先谁后?
  • 如何进行故障恢复?
  • 碰到死锁如何处理?

    1. 在orcle中是SCN(逻辑时间戳) 在inno_db中是Trx_id
    2. 业务属性不匹配,记录每一步操作的反向操作。 如果数据库崩溃,那么重启后在进行数据恢复的时候,在整个回滚过程中,这个系统是无法被外界访问的。
    3. 死锁与死锁检测: 死锁产生原因: 两个线程,不同方向加锁,相同的资源

死锁检测

碰撞检测 等锁超时 降低隔离级别

深入单机事务

事务的ACID

  • 原子性
  • 一致性
  • 隔离性
    • 序列化读
    • 可重复读 (读加锁,只能做到读)
    • 读已提交 (读锁可以被写锁升级。 可以读写 但是不可以 写读)
    • 读未提交 (可能会读到中间状态的值,比如转账过程中,两个人钱都为0)
  • 持久性

原子性

一个事务要么同时成功,要么同时失败。原子性只保证了记录了一个回滚段,在事务失败的时候,可以回滚到上一个操作的状态。

一致性

多个事务之间的 happen-before关系将所有的请求,排队。最终要的部分就是如何处理不同事务之间的读写并行

隔离性

以性能为理由对一致性的破坏除了sql92的 四个隔离级别之外 又有了一个新的隔离级别, 快照隔离级别。mvcc  无锁编程  快照读可以保证在读到一致性的同时实现读未提交。 当读大于写的时候会增加系统的成本。  适合读写比率比较高的情况。

持久性

事务完成之后,该事务对数据库所做的所有更改便持久的保存在数据库中。将请求打包后提交* 直接写入内存  优点:IOPS很高  缺点: 很可能丢失数据* GroupCommit   有点:保证系统的持久性和吞吐量 缺点: 请求的延迟高

事务的调优原则

  • 在不影响业务的情况下,尽可能减少锁的覆盖范围
  • 在不影响业务的情况下,增加锁上可以并行的线程数
    • 读锁,写锁分离。
    • 允许并行读取数据。
  • 在不影响业务的情况下,选择正确的锁类型

悲观锁 使线程到blocking状态 适合并发争抢比较严重的场景

乐观锁 适合并发争抢不太严重的场景

事务个各个不同隔离级别可能会带来的问题

脏读

在一个事务正在访问数据,并对数据进行了修改,这种数据还没提交到数据库,被另一个事务所读到这个数据。这个应该是 读未提交引发的,即写读可并行。

幻读

目前工资为1000的员工有10人。事务1,读取所有工资为1000的员工。这时事务2向employee表插入了一条员工记录,工资也为1000事务1再次读取所有工资为1000的员工 共读取到了11条记录, 解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据     ,则可避免该问题这个从应该是 读写 可并行引起的。

不可重复读

不可重复读的重点是修改 : 同样的条件, 你读取过的数据,再次读取出来发现值不一样了幻读的重点在于新增或者删除 : 同样的条件, 第 1 次和第 2 次读出来的记录数不一样

  1. 该方式的优势是 不需要冲突控制劣势是慢速设备
    [^2]: 两个事务单元之间完全没有冲突则进行并行
    [^3]: 写读之间完全分开,让读读并行 ↩
0 0