数据库事务详解:ACID四性、隔离级别、日志、事务控制语句

目录

    • 事务的特性
    • 事务的隔离级别
    • 事务日志
    • 事务控制语句

数据库中的事务用来管理增、删、改操作,查询不需要事务管理,因为它并不会修改数据库中的数据。

在 MySQL 中只有使用了InnoDB 数据库引擎 的数据库或表才支持事务。

事务的特性

事务具有ACID四性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

  • 原子性

    事务是作为一个整体来执行的,某个事务中的全部操作要么全部成功,要么全部失败。 若事务失败,则数据库状态回滚到事务执行之前。

  • 一致性

    事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如在银行中两个账户转账前后的储蓄总和不变,这就是从转账前的一致性状态转变为了转账后的一致性状态。保证事务的一致性,就是保证数据库的完整性约束没有被破坏。

  • 隔离性

    数据库中不同事务可以并发执行,但它们各自之间是互不影响的,事务a不会被事务b的操作数据干扰。

  • 持久性

    持久性是指一个事务一旦被提交(commit),它对数据库中数据的改变就是永久性的。

对于事务的原子性,只要将事务作为一个整体去执行就可以了,一荣俱荣,一损俱损;

对于事物的一致性,需要设置数据库的完整性约束,保证数据要服从此约束;

对于事务的持久性,若服务器宕机,此时事务的数据还未进行持久化,会有什么影响呢?已提交的事务,肯定已经持久化到磁盘中,还未提交的事务,相应的数据会回滚。这是为什么,继续往下看到事务日志就明白了。

以上这四种性质,原子性、一致性、持久性都比较容易实现,比较复杂的是事务的隔离性。

事务的隔离级别

为了实现事务的隔离性,InnoDB数据库引擎中提供了4中事务隔离级别:

  • ISOLATION_READ_UNCOMMITTED 读未提交

    读未提交是最低级别的隔离。

    事务A修改了数据D,并且还未提交,当事务B再次查询数据D时,查询到的是事务A修改后的数据D。

  • ISOLATION_READ_COMMITTED 读已提交

    事务A修改了数据D,并且已经提交,当事务B再次查询数据D时,查询到的是事务A修改后的数据D。若事务A未提交,则事务B查询到的数据只能是修改前的数据D。

  • ISOLATION_REPEATABLE_READ 可重复读

    事务A修改了数据D,并且已经提交,当事务B再次查询数据D时,查询到的是事务A修改前的数据D。意思就是事务A对于数据D的修改,在事务B未提交时是不可见的,只有当事务B提交后才能看到其它事务提交的修改。

  • ISOLATION_SERIALIZABLE 串行化

    串行化是最高级别的隔离。事务依次执行,不会产生冲突。

若不适当考虑事务的隔离级别, 在数据库中可能会引发下列问题:

  • 脏读

    一个事务读取了另一个事务修改且未提交的数据。

  • 不可重复读

    一个事务不会读取到另一个事务修改且未提交的数据。

    也就是一个事务可以读取另一个事务修改且已提交的数据。

  • 幻读

    事务A在数据库中插入了一条记录,导致事务B执行期间前后查询到的总记录条数不一致。就像出现了幻觉。

画个表:

脏读 不可重复读 幻读
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED ×
ISOLATION_REPEATABLE_READ × ×
ISOLATION_SERIALIZABLE × × ×

不可重复读:可以理解为有一个数据D,事务执行期间重复读取它,并不能保证每次读取的值都一样。

事务日志

数据库管理系统采用事务日志来保证事务的原子性、一致性和持久性。

如果每次更新都将数据持久化到磁盘,由于数据是随机的,会造成大量的随机IO,性能会非常差;但是如果每次更新不马上写盘,那一旦数据库崩溃,数据就会丢失。为了提高事务中更新操作的效率,MySQL中的大多数存储引擎都实现了事务日志

使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改数据本身持久到磁盘

事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头,所有采用事务日志的方式相对来说要快得多。

事务日志持久化以后,内存中被修改的数据在后台可以慢慢地刷回到磁盘。目前大多数存储引擎都是这样实现的,我们通常称之为预写式日志 (Write-Ahead Logging),因此修改数据需要写两次磁盘。

如果数据的修改已经记录到事务日志并持久化,但数据本身没有写回磁盘,此时系统崩溃,存储引擎在重启时能够自动恢复这部分修改的数据。具体的恢复方式则视存储引擎而定。

事务控制语句

  • BEGIN 或 START TRANSACTION 显式地开启一个事务;
  • COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
  • ROLLBACK 回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
  • SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
  • RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
  • ROLLBACK TO identifier 把事务回滚到标记点;
  • SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
  • SET AUTOCOMMIT=0 禁止自动提交
    SET AUTOCOMMIT=1 开启自动提交

参考

https://www.runoob.com/mysql/mysql-transaction.html

https://blog.csdn.net/ncepu_Chen/article/details/94857481

https://zhuanlan.zhihu.com/p/43493165 深入理解数据库事务

https://blog.csdn.net/yinni11/article/details/81510035 事务日志

你可能感兴趣的:(数据库,数据库,mysql,sql,acid)