# MySQL进阶
# 事务
# 引子
转账操作,中间步骤出错,会导致数据不同步
select * from account where name = '张三';
-- 张三账户-1000
update account set money = money - 1000 where name = '张三';
-- 模拟程序抛出异常
程序执行报错...
-- 李四账户+1000
update account set money = money + 1000 where name = '李四';
执行结束后,张三账户减了1000,李四账户没有加1000,采用事务的原子性可以解决这个问题
# 事务操作
- 查看设置事务提交方式,mysql默认自动提交
select @@autocommit;
set @@autocommit = 0;
- 开启事务(推荐)
start transaction;
begin;
- 提交事务
commit;
- 回滚事务,(一般在事务代码块中使用)
rollback;
- 查询正在执行的事务
SELECT * FROM information_schema.INNODB_TRX;
# 使用事务解决
方式一:
select @@autocommit;
-- 当前会话设置为手动提交
set @@autocommit = 0;
select * from account where name = '张三';
-- 张三账户-1000
update account set money = money - 1000 where name = '张三';
-- 模拟程序抛出异常
程序执行报错...
-- 李四账户+1000
update account set money = money + 1000 where name = '李四';
-- 提交事务
commit;
-- 回滚事务
rollback;
方式二:
select @@autocommit;
set @@autocommit = 1;
start transaction;
select * from account where name = '张三';
-- 张三账户-1000
update account set money = money - 1000 where name = '张三';
模拟出错...
-- 李四账户+1000
update account set money = money + 1000 where name = '李四';
-- 提交事务
commit;
-- 回滚事务
rollback;
# 事务四大特性
- 原子性:事务是不可分割的最小操作单元
- 一致性:事务完成时,必须使所有数据保持一致
- 隔离性:不同事物同时操作相同的数据,每个事务都有各自的完整数据空间
- 持久性:事务一旦提交,他对数据库中的数据改变是永久的,并不会被回滚
# 并发事务问题
脏读(读取未提交数据):一个事务读到另一个事务还没有提交的数据
不可重复读(多次读取,数据内容不一致):一个事务先后读取同一条记录,但是两次读取的数据不同。这是由于查询时其他事务修改的提交。
幻读(多次读取,数据总量不一致):一个事务按条件查询时,没有对应数据行,但是在插入数据时,又发现了这行数据,好像出现了幻影
丢失更新:两个事务同时读取一条记录,A先修改、B再修改,B提交后覆盖了A的提交。
# 事物的隔离级别
在不同隔离级别下,并发事务问题是否会出现?
隔离级别 | 脏读 | 不可重复读 | 幻读 | |
---|---|---|---|---|
read uncommitted | ✓ | ✓ | ✓ | |
read committed | × | ✓ | ✓ | |
repeatable read(默认) | × | × | ✓ | |
serializable | × | × | × |
read uncommitted:性能最高,数据安全性最差(不使用)
read commited:可以解决脏读,(Oracle和Sql Server默认)
repeatable read:可以解决脏读和不可重复读
serializable:可以解决脏读、不可重复读和幻读,相当于表锁
# 事务隔离级别的作用范围
全局级:对所有会话有效
会话级:只对当前会话有效
查询和设置事务隔离级别:
- 查询全局事务隔离级别
show global variables like '%isolation%';
select @@transaction_isolation;
- 查询会话事务隔离级别
show session variables like '%isolation%';
select @@transaction_isolation;
- 设置全局事务隔离级别
set global transaction isolation level read committed;
- 设置会话事务隔离级别
set session transaction isolation level read committed;
黑马P57