(一).事务的概念
事务是把一组SQL语句打包成一个整体,在这组SQL语句的执行过程中,要么全部成功,要么全部失败。
(二).事务的ACID特性
事务的ACID 特性指的是Atomicity(原子性) ,Consistency(一致性) ,Isolation(隔离性) 和Durability(持久性)。
1.Atomicity(原子性):
所执行的SQL语句要么全部成功,要么全部失败 ,不会出现执行一半的情况,如果事务在执行过程中出现错误,事务就会回滚(Rollback)到事务刚开始的状态,就像事务没有执行过一样。原子性是支持事务的数据库中最基本的一个特性。
2.Consistency(一致性):
事务执行完成后,保证数据正确并且符合预期
3.Isolation(隔离性):
多个事务之间不能相互影响
示例:

4.Durability(持久性):
将提交后的事务保存到存储介质中,不管数据库是否损坏,都不会影响数据的安全。
(三).事务的使用
1.查看mysql当前支持的存储引擎
show engines;

2.使用事务的语法
sql
-- 开始新的事务
start transaction; -- 或者 begin;
-- 提交当前事务,并对更改持久化保存
commit;
-- 回滚当前事务,取消对其更改
rollback;
注意:无论事务提交还是回滚,事务都会关闭。同时,开启一个事务之后,所写的SQL语句就包含在当前事务当中,这些事务具有ACID特性。
示例:
这是我创建的用于做示例的余额表

(1).测试回滚

(2).测试提交

3.保存点
在事务执行的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态。
语法:
设置保存点:SAVEPOINT SP1; SP1 为保存点的名字
回滚到第二个保存点:ROLLBACK TO SP2;
回滚到事务的初始状态:ROLLBACK
图解:

示例:

4.自动/手动提交事务
(1).自动提交事务
MYSQL默认情况下是自动开启提交和回滚的
查看是否自动开启提交和回滚
show variables like 'autocommit';
autocommit : 系统变量,表示事务是否自动提交

(2).设置事务为自动提交或者手动提交
sql
-- 设置事务自动提交
set autocommit =1;
set autocommit=on;
-- 设置事务手动提交
set autocommit=0;
set autocommit=off;
注意:
①.当使用start transaction 或 begin开启事务,就必须要通过commit 提交事务才会持久化,或者通过rollback回滚事务,才能结束事务,与是否检查set autocommit无关
②.当设置成手动提交事务后,不需要开启事务,主席那个修改操作后,提交或者回滚事务时直接使用commit或者rollback即可
③.已经commit的事务不可以再rollback
5.事务的隔离级别
(1).概念
事务间不同程度的隔离称为事务的隔离级别。事务的不同隔离级别在安全和性能都有差距,有的隔离级别注重并发性,有的隔离级别注重安全性,有的则是并发性和安全性适中,在Mysql的InnoDB的存储引擎中事务的隔离级别有四种:
READ UNCOMMITED ,读未提交
READ COMMITED,读已提交
REPEATABLE READ,可重复读(默认)
SERIALIZABLE,串行化
从高到低安全性越来越高,性能越来越低
(2).查看隔离级别
Ⅰ.查看全局的隔离级别
select @@global.transaction_isolation;
@@表示 "查看系统变量"
global 表示 "全局系统变量"所有会话都生效
Ⅱ.查看当前会话的隔离级别
select @@session.transaction_isolation;
session 表示 "当前会话生效"
(3).设置不同的隔离级别
Ⅰ.语法
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL level | access_mode
level 表示 "隔离级别",即上面介绍的四种隔离级别
access_mode 表示 "访问模式" ,有READ WRITE 和 READ ONLY,READ WRITE表示可以对数据进行读写,READ ONLY 表示只能读,不能写
方式1:SET GLOBAL TRANSACTION ISOLATION LEVEL level;
方式2:SET GLOBAL.TRANSACTION_ISOLATION = ' level ';
方式3:SET @@GLOBAL.TRANSACTION_ISOLATION = ' level ';
注意:使用方式2和方式3的时候,如果level对应的隔离级别有空格,则用"-"代替空格
Ⅱ.不同的隔离级别以及存在的问题
下面的演示会在两个会话的条件下进行演示
①.READ UNCOMMITTED 读未提交
事务A对数据进行了修改,然后事务B读取了事务A还未提交的数据,这个情况称为 "脏读",即事务B访问了事务A rollback的数据。"脏读"读取的数据并不是错误的数据,而是修改了还未保存的数据。
演示:

此时,两个会话中的隔离级别都是 "读未提交"

通过上面的图片可以看出,会话B访问了会话A 中还未保存的数据,此时这种情况就称为 "脏读",即读取的数据不准确。
②.READ COMMITTED 读已提交
事务B一开始读取了某些数据记录,然后事务A对这些数据记录进行了修改并提交,当事务B再次查询这些数据的时候发现与第一次查询的结果不一致,此时这个现象就叫做 "不可重复读"。
演示

此时,两个会话的隔离级别都是 "读已提交"

③.REPEATABLE READ 可重复读
事务A第一次查询了某个结果集,然后第二次以相同的方式查询得到的结果集,发现与第一次查询到的结果不同,两次查询到的结果集的结果不同,此时这种现象就叫做 "幻读"。
注意:InnoDB存储引擎中,使用了next-key锁,锁住了目标行和之前的间隙,解决了部分幻读的我问题。
演示:
由于可重复读的next-key锁配合着mysql的MVCC解决了部分 "幻读问题",所以这里还是先使用 "读已提交"的隔离级别先来演示一下 "幻读"。

隔离级别依旧是 "读已提交"

间隙里面插入数据,导致两次查询的结果不一致,此时这个现象就叫做幻读
先将 隔离级别修改为 "可重复读"


④.串行化
串行化是隔离程度的最高级别,两个事务互不影响。
一个事务进行CRUD 操作的时候,不会影响到其他事务对同一个表的查询,也就是串行化不存在脏读,不可重复读、幻读的隔离问题。
总结
|------------------|--------|-----------|--------|
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| READ UNCOMMITTED | 存在 | 存在 | 存在 |
| READ COMMITTED | 不存在 | 存在 | 存在 |
| REPEATABLE READ | 不存在 | 不存在 | 存在 |
| SERIALIZABLE | 不存在 | 不存在 | 不存在 |
从上到下,性能越来越低安全性越来越高
从下到上,性能越来越低安全性越来越高