Mysql 8 事务

Mysql 8 事务

一.Mysql事务介绍

1.事务概述

MySQL中的事务是指一组操作,这些操作要么全部执行成功,要么全部不执行。在MySQL中,事务是由BEGIN、ROLLBACK和COMMIT语句控制的。

2.事务的特性

  1. 原子性:事务中的所有操作要么全部执行成功,要么全部不执行。如果其中一个操作失败,则整个事务都会回滚到事务开始前的状态。
  2. 一致性:在事务开始和结束时,数据库应该保持一致性状态。如果一个操作违反了数据库的完整性约束,则整个事务都会回滚。
  3. 隔离性:事务应该被隔离开来,以防止并发执行操作时发生干扰。MySQL提供了多种隔离级别,例如可重复读、读已提交、读未提交和串行化。
  4. 持久性:一旦事务提交,它对数据库的修改应该永久保存下来。即使系统发生故障,数据库也应该能够恢复到提交后的状态。

3.并发事务冲突

Mysql在并发处理事务时,事务直接可能会产生冲突,大致分为以下三种情况

  1. 脏读(Dirty Read):一个事务读取了另一个事务未提交的数据,导致读取到了“脏数据”,这种现象称为脏读。例如,一个事务在执行一些更新操作但还未提交时,另一个事务读取了更新前的数据,此时第二个事务读取到的就是脏数据。
  2. 不可重复读(Non-Repeatable Read):一个事务在读取了一个数据后,另一个事务修改或删除了这个数据,导致第一个事务再次读取时得到的结果与之前不同,这种现象称为不可重复读。例如,一个事务读取了某个数据,但是另一个事务修改了这个数据并提交了,此时第一个事务再次读取时得到的结果就不同了。
  3. 幻读(Phantom Read):一个事务在执行一次查询时,两次查询的结果集不一致,这种现象称为幻读。例如,一个事务查询某个范围内的数据,在第一次查询时得到了一些结果,但是在第二次查询时又得到了一些新的结果,这种情况就是幻读。

这些问题的出现是因为不同的事务在并发执行时,相互之间可能会产生干扰,导致事务的隔离性被破坏。为了解决这些问题,MySQL提供了不同的隔离级别,开发人员可以根据具体业务需求选择不同的隔离级别。例如,在可重复读隔离级别下,MySQL使用多版本并发控制(MVCC)技术来避免脏读和不可重复读问题,但是依然可能出现幻读问题。因此,对于特定的业务场景,需要仔细选择隔离级别并采取相应的措施来避免这些问题的出现。

4.事务隔离级别

MySQL提供了四个事务隔离级别,分别为读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。每个隔离级别提供不同的事务隔离程度,具体如下:

  1. 读未提交(Read Uncommitted):最低的隔离级别,事务中的修改可以被其他事务读取,甚至是未提交的修改。此级别的隔离性最差,容易出现脏读、不可重复读和幻读等问题。
  2. 读已提交(Read Committed):只允许读取已经提交的数据,其他事务对数据的修改在该事务提交后才能读取。此级别可以避免脏读,但是依然可能出现不可重复读和幻读等问题。
  3. 可重复读(Repeatable Read):保证在同一事务中多次读取同一数据时得到的结果始终相同,即使其他事务对该数据进行了修改。该级别可以避免脏读和不可重复读,但是依然可能出现幻读问题。
  4. 串行化(Serializable):最高的隔离级别,所有事务按照顺序串行执行,相当于对整个数据库加了一个锁。可以避免脏读、不可重复读和幻读等所有问题,但是对性能有较大影响。

在选择隔离级别时,需要根据具体业务需求和性能要求进行选择。通常情况下,可重复读是最常用的隔离级别,因为它可以保证数据的一致性,同时对性能的影响相对较小。如果应用中需要对数据进行较多的更新操作,可以考虑使用读已提交或串行化隔离级别。

二.自动提交与手动提交

1.概述

Mysql事务有自动提交和手动提交两种方式,MySQL8中默认使用自动提交(autocommit)模式,也就是说,每个SQL语句都会自动提交一个事务。当执行一个SQL语句时,如果该语句执行成功,则该语句的修改就会立即生效并提交到数据库中;如果该语句执行失败,则该语句所做的修改也会被回滚。

自动提交模式的好处是可以简化代码编写,减少出错的机会。但是,在某些情况下,可能需要手动控制事务的提交和回滚,以保证数据的一致性和完整性。例如,需要在多个SQL语句之间建立一个事务,以保证这些语句的执行要么全部成功,要么全部失败回滚。

手动提交和回滚事务的方法如下:

  1. 手动提交事务:使用“commit”语句提交当前事务,例如“commit;”。
  2. 手动回滚事务:使用“rollback”语句回滚当前事务,例如“rollback;”。

