2-3-1-3、事务和事务的隔离级别


事务定义

事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位(不可再进行分割),由一个有限的数据库操作序列构成(多个 DML 语句),要不全部成功,要不全部不成功

DDL (DataDefinitionLanguage)︰数据定义语言,用来定义数据库对象︰库、表、列等
DML(DataManipulationLanguage)︰数据操作语言,用来定义数据库记录(数据)
DQL (DataQueryLanguage):数据查询语言,用来查询记录(数据)
DCL (DataControlLanguage)︰数据控制语言,用来定义访问权限和安全级别

例如:

A 给 B 要转账,A 的账户-1000 元, B 的账户就要+1000 元,这两个 update 语句必须作为一个整体来执行,不然 A 扣钱了,B 没有加钱这种情况就是错误的。那么事务就可以保证 A 、B 账户的变动要么全部一起发生,要么全部一起不发生

事务特性

事务应该具有以下 4 个属性,这四个属性通常称为 ACID 特性

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)

原子性(atomicity)

一个事务必须被视为一个不可分割的最小单元,整个事务中的所有操作要么全部提交成功,要么全部失败,对于一个事务来说,不能只执行其中的一部分操作。比如上面的经典例子:

A 给 B 要转账,A 的账户-1000 元, B 的账户就要+1000 元,这两个 update 语句必须作为一个整体来执行,不然 A 扣钱了,B 没有加钱这种情况就是错误的。那么事务就可以保证 A 、B 账户的变动要么全部一起发生,要么全部一起不发生

一致性(consistency)

一致性是指事务将数据库从一种一致性转换到另外一种一致性状态,在事务开始之前和事务结束之后数据库中数据的完整性没有被破坏,例如上面例子中的账户总和是不变的,也就是一致的

隔离性(isolation)

一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
上面的例子在多线程条件下会有并发问题,MySQL就是通过隔离性来控制并发问题的

持久性(durability)

一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,已经提交的修改数据也不会丢失

事务并发引起的问题

理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据,这样的话并发事务的执行就变成了串行化执行
但是对串行化执行性能影响太大,我们既想保持事务的一定的隔离性,又想让服务器在处理访问同一数据的多个事务时性能尽量高些,这样根据隔离性的不同会引发下面的问题

脏读

当一个事务读取到了另外一个事务修改但未提交的数据,被称为脏读

不可重复读

当事务内相同的记录被检索两次,且两次得到的结果不同时,此现象称为不可重复读

幻读

在事务执行过程中,另一个事务将新记录添加到正在读取的事务中时,会发生幻读

SQL 标准中的四种隔离级别

image.png

MySQL 中的隔离级别

不同的数据库厂商对 SQL 标准中规定的四种隔离级别支持不一样,比方说 Oracle 就只支持 READ COMMITTED 和 SERIALIZABLE 隔离级别,MySQL 虽然支持 4 种隔离级别,但与 SQL 标准中所规定的各级隔离级别允许发生的问题却有些出入,MySQL 在 REPEATABLE READ 隔离级别下,是可以禁止幻读问题的发生的
image.png
MySQL 的默认隔离级别为 REPEATABLE READ,我们可以手动修改事务的隔离级别

如何设置事务的隔离级别

我们可以通过下边的语句修改事务的隔离级别:

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level;

其中的 level 可选值有 4 个:

  • REPEATABLE READ
  • READ COMMITTED
  • READ UNCOMMITTED
  • SERIALIZABLE

设置事务的隔离级别的语句中,在 SET 关键字后可以放置 GLOBAL 关键字、SESSION 关键字或者什么都不放,这样会对不同范围的事务产生不同的影响,具体如下:

使用 GLOBAL 关键字(在全局范围影响)

例如:

SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;

只对执行完该语句之后产生的会话起作用。当前已经存在的会话无效

使用 SESSION 关键字(在会话范围影响)

例如:

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

对当前会话的所有后续的事务有效
该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务;如果在事务之间执行,则对后续的事务有效

