雪白丰腴做美妇网站,网站源码 和网站模板区别,免费建网站 手机网站,舟山企业网站建设MySQL事务详解 数据库事务概述事务是如何实现的事务的ACID特性事务的状态 事务的使用显式事务隐式事务示例自动提交回滚回滚到保存点 事务的隔离级别数据并发问题MySQL 支持的四种隔离级别注意示例 设置隔离级别 事务的常见分类 数据库事务概述
数据库事务是数据库管理系统DBMS中的一个关键概念它涉及到一系列数据库操作这些操作要么全部执行成功要么全部不执行以保持数据库的一致性。事务是确保数据库数据完整性和可靠性的基础。
事务是如何实现的
事务就是一组逻辑操作的集合。实现事务就是要保证可靠性和并发隔离或者说能够满足ACID特性的机制。而这些主要是靠日志恢复和并发控制实现的。
日志恢复数据库里有两个日志一个是redo log一个是undo log。redo log记录的是已经成功提交的事务操作信息用来恢复数据保证事务的持久性。undo log记录的是事务修改之前的数据信息用来回滚数据保证事务的原子性。并发控制并发控制主要靠锁机制和MVCC多版本并发控制来实现保证事务的隔离性。一致性则是通过持久性原子性隔离性来保证。
事务的ACID特性 原子性Atomicity原子性是指事务是一个不可分割的工作单位要么全部提交要么全部失败回滚没有中间状态。 一致性Consistency 事务开始前和结束后数据库从一个合法的状态转移到另一个合法的状态即便在事务执行的过程中发生了错误或异常也要保证数据库的完整性和业务规则没有被破坏。 隔离性Isolation 多个事务并发执行时每个事务的操作应该与其他事务隔离不互相影响。 持久性Durability 一旦事务提交对数据库的修改应该是永久的即使发生系统故障也不会丢失。
事务的状态
活动Active 事务进入活动状态表示它已经开始但尚未完成。这是事务的起始状态。部分提交Partially Committed 事务执行了所有的SQL语句但尚未提交。在这个状态下事务对数据库所做的修改已被写入事务日志但尚未应用到数据库中。已提交Committed 事务已经成功完成并已提交。在这个状态下事务对数据库所做的修改已经永久保存在数据库中成为数据库的一部分。失败Failed 事务执行过程中发生了一个错误导致事务无法继续执行。在这个状态下通常会选择回滚事务将数据库恢复到事务开始前的状态。中止Aborted 事务被中止可能是由于发生错误导致的回滚也可能是由于应用程序显式地中止了事务。挂起Suspended 事务处于一个暂时的挂起状态等待某些条件满足后再继续执行。这通常与事务隔离级别相关例如在并发控制中等待其他事务释放锁。
这些状态反映了事务在其生命周期内可能经历的不同阶段。MySQL通过事务日志transaction log和锁来跟踪和管理事务的状态以确保事务的ACID属性得到维护。了解事务的不同状态是非常重要的以便在处理错误、调优性能或者确保数据一致性时能够采取适当的操作。
事务的使用
事务的完成过程
开启事务一系列 DML 操作结束事务
使用事务有两种方式分别为 显式事务 和 隐式事务 。
显式事务Explicit Transaction
手动启动 明确地使用 START TRANSACTION 或者 BEGIN 语句来显式地启动一个事务。这表示从这一点开始所有的数据库操作将作为一个事务进行处理。手动提交或回滚 在事务执行结束后需要明确地使用 COMMIT 提交事务或者使用 ROLLBACK 回滚事务。这使得开发者有更精确的控制可以根据业务逻辑决定是否提交或回滚事务。
隐式事务Implicit Transaction
自动启动 在默认情况下每个SQL语句都被视为一个事务。这意味着在执行SQL语句时会自动启动一个事务。自动提交 在隐式事务中每个SQL语句执行后都会自动提交事务除非显式地使用 SET AUTOCOMMIT0 关闭自动提交这时需要使用 COMMIT 或 ROLLBACK 手动处理事务。
显式事务
1.开启事务
使用START TRANSACTION 或者 BEGIN 开启一个事务。
START TRANSACTION;
BEGIN;START TRANSACTION 语句相较于 BEGIN 特别之处在于后边能跟随几个 修饰符 READ ONLY 标识当前事务是一个 只读事务 也就是属于该事务的数据库操作只能读取数据而不 能修改数据。 READ WRITE 标识当前事务是一个 读写事务 也就是属于该事务的数据库操作既可以读取数据 也可以修改数据。 WITH CONSISTENT SNAPSHOT 启动一致性读。
2.一系列事务中的操作
主要是DML增删改查不含DDL。
3.提交事务或者中止事务
# 提交事务。当提交事务后对数据库的修改是永久性的。
COMMIT;
# 回滚事务。即撤销正在进行的所有没有提交的修改
ROLLBACK;
# 将事务回滚到某个保存点。
ROLLBACK TO [SAVEPOINT]保存点
# 创建保存点
SAVEPOINT 保存点名称;
# 删除保存点
RELEASE SAVEPOINT 保存点名称;隐式事务
MySQL中有一个系统变量 autocommit 默认是ON也就是开启自动事务。 关闭自动提交
显式的的使用 START TRANSACTION 或者 BEGIN 语句开启一个事务。这样在本次事务提交或者回 滚前会暂时关闭掉自动提交的功能。把系统变量autocommit的值设置为 OFF 就像这样
SET autocommit OFF;
#或
SET autocommit 0;示例
自动提交
MySQL 默认开启自动提交每条语句都是一个事务。 关闭自动提交后可以多条语句为一个事务。 回滚
开启事务插入一条新数据。 回滚回滚后数据回到开启事务前的状态。 回滚到保存点
开启事务插入数据设置保存点 回滚到保存点 需要注意的是回滚到保存点并不是事务的终止状态所以不会提交事务 事务的隔离级别
数据并发问题
脏读指一个事务读取到了另一个事务修改但是还没有提交的数据如果另一个事务后来回滚了读取到的数据就是无效的导致事务读取到的数据是“脏”的因为它基于未提交的数据。
比如A向B转账100A的账户减少了100而B的账户还没来得及修改此时一个并发的事务访问到了B的账户就是脏读
不可重复读指一个事务多次读取同一条记录但前后读到的数据不一致。因为当前事务在读取记录的间隙中其他事务在此期间修改或删除了数据并进行了提交 这可能导致事务在执行期间看到不一致的数据破坏了事务的一致性。
比如A第一次查询自己的账户有100元此时另一个事务给A的账户增加了100元所以A再次读取他的账户得到了200的结果跟第一次读取的不一样。
不可重复读与脏读的不同之处在于脏读是读取了另一个事务没有提交的脏数据不可重复读是读取了已经提交的数据实际上并不是一个异常现象。
幻读事务在查询特定记录的总数时前后查询的结果不一致。这是由于在事务查询间隙时在此期间插入了新的数据。 这可能导致事务在执行期间看到不一致的数据破坏了事务的一致性。
比如A公司一共有100个人第一次查询总人数得到100条记录此时另一个事务新增了一个人所以下一次查询得到101条记录。 不可重复度和幻读的不同之处在于幻读是多次读取的结果行数不同不可重复度是读取结果的值不同。
MySQL 支持的四种隔离级别
READ UNCOMMITTED 读未提交在该隔离级别所有事务都可以看到其他未提交事务的执行结 果。不能避免脏读、不可重复读、幻读。
READ COMMITTED 读已提交它满足了隔离的简单定义一个事务只能看见已经提交事务所做 的改变。这是大多数数据库系统的默认隔离级别但不是MySQL默认的。可以避免脏读但不可 重复读、幻读问题仍然存在。
REPEATABLE READ 可重复读事务A在读到一条数据之后此时事务B对该数据进行了修改并提 交那么事务A再读该数据读到的还是原来的内容。可以避免脏读、不可重复读但幻读问题仍 然存在。这是MySQL的默认隔离级别。
SERIALIZABLE 可串行化确保事务可以从一个表中读取相同的行。在这个事务持续期间禁止 其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免但性能十分低下。能避 免脏读、不可重复读和幻读。
这四种隔离级别具体是如何实现的呢
对于「读未提交」隔离级别的事务来说因为可以读到未提交事务修改的数据所以直接读取最新的数据就好了对于「串行化」隔离级别的事务来说通过加读写锁的方式来避免并行访问对于「读提交」和「可重复读」隔离级别的事务来说它们是通过 Read View 来实现的它们的区别在于创建 Read View 的时机不同大家可以把 Read View 理解成一个数据快照就像相机拍照那样定格某一时刻的风景。「读提交」隔离级别是在「每个语句执行前」都会重新生成一个 Read View而「可重复读」隔离级别是「启动事务时」生成一个 Read View然后整个事务期间都在用这个 Read View。
注意
MySQL 虽然支持 4 种隔离级别但是与SQL 标准中规定的各级隔离级别允许发生的现象却有些出入。
MySQL 在「可重复读」隔离级别下可以很大程度上避免幻读现象的发生注意是很大程度避免并不是彻底避免所以 MySQL 并不会使用「串行化」隔离级别来避免幻读现象的发生因为使用「串行化」隔离级别会影响性能。
MySQL InnoDB 引擎的可重复读隔离级别默认隔离级根据不同的查询方式分别提出了避免幻读的方案
针对快照读普通 select 语句是通过 MVCC 方式解决了幻读因为可重复读隔离级别下事务执行过程中看到的数据一直跟这个事务启动时看到的数据是一致的即使中途有其他事务插入了一条数据是查询不出来这条数据的所以就很好了避免幻读问题。针对当前读select … for update 等语句是通过 next-key lock记录锁间隙锁方式解决了幻读因为当执行 select … for update 语句的时候会加上 next-key lock如果有其他事务在 next-key lock 锁范围内插入了一条记录那么这个插入语句就会被阻塞无法成功插入所以就很好了避免幻读问题。
示例
其他事务增加数据后当前事务的查询结果并不会改变。 但是虽然当前事务查询不到但是能够修改且修改后就能查询到。 所以MySQL 在「可重复读」隔离级别下可以很大程度上避免幻读现象的发生但不能彻底避免。
设置隔离级别
查看默认隔离级别
SELECT transaction_isolation;设置隔离级别
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔离级别;
#其中隔离级别格式READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION 隔离级别
#其中隔离级别格式READ-UNCOMMITTEDREAD-COMMITTEDREPEATABLE-READSERIALIZABLE
# SET SESSION TRANSACTION_ISOLATION 隔离级别 SET TRANSACTION_ISOLATION 隔离级别关于设置时使用GLOBAL或SESSION的影响默认 SESSION
使用 GLOBAL 关键字在全局范围影响 当前已经存在的会话无效只对执行完该语句之后产生的会话起作用 使用 SESSION 关键字在会话范围影响 对当前会话的所有后续的事务有效如果在事务之间执行则对后续的事务有效该语句可以在已经开启的事务中间执行但不会影响当前正在执行的事务
事务的常见分类
扁平事务Flat Transactions 扁平事务指整个应用中的所有操作都在一个事务内执行。事务在应用的整个执行过程中始终存在直到应用执行完成或者发生错误。 带有保存点的扁平事务Flat Transactions with Savepoints 这是扁平事务的扩展其中引入了保存点Savepoints。保存点允许在事务中创建一个标记使得事务可以回滚到这个标记处而不必回滚整个事务。这在处理部分错误时可以更灵活地回滚事务的一部分。 链事务Chained Transactions 链事务是一种序列化的事务执行方式其中一个事务的提交触发另一个事务的开始。每个事务在前一个事务成功提交后才能开始执行。这样可以确保事务按照定义的顺序执行。 嵌套事务Nested Transactions 嵌套事务是指事务内可以包含另一个事务。在这种情况下内部事务的提交或回滚并不会立即影响外部事务而是在外部事务提交时才会生效。大多数数据库系统不直接支持真正的嵌套事务但是可以通过保存点Savepoints来模拟。 分布式事务Distributed Transactions 分布式事务涉及多个独立的事务性资源管理器如数据库、消息队列等。在分布式系统中确保所有相关资源的事务要么全部提交要么全部回滚是具有挑战性的。分布式事务通常需要协调者coordinator和参与者participants之间的通信和协调以确保一致性和隔离性。