事务的ACID

本文深入解析事务处理的基本概念,如ACID特性,并讨论了不同隔离级别下可能遇到的问题,如脏读、幻读及不可重复读。此外还介绍了事务优化策略,包括锁的选择和使用,以提高数据库系统的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

课程链接

事务简介

事务的本质是并发

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]: 写读之间完全分开,让读读并行
<think>嗯,用户想了解数据库事务ACID特性,我需要详细解释每个特性。首先,ACID是原子性、一致性、隔离性和持久性的缩写,对吧?那我得一个一个来。 原子性,用户可能知道原子操作不可分割,但具体到数据库事务,应该是指事务中的操作要么全部成功,要么全部失败回滚。比如转账的例子,扣钱和加钱必须都成功,否则回滚。这时候需要引用原子性的部分,记得用引用[1]和引用[2],因为它们提到了原子性。 接下来是一致性,这个可能有点抽象。事务执行前后数据库必须保持一致性状态,比如转账前后总金额不变。这需要应用层的逻辑和数据库约束共同保证。引用中好像没有直接提到一致性,不过引用[1]和[2]可能涉及,不过可能用户提供的引用里没有详细说明,需要结合自己的知识解释清楚。 然后是隔离性,多个并发事务之间互不干扰。比如两个事务同时操作同一数据,可能出现脏读、不可重复读等问题。数据库通过隔离级别来控制,比如读未提交、读已提交等。引用[3]详细讲了隔离性,提到了并发控制和隔离级别,所以这里需要重点引用[3]。 最后是持久性,事务提交后对数据的修改是永久性的,即使系统故障也不会丢失。通常通过日志和备份实现。引用[3]最后提到了持久性,可以引用这里。 用户可能还关心这些特性如何实现的,比如原子性通过undo log,持久性通过redo log。需要简单说明实现机制,但用户提供的引用里可能没有,所以根据常识补充。 另外,用户提供的引用中提到了隔离级别和并发控制,所以在隔离性部分要展开讨论不同的隔离级别及其影响。比如读未提交可能导致脏读,而可串行化隔离级别最高但性能差。 要确保回答结构清晰,每个特性单独成段,用例子帮助理解。最后生成相关问题,比如ACID的实现原理,隔离级别的区别,事务管理的方法等。检查是否所有引用都正确标注,比如引用[1]提到原子性,引用[3]讨论隔离性和持久性。 可能还需要注意用户提到的“系统级指令”,比如数学公式要用$...$,但这里主要涉及概念,可能用不上数学表达式。不过如果有涉及公式的地方,比如一致性中的约束方程,可能需要用LaTeX,但用户的问题可能不涉及,所以可能不需要。 最后确保回答用中文,引用标识自然添加在相关句子的末尾。检查是否有遗漏的特性或错误解释,确保每个特性解释准确,并引用正确的来源。</think>### 数据库事务ACID 特性 数据库事务的 **ACID** 特性是保证数据操作可靠性和一致性的核心原则,包含以下四个特性: #### 1. 原子性(Atomicity) 事务中的所有操作要么全部成功执行,要么全部失败回滚,不允许部分完成。例如,转账操作中“扣减A账户余额”和“增加B账户余额”必须同时成功或同时撤销。 **实现机制**:通过日志(如 `undo log`)记录事务操作,失败时反向执行日志恢复数据[^1][^2]。 #### 2. 一致性(Consistency) 事务执行前后,数据库必须从一种一致状态转换到另一种一致状态。例如,转账前后两个账户的总金额应保持不变。 **实现依赖**:需要应用层逻辑(如业务规则)和数据库约束(如唯一索引、外键)共同保障。 #### 3. 隔离性(Isolation) 多个并发事务的执行互不干扰,每个事务感知到的数据状态独立于其他事务。例如,事务A未提交时,事务B无法读取其修改的数据。 **实现方式**:通过 **并发控制技术**(如读写锁、多版本控制)和 **隔离级别**(如读未提交、可重复读)来平衡隔离性与性能[^3]。 **常见问题**: - 脏读(读取未提交的数据) - 不可重复读(同一事务内多次读取结果不同) - 幻读(新增或删除的数据影响查询结果) #### 4. 持久性(Durability) 事务提交后,对数据的修改是永久性的,即使系统故障也不会丢失。例如,转账成功后,数据即使遭遇宕机仍能恢复。 **实现机制**:通过日志(如 `redo log`)和持久化存储(如磁盘备份)保障。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值