目录
一、事务简介
事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作 要么同时成功,要么同时失败。
举例说明:最典型例子:银行转账(张三向李四转一千块钱)
- 正常情况:
查询张三账户余额 张三账户余额 -1000 李四账户余额 +1000 -
异常情况: (此时张三减少的钱不能加给李四)
因此,我们想要解决这种异常,我们就需要通过 数据库的事务 来解决,将上述三个操作定义在一个事务当中,要么全部执行成功,要么全部执行失败。
-
解决情况:(事务)
回滚事务就是指将之前临时修改的数据恢复回去,即初始化。 |
对于MySQL数据库来说,事务是默认自动提交的,也就是说当我们进行增删改的某一条语句时,语句结束完,事务就提交给数据库,数据库中数据就会立刻变更过来。
二、事务操作
- 查看 / 设置 事务提交方式:
SELECT @@autocommit ;(自动提交)
SET @@autoconnit = 0;(手动提交)
- 提交事务:START TRANSACTION 或 BEGIN;
- 提交事务:COMMIT;
- 回滚事务:ROLLBACK;
上述例子操作:
-- 创建表添加数据
create table account(
id int auto_increment primary key comment '主键',
name varchar(10) comment '姓名',
money int comment '金额'
)comment '账户表';
insert into account (id, name, money) values (null,'张三',2000),(null,'李四',2000);
update account set money = 2000 where name = '张三' or name = '李四';
-- 方式一:
select @@autocommit;
set @@autocommit = 0;
-- 转账操作
-- 1.查询张三账户余额
select * from account where name = '张三';
-- 2.张三账户余额 -1000
update account set money = money - 1000 where name = '张三';
程序抛出异常...
-- 3.李四账户余额 +1000
update account set money = money + 1000 where name = '李四';
-- 提交事务
commit ;
-- 回滚事务
rollback ;
-- 方式二:
-- 转账操作
-- 开启事务
start transaction ;
-- 1.查询张三账户余额
select * from account where name = '张三';
-- 2.张三账户余额 -1000
update account set money = money - 1000 where name = '张三';
程序抛出异常...
-- 3.李四账户余额 +1000
update account set money = money + 1000 where name = '李四';
-- 提交事务
commit ;
-- 回滚事务
rollback ;
三、事务四大特性(ACID)
- 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
- 隔离性(lsolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
- 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
四、并发事务问题
并发事务问题指 事务A 和 事务B 在同时操作某一个数据库甚至是某一张表时,所引发的一些问题。
问题 | 描述 |
脏读 | 一个事务读到另外一个事务还没有提交的数据。 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了"幻影”。 |
1. 脏读
事务A第一步操作执行完后执行第二步操作,但是事务没有执行完毕是没有提交的,事务A第二步操作结束完后会对数据库表中数据进行更新,此时另外一步事务B进行查询操作,而事务B查询到的正好是事务A第二步操作更新的数据,但是事务A并没有提交。
2. 不可重复读
事务A执行第一步操作后,开始执行第二步操作同时事务B执行更新操作,操作结束后将数据提交到数据库,接着事务A执行第三步操作,此时第一步操作和第三部操作都为一样的查询语句,但是结果不同。
3. 幻读
事务A执行第一步操作,此时事务B也执行操作,执行完毕将数据提交给数据库,接着事务A执行第二步操作,但是发现执行失败,对应主键已经存在,但是当执行第三步操作时,执行结果为空。
五、事务隔离级别
根据上述我们对并发事务问题的了解,接下来我们就学习事务隔离级别来解决这些问题:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
Read uncommitted | ✔ | ✔ | ✔ |
Read committed | ✖ | ✔ | ✔ |
Repeatable Read(默认) | ✖ | ✖ | ✔ |
Serializable | ✖ | ✖ | ✖ |
- 查看事务隔离级别:SELECT @@TRANSACTION_ISOLATION;
- 设置事务隔离级别:SET [ SESSION | GLOBAL ] TRANSACTION ISOLATON LEVEL { READUNCOMMITTED | READ COMMITED│REFPEATABLE READ│ SERALZABLE }
注意:事务隔离级别越高,数据越安全,但是性能越低。