Mysql事务

数据库事务是指一组数据库操作,它们作为一个逻辑单元一起执行,要么全部执行,要么全部不执行。在数据库中,事务通常用于执行一系列的数据库操作,比如插入、更新或删除多条记录等。

事务特性

事务具有以下四个特性,通常称为 ACID 特性:

  1. 原子性(Atomicity):事务中的所有操作都要么全部执行,要么全部不执行,不允许出现部分执行的情况。
  2. 一致性(Consistency):事务执行前和执行后,数据库的完整性约束没有被破坏。
  3. 隔离性(Isolation):多个事务并发执行时,每个事务都应该感觉不到其他事务的存在,各个事务之间应该相互隔离。
  4. 持久性(Durability):事务一旦提交成功,其结果就应该永久保存在数据库中,即使出现系统故障也不应该丢失。

脏读

脏读(Dirty Read)是指在一个事务中读取了另一个事务尚未提交的数据。在脏读的情况下,读取到的数据可能是不准确的,因为这些数据可能会被另一个事务撤销或修改。

例如,假设有两个事务 A 和 B,事务 A 在读取了一条数据之后,事务 B 修改了该数据,但是尚未提交。如果此时事务 A 再次读取该数据,那么就会读取到事务 B 修改后的数据,而这个数据可能是不准确的。

不可重复读

在数据库事务中,不可重复读是指在同一个事务中,多次读取同一个数据时得到的结果可能不同。这通常是由于在事务执行期间,另一个并发的事务修改了同一个数据所导致的。

以下是一个示例,说明不可重复读的情况:

  1. 事务T1读取数据X,获得结果A。
  2. 在T1读取数据X之后,事务T2修改了数据X,将其更改为B。
  3. 事务T1再次读取数据X,此时获得结果B,与第一次读取时的结果不同。

幻读

在数据库事务中,幻读是指在同一个事务中多次读取同一个范围内的记录时,得到的结果可能不同。这通常是由于在事务执行期间,另一个并发的事务插入或删除了一些记录所导致的。

以下是一个示例,说明幻读的情况:

  1. 事务T1读取数据集X,获得结果A。
  2. 在T1读取数据集X之后,事务T2在数据集X中插入了一条新的记录,这条记录不在T1的结果集中。
  3. 事务T1再次读取数据集X,此时获得结果B,其中包含了T2插入的新记录。

在这个示例中,T1的两次读取之间的差异就是幻读的结果。

事务隔离级别

数据库事务隔离级别是指多个事务之间相互隔离的程度,可以通过设置隔离级别来控制事务之间的并发性和数据一致性。常见的隔离级别有四个,分别是:

  1. 读未提交(Read Uncommitted):在这个隔离级别下,一个事务可以读取另一个事务尚未提交的数据,会出现脏读、不可重复读和幻读的问题。
  2. 读已提交(Read Committed):在这个隔离级别下,一个事务只能读取另一个事务已经提交的数据,可以避免脏读的问题,但是仍然会出现不可重复读和幻读的问题。
  3. 可重复读(Repeatable Read):在这个隔离级别下,一个事务在执行期间多次读取同一条记录的数据时,会保证每次读取的数据都相同,可以避免脏读和不可重复读的问题,但是仍然会出现幻读的问题。
  4. 串行化(Serializable):在这个隔离级别下,所有的事务都是串行执行的,每个事务必须等待前一个事务执行完成后才能执行,可以避免脏读、不可重复读和幻读的问题,但是会降低系统的并发性能。

log

redo log

在 MySQL 中,redo log 是一种用于崩溃恢复和事务持久化的机制。redo log 记录了所有的修改操作,即事务对数据库中数据所做的所有修改。当 MySQL 在崩溃后重新启动时,它可以使用 redo log 来恢复最后一次崩溃之前提交的事务。

redo log 是基于磁盘的日志,它是循环写入的,当所有的 redo log 被写满之后,MySQL 将从 redo log 的开头重新开始写入。redo log 存储在磁盘上,因此它不会消耗过多的内存。

redo log 的工作原理是:当一个事务开始时,所有的修改操作都被记录到 redo log 中,但实际的数据修改操作不会立即被执行。相反,它们会被暂时保存在内存中,等到事务提交时,MySQL 才会将其写入磁盘。这样做的目的是为了减少磁盘写入的次数,提高系统的性能。

当 MySQL 发生崩溃或非正常关闭时,redo log 就发挥了重要的作用。MySQL 在重新启动时,会检查 redo log 中尚未提交的事务,然后将其重新执行,以保证数据库状态的一致性。

undo log

在 MySQL 中,undo log 是用于事务回滚和 MVCC(多版本并发控制)实现的机制。当一个事务开始时,MySQL 会创建一个 undo log 来记录该事务所做的修改操作。当事务被回滚时,MySQL 就会使用 undo log 将数据恢复到事务开始之前的状态。

与 redo log 不同的是,undo log 记录的是原始数据的“旧值”,而不是新的修改值。因此,在事务回滚时,MySQL 可以使用 undo log 将数据恢复到事务开始之前的状态。此外,undo log 还可以用于支持 MVCC 实现,MVCC 允许多个事务同时读取同一个数据项,而不会互相干扰。

undo log 存储在磁盘上,但它们通常存储在内存中的临时缓冲区中。当事务提交时,MySQL 会将其对应的 undo log 从内存中写入磁盘中的 undo log 文件中。如果一个事务还没有提交,那么它的 undo log 就不会被写入磁盘,这样可以避免写入磁盘的开销。

bin log

在 MySQL 中,bin log 是用于数据备份、恢复以及复制的机制。bin log 记录了 MySQL 中所有修改数据的操作,包括对数据的插入、更新和删除等操作。

bin log 存储在磁盘上,可以用来恢复数据或复制数据到其他 MySQL 实例。因此,bin log 可以用于数据备份和恢复,也可以用于主从复制,将一个 MySQL 实例的数据复制到其他 MySQL 实例。

bin log 的工作原理是:当一个事务开始时,MySQL 会将所有的修改操作记录到 bin log 中。当事务提交时,MySQL 将事务的提交信息一并记录到 bin log 中。因此,bin log 中不仅包含数据的修改操作,还包含了事务提交的时间、事务 ID 等信息。

bin log 有多种格式,包括 statement、row 和 mixed 等格式。其中,statement 格式记录的是 SQL 语句,row 格式记录的是行级别的变化,mixed 格式是两者的结合。

事务中日志执行流程

  1. 记录undo log,将修改前的数据记录到undoLog中,以便在事务回滚时恢复原来的数据。

  2. 执行事务中的SQL语句,这些语句会修改数据库中的数据。

  3. 记录redo log,将修改后的数据写入到磁盘上的数据文件中,保证事务的持久性。

  4. 记录bin log,将执行的SQL语句记录在二进制日志中,以便用于主从同步和数据恢复等。


Mysql事务
https://cason.work/2023/04/17/Mysql事务/
作者
Cason Mo
发布于
2023年4月17日
许可协议