一、什么是事务?
1. 类比生活
生活中往往出现这样一种场景,一件事情中包含多个任务,只有多个任务同时完成事务才能办成,否则只要有一个任务失败,整件事情失败。
如公司的运营,所有员工共同配合:
- 独立的事务
员工A 工作:独立,和其他人之间没有互相影响 - 独立的事务
员工B 工作:检查线路-> 断电 -> 检查完成-> 完成
员工C 工作:正常工作-> …等待… - 实际工作过程中,为了提高工作效率,要求不同的事务之间必须隔离
不同的员工之间的工作都是相对独立的,提高工作效率
员工A 合格!员工 B/C 出现了事务冲突工作效率受到影响
2. 事务的定义
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。通俗来说事务就是多条DML语句同时成功或者同时失败。
目标:了解事务的本质,了解事务的工作过程,操作事务以提高数据操作效率这才是事务管理的本质。
注
:只有DML语句才与事务管理有关,其他语句无关。只要进行数据的增、删、改操作,就要考虑数据的安全性。
3. 事务的特性(ACID)
3.1 原子性(atomicity)
所有任务要么全部成功,要么全部失败。说明事务是最小的工作单元,不可再分。如 A给 B 转账,不会出现A的钱少了,而B的钱没有增加的情况。
3.2 一致性(consistency)
事务开始前和结束后,数据的完整性约束没有被破坏。如转账完成后,A减少100,B一定增加100。
3.3 隔离性(isolation)
同一时间,只允许一个事务请求同一数据。多个事务同时操作时,不同事务之间彼此没有任何干扰。
3.4 持久性(durability)
事务一旦被提交,对数据的改变就是永久性的。即使数据库系统遇到故障也不会丢失提交事务的操作。
4. 事务的隔离级别
事务的特性已经确定了,但是数据库中如果严格按照事务的四大特性进行管理的话,数据的操作就会变得非常缓慢且消耗非常多的系统资源,为了保障数据的ACID特性的同时提升数据操作的效率
,数据库中定义了事务的隔离级别
4.1 读未提交(read uncommitted)
事务A读到了事务B未提交的数据,并在该数据基础上进行操作。
- 隔离级别最低,操作效率最高,数据的稳定性最差。
- 会出现
脏读
现象:读到了脏数据(别人没有提交的数据)。如果另一个事务回滚,当前事务读到的数据是不合法的。
4.2 读已提交(read committed)
事务A只能读到事务B已提交的数据。
- 大多数数据库默认的隔离级别。如oracle
- 操作效率相对较低,数据的稳定性较差。
- 解决了脏读的问题,每次读取得到的都是真实的数据。
- 会出现
不可重复读
现象:A事务读取了B事务已经提交的更改或删除
数据。在事务开启之后,第一次读到的数据是3条,当前事务未结束,再次读取时,读到的数据是4条。 - 解决策略:对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除。
4.3 可重复读(repeatable read)
一个未完成的事务读取不到其他事务已经提交的数据。如事务A 开启之后,不管多久,每一次在事务A 中读取到的数据都是一致的。即使事务B 已经将数据修改,并且提交了,事务A读取到的数据依旧没有发生改变。
MySQL默认的事务隔离级别。
- 操作效率较低,数据的稳定性较高。
- 解决了脏读和不可重复读的问题。
- 会出现
幻读
现象:A事务读取了或意识到了B事务已经提交的新增
数据。 - 解决策略:对于幻读,必须加表级锁,防止在这个表中新增一条数据。
4.4 序列化/串行化(serializable)
多个事务要排队,不能并发,一个事务在操作时,另一个事务不能操作。
- 操作效率最低,数据稳定性最高。
- 解决了脏读,不可重复读和幻读。
二、事务的操作
MySQL中事务行为默认提交,每执行一条DML语句,就提交一次。
1. 基本语法
1.1 设置隔离级别
-
查看隔离级别
select @@session.transaction_isolation; -- 查看会话级的当前隔离级别 select @@global.transaction_isolation; -- 查看全局级的当前隔离级别
-
设置隔离级别
set session transaction isolation level 隔离级别名称; -- 设置会话级隔离级别 set global transaction isolation level 隔离级别名称; -- 设置全局级隔离级别
1.2 开启事务
start transaction;
1.3 提交事务
commit();
清空事务性活动的日志文件,将改变的数据全部彻底持久化到数据库表中。
提交事务标志着事务的结束,并且是全部成功
的结束。
1.4 回滚事务
rollback();
清空事务性活动的日志文件,将之前所有的DML操作全部撤销恢复到数据改变之前。
回滚事务标志着事务的结束,并且是全部失败
的结束。
2. 案例演示
左:事务A 右:事务B
2.1 读未提交
2.2 读已提交
设置隔离级别,需要重连数据库。
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
2.3 可重复读
mysql> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
2.4 序列化
mysql> set global transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)