如果你觉得这篇文章对你有帮助,请不要吝惜你的“关注”、“点赞”、“评价”、“收藏”,你的支持永远是我前进的动力~~~
一、事务的基本概念
事务是确保数据库操作一致性的重要机制,而根据其涉及的资源和系统结构的不同,可以分为本地事务和分布式事务两种类型。
- 事务:访问并更新数据库中各种数据项的一个程序执行单元。同属于一个事务的一系列操作是不可分割的,要么全部执行成功,要么根本不执行。
- 本地事务:基于单一服务、单一数据库资源访问的事务,被称为本地事务,也称为传统事务。例如LAMP(Linux+Apache+MySQL+PHP)架构中的事务就是本地事务。
- 分布式事务:是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点上。这种情况下,需要保证跨多个节点的操作的一致性和原子性 -- 百度百科。
二、事务的四大特性
事务的四大特性通常被称为ACID,它们分别是:
- 原子性(Atomicity):
- 事务是一个不可分割的工作单位,事务中的操作要么全部执行,要么全部不执行。这意味着事务的操作要么全部成功,要么全部失败,不会处于中间状态。如果事务中的某一部分操作失败,那么事务中的所有操作都会被撤销,数据库状态将回滚到事务开始之前。
- 一致性(Consistency):
- 事务必须使数据库从一个一致性状态转移到另一个一致性状态。在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。例如,在转账事务中,从一个账户转出金额,必须在另一个账户中相应增加金额,保持总金额不变。
- 隔离性(Isolation):
- 并发执行的事务之间不会相互影响。一个事务的执行不会被其他事务干扰。不同的事务并发操作相同的数据时,每个事务都像是在独立的环境中操作,事务的中间状态对外是不可见的,直到事务提交。
- 持久性(Durability):
- 一旦事务提交,它对数据库中数据的改变就是永久的。即使发生系统故障,这些改变也不会丢失。通常,这意味着事务一旦提交,就会被写入到某种持久存储介质中,如磁盘。
这四大特性保证了数据库在执行事务时的可靠性和稳定性,是关系数据库管理系统(RDBMS)中事务处理的基础。
三、事务的隔离级别
事务的隔离级别定义了事务在并发执行时,对其他事务可见的程度。SQL标准定义了以下四种隔离级别,从低到高分别是:
- 读未提交(Read Uncommitted):
- 允许读取尚未提交的数据变更。可能会导致脏读(Dirty Reads),即一个事务可以读取另一个事务中尚未提交的数据。
- 读已提交(Read Committed):
- 仅允许读取已经提交的数据变更。这是大多数数据库系统的默认隔离级别(例如 SQL Server 和 PostgreSQL)。它可以避免脏读,但不可重复读(Non-Repeatable Reads)和幻读(Phantom Reads)仍然可能发生。
- 可重复读(Repeatable Read):
- 确保在事务内可以多次读取同样的数据结果,而不会受到其他事务的影响。MySQL 在默认的存储引擎 InnoDB 中使用的就是这种隔离级别。它可以避免脏读和不可重复读,但幻读仍然可能发生。
- 串行化(Serializable):
- 最高级别的隔离,强制事务串行执行,即事务只能一个接一个地执行,不能并发执行。这可以完全避免脏读、不可重复读和幻读,但会极大地降低系统的并发性能。
四、只读事务
这里需要特别提及“只读事务”,有着其独特的作用。只读事务(Read-Only Transaction)是一种特殊类型的事务,它只允许执行查询操作,不允许执行任何修改数据库状态的操作,如插入、更新或删除。以下是只读事务的一些主要作用:
- 提高性能:
- 由于只读事务不需要考虑数据修改,数据库系统可以优化查询操作,减少锁的竞争和开销,从而提高查询的执行速度。
- 保证数据一致性:
- 只读事务可以确保在事务执行期间看到的数据是一致的,即使其他事务正在修改数据,只读事务也会看到事务开始时数据库的一致性快照。
- 简化数据备份和复制:
- 在进行数据备份或复制操作时,使用只读事务可以确保备份或复制的数据不会因为并发修改而出现不一致。
- 避免副作用:
- 只读事务可以防止执行查询时意外修改数据,这对于维护数据完整性和防止误操作非常有用。
- 提供隔离性:
- 只读事务可以设置不同的隔离级别,以控制对其他事务的可见性,例如,可以设置串行化隔离级别,确保事务完全不受其他事务的影响。
- 优化资源分配:
- 数据库系统可能会为只读事务分配不同的资源,例如,将它们调度到不同的处理队列中,以优化整体资源的使用。
五、并发事务带来的问题
并发事务在数据库管理系统中是常见的,因为它们允许多个操作同时进行,提高了系统的吞吐量和资源利用率。然而,并发事务也可能带来以下问题:
- 更新丢失(Lost Updates):
- 当两个或多个事务同时更新同一数据项时,后一个事务的更新可能会覆盖前一个事务的更新,导致前一个事务的更新丢失。
- 脏读(Dirty Reads):
- 当一个事务读取了另一个未提交事务修改的数据时,如果那个事务最终回滚,那么第一个事务读取的数据就是无效的。
- 不可重复读(Non-Repeatable Reads):
- 在同一个事务中,多次读取同一数据集合时,由于其他事务的修改,导致每次读取的结果不一致。
- 幻读(Phantom Reads):
- 在同一个事务中,第一次查询的结果集与第二次查询的结果集不同,因为其他事务插入了新的行或者删除了已有的行。
- 死锁(Deadlocks):
- 两个或多个事务相互等待对方释放锁,导致所有事务都无法继续执行。
- 饥饿(Starvation):
- 某个事务因为优先级低或其他原因,长时间无法获取所需的资源,导致无法正常执行。
这里重点说明下“不可重复读”和“幻读”的区别。
不可重复读(Non-Repeatable Read)和幻读(Phantom Read)都是数据库事务隔离级别中的问题,它们都涉及到事务在执行期间读取到的数据不一致的情况,但它们关注的点不同。
不可重复读:
- 不可重复读关注的是在一个事务内,多次读取同一行数据时,得到的结果不一致。
- 这种情况通常发生在以下场景:事务A读取了一行数据,然后事务B修改了这行数据并提交,事务A再次读取这行数据时,发现数据已经被修改了。
- 不可重复读的重点在于“同一行”数据的改变。
幻读:
- 幻读关注的是在一个事务内,多次执行范围查询时,得到的结果集不一致。
- 这种情况通常发生在以下场景:事务A执行了一个范围查询,获取了某些行的数据,然后事务B插入了新的行到这个范围,并且提交了。当事务A再次执行同一个范围查询时,它会发现多出了之前没有看到的行。
- 幻读的重点在于“新行”的出现,即事务在查询过程中看到了之前没有看到的行。
简单来说,区别在于:
- 不可重复读是读到了已经存在的数据的改变。
- 幻读是读到了新插入的数据。
六、并发事务问题对应的隔离级别
这个表格展示了MySQL数据库中的事务隔离级别与几种常见并发问题的关系。具体来说,它列出了四种不同的事务隔离级别(读未提交、读已提交、可重复读、可串行化)以及在这些隔离级别下是否可能出现脏读、不可重复读和幻读这三种并发问题的情况。
- 读未提交:在这个隔离级别下,一个事务可以读取另一个未提交事务的数据。因此,可能会出现脏读、不可重复读和幻读。
- 读已提交:在这个隔离级别下,一个事务只能读取已经提交的其他事务的数据。这样可以避免脏读,但仍然可能发生不可重复读和幻读。
- 可重复读:这是InnoDB存储引擎默认的隔离级别。在这个隔离级别下,一个事务在整个执行过程中看到的数据是一致的,即使其他事务在中间进行了更改。这样可以防止脏读和不可重复读,但是仍有可能发生幻读。
- 可串行化:这是最高的事务隔离级别,通过强制事务序列化执行来保证数据的一致性。在这种隔离级别下,所有事务都是顺序执行的,从而避免了所有的并发问题,包括脏读、不可重复读和幻读。
此外,图片下方还提到了一些关于MVCC多版本并发控制的信息:
- 快照读:select操作不会更新版本号。
- 当前读:insert、update、delete会更新版本号,是当前读。
- MVCC机制 + 间隙锁 + 临键锁 可以在一定程度上解决了幻读问题。
这些信息有助于我们更深入地理解MySQL如何处理并发控制和事务隔离。
标签:事务,读取,隔离,幻读,并发,级别,基本概念,分布式 From: https://blog.csdn.net/u013469646/article/details/142968589