【面试系列】谈谈你对数据库ACID的理解

发布于:2025-08-31 ⋅ 阅读:(17) ⋅ 点赞:(0)

扫地僧又偷摸去面试了,这次面试官竟然把它问懵逼了!

面试问题

数据库的ACID是什么?

ACID是DBMS在写入或更新信息时为保证事务正确可靠所必须具备的四个特性。

  • Atomic:原子性,即所有操作要么全部成功,要么全部不成功,不存在部分操作成功,部分操作失败的情况。
  • Consistency:一致性,即事务执行前后数据库必须保持数据的合法性和正确性,比如满足主键约束、唯一性约束等。
  • Isolation:隔离性,即事务间并发执行时互不影响,相互隔离。
  • Durability:持久性,即事务一旦提交成功,则它对数据库的修改就永久保留,宕机重启等异常数据也不会丢失。

上面的问题回答的没问题,但是后面的问题扫地僧回答的一塌糊涂。

可以具体解释下ACID吗?

  • 原子性:事务的所有操作要么全部成功,要么全部失败,不会存在中间态。
    比如A给B转100元时,包含两个操作:A账户扣减100元,B账户增加100元。这两个操作必须要作为一个事务执行,保证A和B的帐户加减要么都成功要么都失败。
    在Mysql中,通过Undo日志来保证原子性:在执行数据修改前,都会将原数据写入到Undo日志中,当事务失败或RollBack时,通过Undo日志进行恢复。

  • 一致性:事务在执行过程中,必须满足预定义的业务规则和约束(如唯一性约束)。因业务实现bug导致数据不正确不属于违反事务的一致性,因为DB只保证事务执行正确,不保证业务正确。
    在Mysql中,一致性是综合结果,由原子性、隔离性、持久性共同保证的,原子性和隔离性保证数据的正确性,持久性保证事务完成后数据不会丢失,其中原子性保证数据不出现中间态,隔离性保证事务执行期间不受其他事务干扰。

  • 隔离性:多个事务并发执行互不影响,相互隔离,隔离本质上也是数据的可见性。当没有隔离时,会存在脏读不可重复读幻读等经典问题。为此,数据库提供了四种隔离级别:

    • 未提交读(Read Uncommitted)不解决任何问题,并发性最高、性能最高。
    • 已提交读(Read Committed)解决了脏读问题。
    • 可重复读(Repeatable Read)解决了脏读和不可重复读问题。
    • 串行读(Serializable)解决脏读、不可重复读和幻读问题,并发性最低,性能最差。
      在Mysql中,通过锁机制实现事务间的隔离性,默认的隔离级别是可重复读(Repeatable Read),但其通过MVCC+Gap锁解决了幻读问题。
  • 持久性:事务一旦提交,它对数据库的修改就永久保留,即使数据库崩了、宕机重启数据也不能丢。
    在Mysql中,通过Redo日志来保证持久性:在事务提交前,会将所有修改写入Redo日志文件中(物理日志),并刷盘,确保写入磁盘成功。当数据库崩溃、宕机重启时,可以通过Redo日志恢复提交成功的事务。

隔离性中多个事务执行互不影响,为什么操作同一个数据的事务会阻塞另一事务?

隔离性就是通过锁机制实现的,这里多个事务执行互不影响是指逻辑上互不影响,不是指物理上互不影响。

ACID和CAP中的C有什么区别?

虽然ACID和CAP中的C都表示一致性,但ACID中的C侧重数据合法性和正确性,而CAP中的C侧重多个数据副本间的一致性。

附录

隔离三个经典问题

  • 脏读(Dirty Read):读取另一个事务未提交的数据
  • 不可重复读(Non-Repeatable Read):一个事务中,前后查询了两次,但两次读到的数据不一样,因为被其他事务修改了。
  • 幻读(Phantom Read):一个事务中,前后查询了两次,但两次读到的数据条目数不一致,因为其他事务插入了新记录。

Mysql Redo日志刷盘时机

Mysql提供innodb_flush_log_at_trx_commit参数控制刷盘机制,取值:

  • 1:每次事务提交都刷盘,最安全,性能最差
  • 0: 每秒刷盘一次
  • 2: 依赖系统异步刷盘,性能最高,最不安全