阅读 55

事务管理之隔离级别

这是我参与8月更文挑战的第8,活动详情查看:8月更文挑战

1 隔离级别引入

​ 并发访问,可能导致,脏读,不可重复读,幻读问题.

1 并发访问

​ 是指在同一个时间段,有多个用户开启了事务,并且同时访问同一张表中记录,称为事务的并发访问。也就是多个事务在并行的执行。

​ 在理想状态,事务的操作是不存在并发访问问题的. 在实际的使用过程中,因为事务的隔离级别不同,可能导致出现上述三种并发访问问题.

2 并发访问引出问题

并发访问的问题含义
脏读一个事务读取到了另一个事务没有提交的数据
不可重复读正常来说,一个事务多次读取同一条记录结果应该是一致的, 如果出现多次读取不一致的情况,称为不可重复读。通常是 因为一个事务在读取数据,另一个读取更新了这条记录导致。
幻读一个事务在统计或查询的时候,2次出现查询的记录数不同。 通常是因为一个事务在统计,另一个事务插入或删除了记录导致。

​ 上述三种并发访问问题,可以通过设置事务隔离级别去控制.隔离级别越高,并发出现的问题就越少。

2 四种隔离级别

级别名称隔离级别脏读不可重复读幻读数据库默认级别
1读未提交read uncommitted
2读已提交read committedOracle和Sql Server
3可重复读repeatable readMysql
4串行化serializable

说明:

  • 1 Read uncommitted (读未提交): 隔离级别最低,三种并发访问的问题都是存在
  • 2 Read committed (读已提交):解决了脏读的问题,Oracle和SQL Server默认是这种隔离级别
  • 3 Repeatable read (可重复读):这是MySQL默认的隔离级别,可以解决脏读和不可重复读的问题
  • 4 Serializable (串行化):所有的事务都有串行的方式执行,不存在并发的事务

ps:

​ 隔离级别越高:安全性越高,性能就越低

3 案列

命令说明
select @@tx_isolation查询事务隔离级别
set global transaction isolation level 隔离级别设置全局事务隔离级别

隔离级别:

  • read uncommitted
  • read committed
  • repeatable read
  • serializable

1 脏读

一个事务读取到另一个事务未提交的数据,解决方法就是提高事务的隔离级别为read committed.

1 案例说明

1 准备数据

-- 给虹猫和蓝兔金额设置为1000
update account set balance = 1000;
复制代码

2 操作步骤

1 设置全局的隔离级别为最低

2 开启事务

3 更新账户余额, 虹猫减100 ,蓝兔加100

4 用一个新的命令行查看蓝兔的金额,钱已到账

5 回滚更新账户余额操作

6 用蓝兔命令行查询,钱恢复原样

-- 1 设置隔离级别
set global transaction isolation level read uncommitted; 

-- 2 开启事务
start transaction;

-- 3 更新账户余额
update account set balance=balance-100 where name='hm';
update account set balance=balance+100 where name='lt';

 -- 4 使用 另新命令行, 切换到自己的库,本人使用test库
 use test;
 select * from account;
 
 -- 5 回滚
 rollback;
 
 -- 6 使用新命令行,查询数据
  select * from account;
复制代码

解决上述问题方法: 将全局的隔离级别进行提升

-- 1 设置隔离级别为 可重复读
set global transaction isolation level read committed; 

-- 2 重复上述操作 虹猫账号没有变化
复制代码

2 不可重复读

一个事务多次读取的数据不同,导致无法判断数据的正确性.

1 设置全局的隔离级别为读已提交

2 开启事务

3 在虹猫命令行查询虹猫余额

4 在新命令行,开启事务,给虹猫加100元钱,提交事务.

5 在虹猫命令行,再次查询虹余额,发现金额增加了100

6 虹猫命令行提交事务

-- 1 设置隔离级别
set global transaction isolation level read committed; 

-- 2 虹猫命令行
start transaction;
select * from account where name='hm'; 

-- 3 新命令行
use test;
start transaction;
update account set balance=balance+100 where name='hm';
commit;

-- 4 虹猫命令行
select * from account where name='hm'; 

-- 5 虹猫命令行提交事务
commit;
复制代码

解决方法:将全局的隔离级别进行提升

-- 1 设置隔离级别为 可重复读
set global transaction isolation level repeatable read; 

-- 2 重复上述操作 虹猫账号没有变化
复制代码

3 幻读

一个事务多次统计数据,得到数据条数不同,无法判断数据正确性.

如虹猫金额大于1000,蓝兔金额小于1000. 现在需要统计金额大于1000的人员. 第一个事务查询到的是虹猫, 第二个事务,给蓝兔增加了超过1000的钱,第一个事务再查询时,发现金额大于1000的人员变成两个了.

1 设置全局的隔离级别为可重复读

2 开启事务

3 在虹猫命令行查询余额大于1000的数量

4 在新命令行,开启事务,给蓝兔加1000元钱,提交事务.

5 在虹猫命令行,再次查询余额大于1000的数量,数量变化了

6 虹猫命令行提交事务

-- 1 设置隔离级别
set global transaction isolation level repeatable read; 

-- 2 虹猫命令行
start transaction;
select count(id) from account where banlance > 1000; 

-- 3 新命令行
use test;
start transaction;
update account set balance=balance+1000 where name='lt';
commit;

-- 4 虹猫命令行
select count(id) from account where banlance > 1000; 

-- 5 虹猫命令行提交事务
commit;
复制代码

解决方法: 提高隔离级别serializable

-- 1 设置隔离级别为 串行化
set global transaction isolation level serializable; 

-- 2 重复上述操作 统计数据没有变化
复制代码
文章分类
后端
文章标签