MySQL——事务(Transaction)详解

本文围绕MySQL事务展开,介绍了事务定义,即最小不可再分工作单元,与DML语句相关。阐述了事务四大特征ACID,包括原子性、一致性、隔离性和持久性。还说明了事务开启和结束标志,分析了并发问题,如脏读、不可重复读和幻读,并通过实例讲解了隔离性的不同级别及传播机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、事务定义

  • Transaction
  • 事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)
  • 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成(DML:数据操纵语言,SQL语言中,负责对数据库对象运行数据访问工作的指令集,以INSERT、UPDATE、DELETE三种指令为核心)
  • 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。

二、事务四大特征(ACID)

  • 原子性(A):事务是最小单位,不可再分,事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。
  • 一致性(C):事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败
  • 隔离性(I):事务A和事务B之间具有隔离性,同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
  • 持久性(D):是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中),事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

三、事务开启的标志?事务结束的标志?

  • 开启标志:任何一条DML语句(insert、update、delete)执行,标志事务的开启
  • 结束标志(提交或者回滚):
    • 提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步
    •  回滚:失败的结束,将所有的DML语句操作历史记录全部清空

 

四、事务的并发问题

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

 

五、事务四大特性之一————隔离性(isolation)

事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)  MySQL默认事务隔离级别
串行化(serializable)

例子说明:

1. 读未提交:

   将A的隔离级别设置为read uncommitted(读未提交)

  • A:启动事务,此时数据为初始状态
  • B:启动事务,更新数据,但不提交
  • A:再次读取数据,发现数据已经被修改了,这就是所谓的“脏读”
  • B:回滚事务
  • A:再次读取数据,发现数据变回初始状态

经过上面的实验可以得出结论,事务B更新了一条记录,但是没有提交,此时事务A可以查询出未提交记录。造成脏读现象。未提交读是最低的隔离级别。

2. 不可重复读:

   将客户端A的事务隔离级别设置为read committed(已提交读)

  • A:启动事务,此时数据为初始状态
  • B:启动事务,更新数据,但不提交
  • A:再次读数据,发现数据未被修改
  • B:提交事务
  • A:再次读取数据,发现数据已发生变化,说明B提交的修改被事务中的A读到了,这就是所谓的“不可重复读”

经过上面的实验可以得出结论,已提交读隔离级别解决了脏读的问题,但是出现了不可重复读的问题,即事务A在两次查询的数据不一致,因为在两次查询之间事务B更新了一条数据。已提交读只允许读取已提交的记录,但不要求可重复读。

3. 可重复读:

    将A的隔离级别设置为repeatable read(可重复读)

  • A:启动事务,此时数据为初始状态
  • B:启动事务,更新数据,但不提交
  • A:再次读取数据,发现数据未被修改
  • B:提交事务
  • A:再次读取数据,发现数据依然未发生变化,这说明这次可以重复读了
  • B:插入一条新的数据,并提交
  • A:再次读取数据,发现数据依然未发生变化,虽然可以重复读了,但是却发现读的不是最新数据,这就是所谓的“幻读”
  • A:提交本次事务,再次读取数据,发现读取正常了

由以上的实验可以得出结论,可重复读隔离级别只允许读取已提交记录,而且在一个事务两次读取一个记录期间,其他事务部的更新该记录。但该事务不要求与其他事务可串行化。例如,当一个事务可以找到由一个已提交事务更新的记录,但是可能产生幻读问题(注意是可能,因为数据库对隔离级别的实现有所差别)。像以上的实验,就没有出现数据幻读的问题。

4.串行化 :

    将A的隔离级别设置为可串行化(Serializable)

  • A:启动事务,此时数据为初始状态
  • 发现B此时进入了等待状态,原因是因为A的事务尚未提交,只能等待(此时,B可能会发生等待超时)
  • A:提交事务
  • B:发现插入成功

serializable完全锁定字段,若一个事务来查询同一份数据就必须等待,直到前一个事务完成并解除锁定为止。是完整的隔离级别,会锁定对应的数据表格,因而会有效率的问题。

六、传播机制

/**
 * Support a current transaction, create a new one if none exists.
 * Analogous to EJB transaction attribute of the same name.
 * <p>This is the default setting of a transaction annotation.
 */
1. REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

/**
 * Support a current transaction, execute non-transactionally if none exists.
 * Analogous to EJB transaction attribute of the same name.
 * <p>Note: For transaction managers with transaction synchronization,
 * {@code SUPPORTS} is slightly different from no transaction at all,
 * as it defines a transaction scope that synchronization will apply for.
 * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
 * will be shared for the entire specified scope. Note that this depends on
 * the actual synchronization configuration of the transaction manager.
 * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
 */
2. SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

/**
 * Support a current transaction, throw an exception if none exists.
 * Analogous to EJB transaction attribute of the same name.
 */
3. MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

/**
 * Create a new transaction, and suspend the current transaction if one exists.
 * Analogous to the EJB transaction attribute of the same name.
 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
 * on all transaction managers. This in particular applies to
 * {@link org.springframework.transaction.jta.JtaTransactionManager},
 * which requires the {@code javax.transaction.TransactionManager} to be
 * made available to it (which is server-specific in standard Java EE).
 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
 */
4. REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

/**
 * Execute non-transactionally, suspend the current transaction if one exists.
 * Analogous to EJB transaction attribute of the same name.
 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
 * on all transaction managers. This in particular applies to
 * {@link org.springframework.transaction.jta.JtaTransactionManager},
 * which requires the {@code javax.transaction.TransactionManager} to be
 * made available to it (which is server-specific in standard Java EE).
 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
 */
5. NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

/**
 * Execute non-transactionally, throw an exception if a transaction exists.
 * Analogous to EJB transaction attribute of the same name.
 */
6. NEVER(TransactionDefinition.PROPAGATION_NEVER),

/**
 * Execute within a nested transaction if a current transaction exists,
 * behave like {@code REQUIRED} otherwise. There is no analogous feature in EJB.
 * <p>Note: Actual creation of a nested transaction will only work on specific
 * transaction managers. Out of the box, this only applies to the JDBC
 * DataSourceTransactionManager. Some JTA providers might support nested
 * transactions as well.
 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
 */
7. NESTED(TransactionDefinition.PROPAGATION_NESTED);
常用的传播机制:
REQUIRED: 支持当前事务(外部事务),如果不存在则创建新事务.
REQUIRES_NEW: 创建一个新事务,并且暂停当前事务(外部事务).
NESTED: 如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就会REQUIRED一样.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值