Mysql-事务

1.介绍

事务就是一组 DML 语句组成,这些语句在逻辑上存在相关性,这一组 DML 语句要么全部成功,要么全部失败,是一个整体。MySQL 提供一种机制,保证我们达到这样的效果。
一个 MySQL 数据库,可不止你一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,
在向 MySQL 服务器发起事务处理请求。而每条事务至少一条 SQL ,最多很多 SQL , 这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。

一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性:

  • 原子性: 一个事务( transaction )中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback )到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性: 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • **隔离性:**数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable )
  • 持久性: 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

上面四个属性,可以简称为 ACID 。 当我们使用事务时,要么提交,要么回滚。**因此事务本质上是为了应用层服务的。**而不是伴随着数据库系统天生就有的。

2.事务的版本支持

在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务, MyISAM 不支持。

3.事务的提交方式

事务的提交方式常见的有两种:

  • 自动提交
  • 手动提交

查看事务提交方式

show variables like 'autocommit' ;

用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0; #SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT = 1 ; #SET AUTOCOMMIT=1 开启自动提交

4.事务的操作

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关。
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚。
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为 MySQL 有MVCC )。
  • 从上面的例子,我们能看到事务本身的原子性(回滚),持久性(commit)。

savepoint save1; -- 创建一个保存点save1

当插入或删除一个数据后,想放弃这次的操作可以回滚到保存点save1
rollback to save1; -- 回滚到save1


事务操作注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)。
  • 如果一个事务被提交了(commit),则不可以回退(rollback)。
  • 可以选择回退到哪个保存点。
  • InnoDB 支持事务, MyISAM 不支持事务。
  • 开始事务可以使 start transaction 或者 begin。

5.事务隔离级别

5.1 如何理解隔离性?

  • MySQL服务可能会同时被多个客户端进程(线程)访问,访问的方式以事务方式进行
  • 一个事务可能由多条 SQL 构成,也就意味着,任何一个事务,都有执行前,执行中,执行后的阶段。而所谓的原子性,其实就是让用户层,要么看到执行前,要么看到执行后。执行中出现问题,可以随时回滚。所以单个事务,对用户表现出来的特性,就是原子性。
  • 所有事务都要有个执行过程,那么在多个事务各自执行多个 SQL 的时候,就还是有可能会出现互相影响的情况。
  • 数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性。
  • 数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别 。

隔离级别

5.1.1 读未提交

读未提交【 Read Uncommitted : 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等。

--几乎没有加锁,虽然效率高,但是问题太多,严重不建议采用。

--一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读(dirty read)

5.1.2 读提交

读提交【 Read Committed :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义: 一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select , 可能得到不同的结果。

同一个事务内,同样的读取,在不同的时间段 ( 依旧还在事务操作中!) ,读取到了不同的值,这种现象叫做不可重复读 (non reapeatable read)。

5.1.3 可重复读

可重复读【 Repeatable Read : 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。

insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读(phantom read)。

5.1.4 串行化

串行化【 Serializable : 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争。(这种隔离级别太极端,实际生产基本不使用)

--对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用。

5.2 总结

  • 隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个平衡点。
  • 不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增:同样的条件, 第1次和第2次读出来的记录数不一样。
  • mysql 默认的隔离级别是可重复读,一般情况下不要修改。

set global transaction isolation level 隔离级别 --设置全局隔离级别的SQL命令

6.一致性

  • 事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。
  • 其实一致性和用户的业务逻辑强相关,一般 MySQL 提供技术支持,但是一致性还是要用户业务逻辑做支撑,也就是,一致性,是由用户决定的。
  • 而技术上,通过 AID 保证 C 。
相关推荐
何怀逸2 分钟前
MySQL的buffer pool的缓存中,修改语句在执行时,是先更新buffer pool,还是先更新数据库
数据库·mysql·缓存
SaebaRyo2 分钟前
MySQL常见写法
后端·mysql·docker
SaebaRyo6 分钟前
MySQL多表查询和事务
后端·mysql
xjz18428 分钟前
深入解析MySQL 5.7 InnoDB多版本并发控制(MVCC)机制
mysql
deadknight91 小时前
表、索引统计信息锁定和解锁
数据库·oracle
yinghuabanwo1 小时前
【1688】崖山集群YAC安装备忘
数据库·崖山yashandb
不剪发的Tony老师1 小时前
PostgreSQL 18新特性之虚拟生成列
数据库·postgresql
考虑考虑1 小时前
UNION和UNION ALL的用法与区别
数据库·后端·mysql
CL_IN1 小时前
如何将聚水潭·奇门平台数据高效集成到MySQL
android·数据库·mysql
8643063372 小时前
在Visual Studio 2022中实现Qt插件开发
数据库·qt·visual studio