不用关键字(只对执行语句后的下一个事务产生影响)

例如:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

只对当前会话中下一个即将开启的事务有效。下一个事务执行完后,后续事务将恢复到之前的隔离级别。该语句不能在已经开启的事务中间执行,会报错的

修改默认MySQL隔离级别

如果我们在服务器启动时想改变事务的默认隔离级别,可以修改启动参数 transaction-isolation 的值,比方说我们在启动服务器时指定了

--transaction-isolation=SERIALIZABLE

那么事务的默认隔离级别就从原来的 REPEATABLE READ 变成了 SERIALIZABLE
查看当前会话默认的隔离级别可以通过查看系统变量 transaction_isolation 的值来确定:

SHOW VARIABLES LIKE 'transaction_isolation';

image.png
使用下面的简写命令也可以:

SELECT @@transaction_isolation;

image.png
transaction_isolation 是在 MySQL 5.7.20 的版本中引入来替换 tx_isolation 的,如果使用的是之前版本的 MySQL,请将上述用到系统变量 transaction_isolation 的地方替换为 tx_isolation

MySQL 事务

事务基本语法

事务开始

  1. begin
  2. START TRANSACTION(推荐)
  3. begin work

事务回滚

rollback

事务提交

commit

保存点

如果你开启了一个事务,执行了很多语句,忽然发现某条语句有点问题,你只好使用 ROLLBACK 语句来让数据库状态恢复到事务执行之前的样子,然后一切从头再来,但是可能根据业务和数据的变化,不需要全部回滚。所以 MySQL 里提出了一个保存点(英文:savepoint)的概念,就是在事务对应的数据库语句中打几个点,我们在调用 ROLLBACK 语句时可以指定会滚到哪个点,而不是回到最初的原点。定义保存点的语法如下:

SAVEPOINT 保存点名称;

当我们想回滚到某个保存点时,可以使用下边这个语句(下边语句中的单词 SAVEPOINT 是可有可无的):

ROLLBACK TO [SAVEPOINT] 保存点名称;

不过如果 ROLLBACK 语句后边不跟随保存点名称的话,会直接回滚到事务执行之前的状态不过如果 ROLLBACK 语句后边不跟随保存点名称的话,会直接回滚到事务执 行之前的状态
如果我们想删除某个保存点,可以使用这个语句:

RELEASE SAVEPOINT 保存点名称;

隐式提交

使用 START TRANSACTION 或者 BEGIN 语句开启了一个事务,或者把系统变量 autocommit 的值设置为 OFF 时,事务就不会进行自动提交,但是如果我们输入了某些语句之后就会悄悄的提交掉,就像我们输入了 COMMIT 语句了一样,这种因为某些特殊的语句而导致事务提交的情况称为隐式提交,这些会导致事务隐式提交的语句包括:

  • 执行 DDL
  • 隐式使用或修改 mysql 数据库中的表

使用 ALTER USER、CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD 等语句时也会隐式的提交前边语句所属于的事务

  • 事务控制或关于锁定的语句
    • 在一个会话里,一个事务还没提交或者回滚时就又使用 START TRANSACTION 或者 BEGIN 语句开启了另一个事务时,会隐式的提交上一个事务
    • 当前的 autocommit 系统变量的值为 OFF,我们手动把它调为 ON 时, 也会隐式的提交前边语句所属的事务
    • 使用 LOCK TABLES、UNLOCK TABLES 等关于锁定的语句也会隐式的提交 前边语句所属的事务
  • 加载数据的语句

使用 LOAD DATA 语句来批量往数据库中导入数据时,也会隐式的提交前边语句所属的事务

  • MySQL 复制的一些语句

使用 START SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO 等语句时也会隐式的提交前边语句所属的事务

  • 其它的一些语句

使用 ANALYZE TABLE、CACHE INDEX、CHECK TABLE、FLUSH、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE、RESET 等语句也会隐式的提交前边语句所属的事务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值