Mysql学习笔记之事务
1.简介
事务是指数据库在执行一组操作时,要么全部成功,要么全部失败,以保证数据的一致性和完整性。
例如在转账场景中,从A账户扣除了多少钱,B账户就应该增加多少钱,若更新B账户数据失败,而A账户已经发生了扣除就会存在严重问题,开启事务就可以在更新B账户失败时可以回滚对A账户的操作。
2.事务特性
事务有四个特性,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
-
原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
-
一致性:事务完成时,必须使所有的数据都保持一致状态。
这里所说的一致性不是表示事务执行前后的数据保持一致,而是指在事务执行过程中所插入的数据都必须满足数据库的预设条件,换句话说,数据必须保证是正确的才能被插入或修改 -
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。隔离可以分为四种隔离级别,后文会介绍
-
持久性:事务处理结束后,对数据的修改就是永久的。
3.事务控制
默认情况下,MySQL的事务是自动提交的,当执行完一条DML语句时,MySQL会立即隐
式的提交事务。
当然也可以手动提交事务,有两种方式可以设置手动提交事务。
3.1 修改设置
查看当前提交方式SELECT @@autocommit
1表示自动提交;0表示手动提交,通过SET @@autocommit = 0
修改提交方式,sql执行完成后通过COMMIT
提交事务,通过ROLLBACK
回滚事务
3.2 通过sql语句开启事务
-- 开始事务
START TRANSACTION
-- 或者
BEGIN
--提交事务
COMMIT
--回滚事务
ROLLBACK
4.并发事务问题
4.1 脏读
一个事务读取了另一个未提交事务修改过的数据。若该未提交事务最终回滚,则读取到的数据是无效的,这种数据不一致性问题称为脏读。
事务A 事务B
| |
|-- UPDATE table (未提交) -->|
| |-- SELECT table (读到脏数据)
|-- ROLLBACK ----------------->|
| |-- 使用无效数据(导致错误)
当事务A更新了表中的数据,但并为提交,此时事务B查询表中数据,就可能会读取到事务A未提交的数据,若事务A执行了回滚操作,就会导致使用错误数据
4.2 不可重复读
一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
事务A 事务B
| |
|--- SELECT → 1000 |
| |--- UPDATE → 800
| |--- COMMIT
|--- SELECT → 800 |
事务A在两次查询工程中,事务B修改了数据并提交,导致事务A两次查询结果不一致
4.3 幻读
一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据
已经存在
事务A 事务B
| |
|--- SELECT [id = 1] |
| |--- INSERT id = 2
| |--- COMMIT
|--- INSERT id = 2 (error) |
事务A在查询时不存在id = 2的数据,但在插入之前事务B插入了id = 2的数据,此时事务A在插入id = 2的数据就会产生错误
5.事务隔离级别
为了解决并发事务所引发的问题,在数据库中引入了事务隔离级别。主要有以下几种:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable Read(默认) | × | × | √ |
Serializable | × | × | × |
√表示存在可能性,X表示不存在可能性
5.1 修改事务隔离级别
1.查看当前事务隔离级别
SELECT @@TRANSACTION_ISOLATION;
2.修改隔离级别
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL [ READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE ]
-- SESSION 表示当前会话 GLOBAL 表示全局,修改全局时需要重启服务-- 1.修改当前会话的隔离级别为Read uncommitted
SET SESSION TRANSACTION ISOLATION LEVEL UNCOMMITTED READ;
-- 2.修改当前会话的隔离级别为Serializable
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 2.修改全局的隔离级别为Serializable
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
注意:事务隔离级别越高,数据越安全,但是性能越低。