MySQL — 事务 (o゚▽゚)o
文本目录:
❄️一、什么是事务:
❄️二、ACID特性:
❄️三、使用事务:
▶1、查看支持事务的存储引擎:
▶2、语法:
▶3、开启并且回滚:
▶4、开启并且提交:
▶ 5、保存点:
▶6、手动/自动提交事务:
❄️四、事务的隔离性和隔离级别:
☑1、隔离性:
☑2、隔离级别:
☑3、查看和设置隔离级别:
☑4、不同隔离级别存在的问题:
1)、READ UNCOMMITTED — 读未提交与脏读:
2)、READ COMMITTED — 读已提交与不可重复读:
3)、REPEATABLE READ — 可重复读与幻读:
4)、SERIALIZABLE — 串行化:
☑5、不同隔离级别的性能:
❄️总结:
❄️一、什么是事务:
事务呢就是把一组 SQL 语句打包成为一个整体,对于这组 SQL 语句的执行呢,结果要么是全部成功,要么是全部失败。对于这组 SQL 语句可以是 一条也可以是多条语句。
我们来举一个例子:
对于转账来说:
我们来看看对于这个操作的语句的编写:
转账成功之后呢,要满足一下结果:
1、张三 的钱为 900 而李四的钱为1100,不能出现张三减少而李四没有增加的结果。
2、张三和李四在转账前后的总的钱数是不变的,1000+1000 = 2000 - > 900 + 1100 = 2000
3、转账后的结果应该保存在存储介质中,以便于后面的使用
4、 在转账的处理过程中张三和李四的余额不能因其他的转账事件而受到干扰。
这上面的四个条件呢,就是我们的 事务在执行过程中必须要保证的,这也就是事务的 ACID特性。
我们来详细介绍一下 ACID 特性。
❄️二、ACID特性:
事务的 ACID 呢指的是:Atomicity(原子性),Consistency(一致性),Isolation(隔离性)和Durability(持久性)。
1、Atomicity(原子性):
一个事务中的所有操作要么全部成功、要么全部失败,不会出现只成功一半的情况,如果事务在执行过程中发生错误,会 回滚 到事务的开始前的状态,就像这个事务从来没有执行过一样。
2、Consistency(一致性):
在事务的开始之前或者结束之后,数据库的完整性不会被破坏。这表示写入的数据必须完全符合所有的预设规则,包括数据的精度、关联性以及关于事务执行过程中服务器崩溃后如何恢复。
3、Isolation(隔离性):
数据库允许多个并发事务同时对数据进行读写和修改,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务可以指定不同的隔离级别,以权衡在不同的应用场景下数据库性能和安全。
4、Durability(持久性):
事务处理结束后,对数据的修改将永久的写入存储介质,即便系统故障也不会丢失。
❄️三、使用事务:
▶1、查看支持事务的存储引擎:
要使用事务那么数据库就要支持使用,在 MySQL 中呢支持事务的存储引擎呢是 InnoDB ,我们可以通过 show engines;来进行查看:
▶2、语法:
对于事务的语法就非常的简单了,我们来看看:
-- 开启一个新的事务
START TRANSACTION;
-- 或者
BEGIN
-- 提交当前事务,并对更改持久化保存
COMMIT;
-- 回滚当前事务,取消其更改
ROLLBACK;
注意:
不论是 提交 或者 回滚 ,事务都会关闭
▶3、开启并且回滚:
我们先来开启事务:
这之后我们所写的 SQL语句 都是包含在事务中的。之后我们再进行操作:
这些操作都包含在 事务中,之后我们来进行回滚之后,再看看余额是什么:
可以看到再 回滚事务之后呢 我们的数据就返回到了事务开始之前了。
▶4、开启并且提交:
这个操作呢,在关闭事务之前的操作是一样的,我们直接来看代码:
我们来提交一下事务看看: 我们可以看到对于提交之后呢,数据就进行了在事务中执行之后所得的数据的结果进行了保存。
▶ 5、保存点:
语法:
SAVEPOINT 保存点的名字;
我们来看看如何使用:
这个虽然有点长,但是呢这个就是我们的关于保存点的使用,和如何回滚到保存点的操作。这里要注意:当我们的回滚到保存点这个操作的时候,我们要注意要有 to 和保存点的名字。
▶6、手动/自动提交事务:
默认情况下,MySQL是自动提交事务的,也就是说我们执行的每个修改操作,比如插入、更新和删除,都会自动开启一个事务并在语句执行完成之后自动提交,发生异常时自动回滚。
查看当前事务是否自动提交可以使用以下语句:
show variables like 'autocommit';
ON 表示自动提交开启。
如果想要更改是否是否自动提交,我们可以使用一下语句:
设置自动提交:
SET AUTOCOMMIT=1;
SET AUTOCOMMIT=NO;
设置手动提交:SET AUTOCOMMIT=0;
SET AUTOCOMMIT=OFF;
对于我们的修改是否自动提交的时候要注意:
1、只要使用 START TRANSACTION 或 BEGIN 开启事务,必须要通过 COMMIT 提交才会持久化,与是否设置 SET autocommit 无关。
2、手动提交模式下,不用显示开启事务,执行修改操作后,提交或回滚事务时直接用commit 或 rollback。
3、 已提交的事务不能回。
❄️四、事务的隔离性和隔离级别:
☑1、隔离性:
简单来说呢,隔离性就是让不同的事务之间在执行的过程中不受影响,那么事务之间就需要要相互隔离。
☑2、隔离级别:
事务之间不同的隔离程度,我们称之为 —— 事务的隔离级别,不同的隔离级别在性能和安全方面做了取舍,有的隔离级别注重并发性,有的注重安全性,有的则是并发和安全适中。
在MySQL 中对于事务的隔离级别有四种:
a、READ UNCOMMITTED ,读未提交
b、READ COMMITTED ,读已提交
c、REPEATABLE READ ,可重复读(默认)
d、SERIALIZABLE ,串行化
但是呢对于这几种隔离级别都存在一些问题不是很完美的,这些问题我们之后来了解一下。
☑3、查看和设置隔离级别:
事务的隔离级别分为全局作用域和会话作用域,查看不同作用域事务的隔离级别,可以使用以下的方式:
-- 全局作用域
SELECT @@GLOBAL.transaction_isolation;
-- 会话作用域
SELECT @@SESSION.transaction_isolation;
我们来演示一遍:
默认是 可重复读的。
对于在不同的作用域中设置事务的隔离级别:
语法1:
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔离级别;
语法2:
这里要注意在隔离级别中如果存在空格要使用 “-” 代替
SET GLOBAL transaction_isolation = '隔离级别';
语法3:
这里要注意在隔离级别中如果存在空格要使用 “-” 代替
SET @@GLOBAL.transaction_isolation = '隔离级别'
示例:
语法1:
-- 设置全局事务隔离级别为串行化,后续所有事务生效,不影响当前事务
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 设置会话事务隔离级别为串行化,当前会话后续的所有事务⽣效,不影响当前事务,可以在任何时候执行
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
语法2:
SET GLOBAL transaction_isolation = 'SERIALIZABLE';
SET GLOBAL transaction_isolation = 'REPEATABLE-READ';
☑4、不同隔离级别存在的问题:
1)、READ UNCOMMITTED — 读未提交与脏读:
这个的隔离级别,由于不在读取数据额时候做任何的操作,那么其并发性很高,但是呢会出现大量的数据安全问题,比如“脏读”。
什么是“脏读”:
比如在事务A中执行了一条 insert 语句,在没有执行 commit 的情况下,会被事务B读取到,这个时候我们在事务A中进行回滚,那么 事务B 中读取到的 事务A写入的数据将没有意义,我们把这个现象叫做——“脏读”。
我们来实现一下这个问题:
这个就是我们的 读未提交中的 “脏读” 问题。
2)、READ COMMITTED — 读已提交与不可重复读:
为了解决 “脏读” 这个问题呢,我们把事务的隔离级别设置为——READ COMMITTED,这个时候事务只能读取到其他事务提交之后的数据,但会出现——不可重复读的问题。
比如:我们在事务A中查询这个数据,之后在事务B中 修改这个数据 或者 新增一个数据,并且进行了 commit 操作,这时候 事务A 再查询数据的时候呢,得到的是事务B修改之后的结果,这个时候事务A就出现了在同一个事务中通过相同的问题,但是查询的是不同的结果,这个就是——不可重复读 问题。
我们还是进行对这个问题重现一下:
3)、REPEATABLE READ — 可重复读与幻读:
为了解决上面的问题呢,又提出了 REPEATABLE READ 的隔离级别,这时同一个事务中读取的数据在任何时候都是相同的结果。但是又出现了一个问题——幻读
比如:事务A查询了一个区间的记录得到结果集A,事务B向这个区间的间隙中写入了一条记录并提交,事务A再查询这个区间的结果集时会查到事务B新写入的记录得到结果集B,两次查询的结果集不一致,这个呢就是 —— 幻读。
我们还是来看看问题的演示:
这里因为 MySQL的InnoDB使用了 Next—Key 锁,解决了大部分的幻读问题,这里为了实现幻读,我们使用 READ COMMITTED 这个隔离级别。
这个就是幻读的问题的演示了。
4)、SERIALIZABLE — 串行化:
这个没有什么问题,此时所有的事务进行串行执行,可以解决所有的并发的安全问题,但是呢这个并发的性能最低。
☑5、不同隔离级别的性能:
并发性能 | 隔离级别 | 脏读 | 不可重复读 | 幻读 | 隔离力度 |
高 | READ UNCOMMITTED | 存在 | 存在 | 存在 | 低 |
较高 | READ COMMITTED | 解决 | 存在 | 存在 | 较低 |
较低 | REPEATABLE READ | 解决 | 解决 | 存在 | 较高 |
低 | SERIALIZABLE | 解决 | 解决 | 解决 | 高 |
❄️总结:
OK,我们的事务到这里呢也就结束了,并且对于MySQL的基础知识呢,我们到这里也同样了解完了,我们呢在下一博客中就要开启新的篇章了,让我们尽情期待吧!!!拜拜~~~