1. MySQL 事务的四大特性
2. MySQL 事务的并发问题
3. MySQL 事务的隔离级别
---------------------------------------------------------
1. MySQL 事务的四大特性
MySQL 事务具有四个特性:原子性、一致性、隔离性、持久性,这四个特性简称 ACID 特性
一、原子性(Atomicity ):一个事务是一个不可再分割的整体,要么全部成功,要么全部失败
事务在数据库中就是一个基本的工作单位,事务中包含的逻辑操作(SQL 语句),只有两种情况:成功和失败。事务的原子性其实指的就是这个逻辑操作过程具有原子性,不会出现有的逻辑操作成功,有的逻辑操作失败这种情况
二、一致性(Consistency ):一个事务可以让数据从一种一致状态切换到另一种一致性状态
举例说明:张三给李四转账 100 元,那么张三的余额应减少 100 元,李四的余额应增加 100 元,张三的余额减少和李四的余额增加这是两个逻辑操作具有一致性
三、隔离性(Isolution ):一个事务不受其他事务的影响,并且多个事务彼此隔离
一个事务内部的操作及使用的数据,对并发的其他事务是隔离的,并发执行的各个事务之间不会互相干扰
四、持久性(Durability ):一个事务一旦被提交,在数据库中的改变就是永久的,提交后就不能再回滚
一个事务被提交后,在数据库中的改变就是永久的,即使系统崩溃重新启动数据库数据也不会发生改变
2. MySQL 事务的并发问题
上面讲到了事务的隔离性,当有多个任务时,应当让多个事务同时执行,这就是事务的并发。既然事务存在并发执行,那必然存在两个事务操作同一个数据的冲突问题,那么我们来看一下会出现哪些问题
下面介绍脏读、不可重复读、幻读时会涉及到事务隔离级别,可先略过。按照提示设置事务隔离级别即可,本文后面会介绍事务隔离级别。测试这几个事务并发问题可以通过打开两个终端窗口进行测试
查看事务隔离级别
select @@transaction_isolation;
一、脏读
测试脏读: 将事务隔离级别修改为读未提交
# READ-UNCOMMITTED 读未提交
set session transaction isolation level read uncommitted;
现在有两个事务,分别是事务 A 和事务 B。在事务 A 中查询一条数据,查询结果中 score 的值是 80,然后事务 B 去修改这一条数据,将 score 的值改为 90,但是它没有提交,这时候事务 A 去查询这条数据,发现数据竟然发生了变化。
脏读: 在一个事务里面,由于其他事务修改了数据并且没有提交,而导致前后两次读取的数据不一致的情况,这种事务并发问题称之为 “脏读”
二、不可重复读
测试不可重复读: 将事务隔离级别修改为读已提交
# READ-COMMITTED 读已提交
set session transaction isolation level read committed;
同样是两个事务,事务 A 查询一条数据,事务 B 修改了这条数据,特别注意,这里事务 B 执行了提交,但是事务 A 还没有提交或回滚,这种事务并发问题称为不可重复读
不可重复读: 一个事务读取到其他事务已提交的数据导致前后两次读取数据不一样的情况
三、幻读
测试可重复读: 将事务隔离级别修改为可重复读
# REPEATABLE-READ 可重复读(默认的事务隔离级别)
set session transaction isolation level repeatable read;
幻读: 一个事务前后两次读取的数据不一致,是因为其他事务插入数据导致的事务并发情况
3. MySQL 事务的隔离级别
MySQL 事务有四种隔离级别,如下所示,表格中的 “是” 代表存在这个问题,“否” 代表没有这个问题
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted(读未提交) | 是 | 是 | 是 |
Read committed(读已提交) | 否 | 是 | 是 |
Repeatable read(可重复读,默认的隔离级别) | 否 | 否 | 是 |
Serializable(可串行化) | 否 | 否 | 否 |
查看事务隔离级别
# 查看全局事务隔离级别
select @@global.tx_isolation;
# 查看会话事务隔离级别(也就是当前窗口)
select @@tx_isolation;
select @@transaction_isolation;
设置事务隔离级别
# 读未提交
set session transaction isolation level read uncommitted;
# 读已提交
set session transaction isolation level read committed;
# 可重复读(默认隔离级别)
set session transaction isolation level repeatable read;
# 可串行化
set session transaction isolation level serializable;
总结:
MySQL 的默认隔离级别是可重复读,不是读已提交
隔离性从低到高分别是:读未提交、读已提交、可重复读、可串行化
并发性跟隔离性恰好相反,从低到高是:可串行化、可重复读、读已提交、读未提交
这也非常好理解,隔离性越高,说明锁的粒度越细,并发性自然就会降低