在手动提交事务的情况下,多个SQL语句可以组成一个事务,只有在所有语句都执行成功后,才会将这些修改提交到数据库中。如果其中一个SQL语句执行失败,整个事务都会被回滚,即所有修改都不会生效。

需要注意的是,在手动提交事务的情况下,如果没有使用“commit”语句提交事务,那么所有修改都不会被保存到数据库中,这可能会导致数据丢失或不一致。因此,需要特别小心地管理事务提交和回滚的操作。

2.事务实操

查看事务提交类型,ON为自动提交,OFF是手动提交

SHOW VARIABLES LIKE 'autocommit';

另一种方式 1为自动提交,0为手动提交

SELECT @@autocommit;

修改提交类型为手动提交,如果要修改为自动提交,就把0换成1,但是要注意,这只在一次Mysql会话(一次客户端与mysql的连接)中生效,如果要持久生效需要修改my.ini配置文件。

SET autocommit = 0;

手动提交下开启一个事务(Begin也可以,效果是一样的)

START TRANSACTION;   

回滚整个事务,即整个事务中所有执行的SQL

ROLLBACK

提交事务,事务一旦提交就无法ROLLBACK回滚

COMMIT

3.连接关闭后手动提交变回了自动提交

当关闭连接时,手动提交的事务会自动回滚,也就是事务的状态变回了自动提交。这是因为事务是与连接绑定的,连接关闭后事务也随之失效。如果想要在关闭连接后继续进行事务操作,需要重新建立连接并开启新的事务。

4.连接关闭后未提交的事务自动回滚

如果 MySQL 的连接在事务处理期间意外关闭或用户手动关闭,未提交的事务将自动回滚。这是 MySQL 的默认行为。如果需要将未提交的事务持久化并在重新连接后继续处理,可以使用事务日志或XA事务。

5.手动提交但是没有使用start transation,依然能够rollback之前所有sql

在MySQL 8中,如果要手动提交事务,可以使用START TRANSACTION语句来明确地开始一个事务。但是,如果在没有显式启动事务的情况下执行多个更新(增删改)语句,并且已关闭自动提交,则这些语句将在同一事务中执行,并且可以使用COMMIT语句来提交它们。因此,在MySQL 8中,可以使用手动提交事务而无需明确地启动事务,只需确保已关闭自动提交。

6.修改事务隔离级别

在 MySQL 中可以使用 SET TRANSACTION 命令来设置事务的隔离级别,命令格式如下:

SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

其中,隔离级别参数可以是以下四种:

  • READ UNCOMMITTED:未提交读,最低的隔离级别,事务可以读取未提交的数据,可能导致脏读、不可重复读和幻读问题。
  • READ COMMITTED:提交读,事务只能读取已经提交的数据,可以避免脏读问题,但是可能存在不可重复读和幻读问题。
  • REPEATABLE READ:可重复读,事务在执行期间读取的数据集不会发生改变,可以避免脏读和不可重复读问题,但是可能存在幻读问题。
  • SERIALIZABLE:串行化,最高的隔离级别,可以避免脏读、不可重复读和幻读问题,但是会导致并发性能问题。

需要注意的是,设置隔离级别只对当前会话有效,事务结束后会自动恢复到数据库的默认隔离级别。如果需要全局设置隔离级别,可以修改 my.cnf 配置文件并重启数据库服务。

7.rollback如何只回滚上一条SQL语句?

在MySQL 8中,可以使用SAVEPOINT语句来创建一个保存点(Savepoint),在事务执行过程中可以回滚到保存点的位置,从而回滚指定的SQL语句,而不是整个事务。

使用SAVEPOINT语句创建保存点的语法如下:

SAVEPOINT savepoint_name;

其中,savepoint_name为保存点的名称,可以自定义。

创建保存点之后,可以使用ROLLBACK语句回滚到指定的保存点,从而回滚到保存点之后执行的SQL语句。例如:

ROLLBACK TO SAVEPOINT savepoint_name;

其中,savepoint_name为需要回滚到的保存点的名称。

需要注意的是,如果在回滚到保存点之后,后续还有其他的SQL语句执行,则这些SQL语句仍然会被撤销,因为回滚到保存点相当于撤销保存点之后的所有SQL语句,而且该保存点也会被删除。

这是MySQL 8的设计规定,符合SQL标准,因为保存点实际上是一种事务处理的辅助机制,用于标记一个事务处理过程中的一个可回滚的状态,并在需要回滚时恢复到这个状态,而当使用ROLLBACK语句回滚到保存点时,相当于是回滚到这个状态之前,因此保存点也会被删除。

如果需要在回滚之后还能继续使用保存点,可以重新创建一个新的保存点。例如:

SAVEPOINT my_savepoint; 
-- 一些修改操作 
ROLLBACK TO SAVEPOINT my_savepoint; 
-- 回滚到保存点之后的状态 
SAVEPOINT my_new_savepoint; 
-- 继续进行修改操作
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值