MYSQL之事务篇
事务概述
在引入事务之前我们先考虑银行转账的操作:
# 从id=1的账户给id=2的账户转账100元
# 第一步:将id=1的A账户余额减去100
UPDATE accounts SET balance = balance- 100 WHERE id = 1;
#第二步:将id=2的B账户余额加上100
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
上边的两个SQL语句必须全部执行,或者由于某种原因第一条语句执行成功而第二条语句执行失败时,第一条语句必须被撤销。我们把多条语句作为一个整体进行操作的功能称为数据库事务
。把撤销指定SQL语句的过程称为回退
。数据库事务可以保证事务范围内的所有操作都可以全部成功或者全部失败。
一般来讲事务有ACID
四个特性:
- A:Atomic,原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;
- C:Consistent,一致性,事务完成后,所有数据的状态都是一致的,即A账户只要减去了100,B账户则必定加上了100;
- I:Isolation,隔离性,如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离;
- D:Duration,持久性,即事务完成后,对数据库数据的修改被持久化存储。
对于单条SQL语句来说,数据库系统会自动的将其作为原子工作单元执行,要么全执行,要么全部执行,这种事务我们称之为隐式事务
。
当然我们也可以手动将多条SQL语句作为一个事务来执行,这种事务我们称之为显示事务
,其一般格式如下:
#使用BEGIN开启一个事务,即试图把事务内的所有SQL所做的修改永久保存。
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
#使用COMMIT提交一个事务
BEGIN;UPDATE accounts SET balance = balance - 100 WHERE id = 1;UPDATE accounts SET balance = balance + 100 WHERE id = 2;COMMIT;
COMMIT;
事务隔离级别
Isolation Level | 脏读(Dirty Read) | 不可重复读(Non Repeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
Read Uncommitted | yes | yes | yes |
Read Committed | - | yes | yes |
Repeatable Read | - | - | yes |
Serializable | - | - | - |
Read Uncommitted
Read Uncommitted
是隔离级别最低的一种事务级别。在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据,这就是脏读(Dirty Read)。
Read Committed
在Read Committed
隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。
不可重复读
是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。
Repeatable Read
在Repeatable Read
隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。
幻读
是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。
Serializable
Serializable
是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。
虽然Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用Serializable隔离级别。