2.事务并发处理
1 事务并发处理
a) 事务的四大特性:ACID
- Atomic(原子性) Consistency(一致性) Itegrity(隔离性) Durability(持久性)
b) 事务并发时可能出现的问题:
时间 |
取款事务A |
存款事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
查询账户余额为1000元 |
|
T4 |
|
查询账户余额为1000元 |
T5 |
|
汇入100元把余额改为1100元 |
T6 |
|
提交事务 |
T7 |
取出100元把余额改为900 元 |
|
T8 |
撤销事务 |
|
T9 |
余额恢复为1000元(丢失更新) |
|
第一类丢失更新(Lost Update) (只要数据库支持事务,这类问题一般不会出现)
dirty read脏读(读到了另一个事务在处理中还未提交的数据)
时间 |
取款事务A |
存款事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
|
查询账户余额为1000元 |
T4 |
|
汇入100元把余额改为1100元 |
T5 |
查询账户余额为1100元(读取脏数据) |
|
T6 |
|
回滚 |
T7 |
取款1100 |
|
T8 |
提交事务失败 |
|
non-repeatable read 不可重复读
在事务A的执行过程中,事务B进行了开启,修改和提交,导致事务A在事务B执行前读取的数据和事务B执行后读取的数据不一致
时间 |
取款事务A |
存款事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
查询账户余额为1000元 |
|
T5 |
|
汇入100元把余额改为1100元 |
T5 |
|
提交事务 |
T6 |
查询帐户余额为1100元 |
|
T8 |
提交事务 |
|
second lost update problem 第二类丢失更新(不可重复读的特殊情况)
时间 |
取款事务A |
存款事务B |
T1 |
|
开始事务 |
T2 |
开始事务 |
|
T3 |
|
查询账户余额为1000元 |
T4 |
查询账户余额为1000元 |
|
T5 |
|
取出100元把余额改为900元 |
T6 |
|
提交事务 |
T7 |
汇入100元 |
|
T8 |
提交事务 |
|
T9 |
把余额改为1100元(丢失更新) |
|
phantom read 幻读
和 不可重复读 类似,不过不可重复读针对的列的修改,而幻读针对的是列的增加
时间 |
查询学生事务A |
插入新学生事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
查询学生为10人 |
|
T4 |
|
插入1个学生 |
T5 |
查询学生为11人 |
|
T6 |
|
提交事务 |
T7 |
提交事务 |
MySQL中的事务隔离级别:
1.read-uncommitted(允许读取未提交的数据) 会出现dirty read, phantom-read,non-repeatable read 问题
2.read-commited(读取已提交的数据 项目中一般都使用这个)不会出现dirty read,因为只有另一个事务提交才会读出来结果,但仍然会出现 non-repeatable read 和 phantom-read
使用read-commited机制可用 ‘悲观锁 乐观锁’ 来解决non-repeatable read 和 phantom-read问题
3.repeatable read(事务执行中其他事务无法执行修改或插入操作 较安全) (这是MySQL默认的隔离级别)
4.serializable解决一切问题(顺序执行事务 不并发,实际中很少用)