文章目录
1. 什么是事务?
事务是数据操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作。
事务是一组不可在分割的操作集合(工作逻辑单元)。
1.1 典型事务场景
以转账为例:
update user_account set balance = balance - 1000 where user_id = 3;
1.2 如何开启事务
-
mysql 中开启事务
begin/start transaction; commint/rollback; set session autocommit = on/off;
-
jdbc 编程开启事务
connection.setAutoCommit(false)
2. 事务 ACID 特性
-
原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
-
一致性(Consistency)
事务前后数据的完整性必须保持一致。
-
隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
-
持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响。
2.1 原子性(Atomicity)
针对同一个事务
这个果汁包含两个步骤:
- A:
800 -200 = 600
- B:
200 + 200 = 400
原子性表示这两个步骤一起成功,或者一起失败,不能只发生其中一个动作。
2.2 一致性(Consistency)
针对一个事务操作前后的状态一致
-
操作前
A:800,B:200
-
操作后
A:600,B:400
一致性表示事务完成后,符合逻辑运算。
2.3 隔离性(Isolation)
针对多个用户同时操作,主要是排除其他事务对本次事务的影响。
两个事务同时进行,其中一个事务读取到另外一个事务还没有提交的数据,B
2.4 持久性(Durability)
表示事务结束后的数据不随着外界原因导致数据丢失。
操作前
A:800,B:200
操作后
A:600,B:400
如果在操作前(事务还没有提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
A:800,B:200
如果在操作后(事务已经提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
A:600,B:400
3. 事务并发带来的问题
3.1 脏读
指一个事务读取了另外一个事务未提交的数据。
事务 A 读取了事务 B 未提交的事务,输出结果为:18。
3.2 不可重复读
在一个事务内读取表中的某一行数据,多次读取结果不同。
在事务 B 的执行过程中,事务 A 多次读取结果不一样。
3.3 幻读
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
4. 事务隔离级别设置
4.1 数据库设置事务隔离级别
设置事务隔离级别
--读 未提交
set TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
--读 已提交
set TRANSACTION ISOLATION LEVEL READ COMMITTED;
--可重复读
set TRANSACTION ISOLATION LEVEL REPEATABLE READ;
--序列化(串行化)
set TRANSACTION ISOLATION LEVEL SERIALIZABLE;
查询当前事务隔离级别
select @@tx_isolation
4.2 java 代码设置事务隔离级别
适当的 Connection 方法,比如 setAutoCommit
或 setTransactionIsolation
设置 | 描述 |
---|---|
TRANSACTION_SERIALIZABLE | 指示不可以发生脏读、不可重复读和虚读的常量。 |
TRANSACTION_REPEATABLE_READ | 指示不可以发生脏读和不可重复读的常量;虚读可以发生。 |
TRANSACTION_READ_UNCOMMITTED | 指示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量。 |
TRANSACTION_READ_COMMITTED | 指示不可以发生脏读的常量;不可重复读和虚读可以发生。 |
5. Innodb 引擎对事务隔离级别的支持
隔离级别到底是如何实现的呢?下一节我们通过分析 mysql 的锁和 MVCC 机制来讲解。