💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 事务 > 官网:https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-model.html * **InnoDB 引擎**才支持事务 * 事务处理可以用来维护数据库的完整性,保证成批的 SQL语句**要么全部执行,要么全部不执行** * 事务需要满足4个条件(**ACID**):**原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)** * MySQL 默认自动提交事务 ## **ACID** 事务正确执行的四要素: * **原子性(Atomicity)**: 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。 * **一致性(Consistency)**: 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。 * **隔离性(Isolation)**: 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。 事务隔离分为不同级别,包括**读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)**。 * **持久性(Durability)**:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 ## **事务的隔离级别** ### **读未提交(Read uncommitted)** 所有事务都可以看到没有提交事务的数据。会造成**脏读**问题。 ### **读已提交(Read committed)** 事务成功提交后才可以查询到。 ### **可重复读(Repeatable read)** InnoDB **默认的**隔离级别 同一事务中的**一致性读取**读取第一次读取建立的[快照](https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_snapshot),这意味着,如果在同一个事务中发出几个普通的(非锁定的)`SELECT`语句,这些`SELECT`语句之间也是一致的。 对于锁定读取(`SELECT with FOR UPDATE` or `FOR SHARE`)、`UPDATE`、`DELETE`语句,锁定取决于语句是使用具有唯一搜索条件的唯一索引还是范围类型的搜索条件。 * 对于具有唯一搜索条件的唯一索引,InnoDB 只锁定下找到的索引记录,而不锁定它之前的间隙。 * 对于其他搜索条件,InnoDB 锁定扫描的索引范围,使用**间隙锁**或**下一个键锁**来阻止其他会话插入该范围所覆盖的间隙。 ### **串行化(Serializable)** 强制的进行排序,在每个读读数据行上添加**共享锁**。会导致大量超时现象和锁竞争 ## **事务隔离产生的影响** - **脏读**:一个事务读取到了另一个事务修改后还没有提交的数据。 - **不可重复读**:一个事务多次读取同一数据时,有另外的事务进行修改提交,导致 **多次读取同一数据结果不一致**。 - **幻读**:一个事务中,多次 `SELECT` 查询到不同的行,即在一次事务中,执行两次 `SELECT` ,但第二次返回了第一次没有返回的行。 > 为防止出现幻读,InnoDB 中使用了一种称为下一个键锁定的算法,它结合了索引行锁和间隙锁。 ## 一致非锁定读 一致性读取意味着 InnoDB 使用多版本向查询提供数据库在某个时间点的快照。查询会看到在该时间点之前提交的事务所做的更改,以及稍后或未提交的事务所做的更改。此规则的例外是查询会看到同一事务中先前语句所做的更改。 此异常会导致以下异常:如果更新表中的某些行,则 `SELECT`看到更新行的最新版本,但它也可能看到任何行的旧版本。如果其他会话同时更新同一个表,则异常意味着您可能会看到该表处于数据库中从未存在过的状态。 如果事务隔离级别为 **REPEATABLE READ**(默认级别),则同一事务中的所有一致性读取都会读取该事务中第一次此类读取所建立的快照。您可以通过提交当前事务并在此之后发出新查询来获得查询的更新快照。 使用**READ COMMITTED**隔离级别,事务中的每个一致读取都会设置并读取自己的新快照。 一致读取是 InnoDB处理 `SELECT`语句 **READ COMMITTED**和 **REPEATABLE READ**隔离级别的默认模式。一致读取不会对其访问的表设置任何锁定,因此其他会话可以在对表执行一致读取的同时自由修改这些表。 假设您在默认 **REPEATABLE READ**隔离级别下运行。当您发出一致读取(即普通 `SELECT`语句)时, InnoDB 为您的事务提供一个时间点,根据该时间点您的查询看到数据库。如果另一个事务在分配您的时间点后删除了一行并提交,您不会看到该行已被删除。插入和更新的处理方式类似。 > 详细:https://dev.mysql.com/doc/refman/5.6/en/innodb-consistent-read.html