# 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:可以解决脏读、不可重复读和幻读,相当于表锁

# 事务隔离级别的作用范围

全局级:对所有会话有效

会话级:只对当前会话有效

查询和设置事务隔离级别:

  1. 查询全局事务隔离级别
show global variables like '%isolation%';
select @@transaction_isolation;
  1. 查询会话事务隔离级别
show session variables like '%isolation%';
select @@transaction_isolation;
  1. 设置全局事务隔离级别
set global transaction isolation level read committed;
  1. 设置会话事务隔离级别
set session transaction isolation level read committed;

黑马P57

Last Updated: 12/23/2024, 4:18:13 AM