


专栏:MySQL数据库成长记
个人主页:手握风云
目录
[1.1. 什么是隔离性](#1.1. 什么是隔离性)
[1.2. 隔离级别](#1.2. 隔离级别)
[1.3. 不同隔离级别存在的问题](#1.3. 不同隔离级别存在的问题)
[1.3.1. READ UNCOMMITTED------读未提交](#1.3.1. READ UNCOMMITTED——读未提交)
[1.3.2. READ COMMITTED------读已提交](#1.3.2. READ COMMITTED——读已提交)
[1.3.3. REPEATABLE READ------可重复读](#1.3.3. REPEATABLE READ——可重复读)
[1.3.4. SERIALIZABLE------串行化](#1.3.4. SERIALIZABLE——串行化)
[1.4. 不同隔离级别的性能与安全](#1.4. 不同隔离级别的性能与安全)
[1.5. 查看和设置隔离级别](#1.5. 查看和设置隔离级别)
一、事务的隔离性和隔离级别
1.1. 什么是隔离性
MySOL服务可以同时被多个客户端访问,每个客户端执行的DML语句以事务为基本单位,那么不同的客户端在对同一张表中的同一条数据进行修改的时候就可能出现相互影响的情况,为了保证不同的事务之间在执行的过程中不受影响,那么事务之间就需要要相互隔离,这种特性就是隔离性。
1.2. 隔离级别
事务具有隔离性,那么如何实现事务之间的隔离?隔离到什么程度?如何保证数据安全的同时也要兼顾性能?
事务间不同程度的隔离,称为事务的隔离级别;不同的隔离级别在性能和安全方面做了取舍,有的隔离级别注重并发性,有的注重安全性,有的则是并发和安全适中;在MySQL的InnoDB引擎中事务的隔离级别有四种,分别是:
- READ UNCOMMITTED,读未提交。
- READ COMMITTED,读已提交。
- REPEATABLE READ,可重复读。
- SERIALIZABLE,串行化。
1.3. 不同隔离级别存在的问题
1.3.1. READ UNCOMMITTED------读未提交
事务A对数据进行了修改,事务B可以访问到事务A还没有提交的数据(也就是可能发生回滚),这个现象叫做"脏读"。
1.3.2. READ COMMITTED------读已提交
在工作中,程序员需要经常使用git提交项目,如果其他同事在查看的过程中,上传者对其进行了修改。事务A在一个事务对同一条记录查询了两次,在两次查询之间事务B对数据进行了修改并提交了事务,那么事务A就会查询到两条不同的结果,这种现象就是"不可重复读"。
1.3.3. REPEATABLE READ------可重复读
当一个程序员在去修改项目时,突然领导说先不要上传,看完之后再改,这个过程就相当于加了一把锁。但是程序员还可以对其他文件进行修改(增、删),导致仓库中的文件列表不一样,那么领导第一次查询的列表内容与第二次查询到的列表内容不一致。务A第一次查询到的结果集)与第二次查询到的结果集不一致,这个现象叫"幻读"。
在Innodb存储引擎中,使用了next-key锁,锁住了目标行与之前的间隙,解决了部分的幻读问题。
1.3.4. SERIALIZABLE------串行化
可以解决所有的数据安全问题,所有的事务是一个接一个的执行,一个事务必须要等到上一个事务执行完成之后才执行。
1.4. 不同隔离级别的性能与安全
|------------------------|------|-----------|---------------|-------------------------------------|
| 隔离级别(Isolation Level) | 并发性能 | 隔离力度(安全性) | 解决的问题 | 存在的问题 |
| READ UNCOMMITTED(读未提交) | 最高 | 最低 | 无(不解决任何并发问题) | 存在脏读、不可重复读、幻读 |
| READ COMMITTED(读已提交) | 较高 | 较低 | 解决脏读 | 存在不可重复读、幻读 |
| REPEATABLE READ(可重复读) | 中等 | 较高 | 解决脏读、不可重复读 | (InnoDB 中通过 Next-Key 锁大幅缓解幻读,基本无幻读) |
| SERIALIZABLE(串行化) | 最低 | 最高 | 解决脏读、不可重复读、幻读 | 无(完全避免并发问题) |
并发性能 指数据库同时处理多个事务的能力,串行化因强制事务排队执行,性能最差。**隔离力度(安全性)**指事务间相互隔离、避免数据不一致的能力,行化因完全隔绝并发,安全性最高。
1.5. 查看和设置隔离级别
- 事务的隔离级别分为全局作用域和会话作用域,全局作用域下的事务隔离级别设置会影响后续所有新启动的数据库连接和事务。会话作用域仅对当前数据库会话(即一个客户端与数据库建立的连接期间)内的事务有效。
sql
-- 全局作用域
SELECT @@GLOBAL.transaction_isolation;
-- 会话作用域
SELECT @@SESSION.transaction_isolation;


- 设置事务的隔离级别和访问模式
sql
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level|access_mode;
方括号 []
内为可选参数 ,不指定时默认作用于 "下一个事务"(仅对后续第一个事务生效,之后恢复原有设置)。level
:表示事务隔离级别(必选,需从指定选项中选择)。access_mode
:表示事务访问模式(可选,控制事务是否允许读写操作)。
sql
-- 1. 设置全局隔离级别为"串行化"(影响后续所有新连接,不影响当前事务)
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 2. 设置会话隔离级别为"串行化"(影响当前会话后续所有事务,不影响其他会话)
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 3. 设置"仅下一个事务"的隔离级别为"串行化"(临时生效,后续事务恢复原级别)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
sql
-- 1. 方式一:直接赋值给transaction_isolation变量
-- 设置全局隔离级别为"串行化"
SET GLOBAL transaction_isolation = 'SERIALIZABLE';
-- 设置会话隔离级别为"可重复读"(空格替换为"-",即REPEATABLE-READ)
SET SESSION transaction_isolation = 'REPEATABLE-READ';
-- 2. 方式二:通过@@变量名赋值
-- 设置全局隔离级别为"串行化"
SET @@GLOBAL.transaction_isolation = 'SERIALIZABLE';
-- 设置会话隔离级别为"可重复读"(空格替换为"-")
SET @@SESSION.transaction_isolation = 'REPEATABLE-READ';