MySQL-事务(四)
1. 前言
本文主要分为三个部分:
- 第一个部分为
MySQL
事务的特性;- 第二个部分为
MySQL
事务的隔离级别;- 第三个部分为
MySQL
常见锁机制;- 第四个部分为具体的实践案例。
2. 💡问题思考
MySQL
事务是什么?MySQL
事务是指一组SQL
语句,它们被当成一个单独的工作单元, 要么全部执行成功,要么全部不执行。
1
2
3
4
5
6
7假设你有一个银行账户,你要向另一个账户转账 1000 元。
这个操作涉及到两个 SQL 语句:一个是从你的账户扣除 1000 元,另一个是给对方的账户增加 1000 元。
如果你不使用事务,那么可能会出现以下情况:
1. 第一个 SQL 语句执行成功,但是第二个 SQL 语句执行失败,导致你的钱少了 1000 元,但是对方没有收到。
2. 第一个 SQL 语句执行失败,但是第二个 SQL 语句执行成功,导致你的钱没有变化,但是对方多了 1000 元。
3. 第一个 SQL 语句执行成功,但是在第二个 SQL 语句执行之前,有其他人查询了你或对方的账户余额,看到了不正确的数据。
这些情况都会造成数据的不一致和不完整。如果你使用事务,那么你可以保证两个 SQL 语句要么都执行成功,要么都不执行。MySQL
事务解决了什么问题?针对上诉问题,事务最少是需要满足一致性和隔离性。
脏读:一个事务读取了另一个事务未提交的数据,不符合一致性。
- 不可重复读:一个事务读取了另一个事务已经提交的
update
操作的数据,导致前后两次查询结果不一致,不符合隔离性 - 幻读:一个事务读取了另一个事务已经提交的 insert 操作的数据,导致前后两次查询结果不一致,不符合隔离性。
MySQL
事务隔离级别是什么?MySQL
的事务隔离级别是指在多个事务并发运行时,互相是如何隔离的,从而来避免一些事务并发运行时产生的问题。SQL
标准中规定了四种事务隔离级别:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable
)。
1
2
3
4
5
6假设有两个人 A 和 B,他们都要从银行取钱。
A 先开始取钱,他将银行卡中的余额从 1000 元改为 800 元,但是还没有完成取钱。此时,B 开始取钱,他需要查询银行卡中的余额。
如果 B 的隔离级别是读未提交,则 B 可以读取到 A 修改后的余额 800 元;
如果 B 的隔离级别是读已提交,则 B 只能读取到 A 修改前的余额 1000 元;
如果 B 的隔离级别是可重复读,则 B 只能读取到 A 修改前的余额 1000 元;
如果 B 的隔离级别是串行化,则 B 必须等待 A 完成取钱后才能开始查询。
3. 事务特性
事务是由一组
SQL
语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的 ACID 属性。
- 原子性(Atomicity) :事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
- 一致性(Consistent) :在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性。
- 隔离性(Isolation) :数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
- 持久性(Durable) :事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
4. 事务隔离级别
从问题思考中,我们知道事务的隔离级别主要分为以下四类:
- 读未提交(Read Uncommitted)
- 读已提交(Read Committed)
- 可重复读(Repeatable Read)
- 串行化(
Serializable
)而事务隔离级别主要解决了以下主要的三个问题:
- 脏读
- 不可重复读
- 幻读
Mysql
默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认用Mysql
设置的隔离级别,如果Spring
设置了就用已经设置的隔离级别
- 脏读、不可重复读 和 幻读,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
读未提交(Read uncommitted) | 可能 | 可能 | 可能 |
读已提交(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatableread) | 不可能 | 不可能 | 可能 |
可串行化(Serializable) | 不可能 | 不可能 | 不可能 |
- 查看当前数据库的事务隔离级别:
1 | show variables like 'tx_isolation'; |
- 设置事务隔离级别:
1 | set tx_isolation='REPEATABLE-READ'; |
5. 锁
锁的本质是解决了 计算机协调多个进程或线程并发访问某一资源的机制。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Wickson Blog!
评论