什么是数据库事务
构成单一逻辑工作单元的操作集合
一个典型的数据库事务如下
1 | BEGIN TRANSACTION //事务开始 |
事务四大特性 ACID
不是所有操作都是事务,事务要有一下四个特性
- 原子性(Atomicity)
- 事务作为一个整体被执行,包括对数据库的操作,要么全部被执行, 要么都不执行
- 一致性(Consistency)
- 事务应确保数据库的状态从一个一致状态转变成另一个一致状态。一致状态是数据库中的数据应满足完整性约束
- 隔离性(Isolation)
- 多个事务并发执行时,一个事务的执行不应该影响其他事务的执行
- 永久性(Durability)
- 已被提交的事务对数据库的修改应该永久保存在数据库中
常见并发异常
1、脏读
一个事务读取到另一个事务未提交的数据
事务A | 事务B |
---|---|
- | 开始事务 |
开始事务 | |
- | 查询账户余额为2000元 |
- | 取款1000元,余额被更改为1000元 |
查询账户余额为1000元(产生脏读) | - |
- | 取款操作发生未知错误,事务回滚,余额变更为2000元 |
转入2000元,余额被更改为3000元(脏读的1000+2000) | - |
提交事务 | - |
按照正确逻辑,此时账户余额应该为4000元 | - |
2、不可重复读
前后多次读取,数据内容不一致
事务A | 事务B |
---|---|
开始事务 | - |
第一次查询,小明的年龄为20岁 | - |
- | 开始事务 |
其他操作 | - |
- | 更改小明的年龄为30岁 |
- | 提交事务 |
第二次查询,小明的年龄为30岁 | - |
按照正确逻辑,事务A前后两次读取到的数据应该一致 | - |
3、幻读
前后多次读取,数据总量不一致
事务A | 事务B |
---|---|
开始事务 | - |
第一次查询,数据总量为100条 | - |
- | 开始事务 |
其他操作 | - |
- | 新增100条数据 |
- | 提交事务 |
第二次查询,数据总量为200条 | - |
按照正确逻辑,事务A前后两次读取到的数据应该一致 | - |
不可重复读和幻读 区别
1、不可重复读
读取了其他事务更改的数据,针对insert和update操作
解决:使用行级锁,锁定该行,事务A多次读取操作完毕后才释放,这时候才允许其他事务更改刚才的数据
2、幻读
读取了其他事务新增的数据,针对insert和delete操作
解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放,这时候才允许其他事务新增数据
四大隔离级别
1、读未提交 READ UNCOMMITTED
1 | 1)用户B: |
2、读已提交 READ COMMITTED
SQL Server和Oracle的默认隔离级别
1 | 1)用户B: |
3、可重复读 REPEATABLE READ
MySql的默认隔离级别
1 | 在用户A的事务运行之前,先设定SQL的隔离等级为REPEATABLE READ |
4、串行化 SERIALIZABLE
1 | 在用户A的事务运行之前,先设定SQL的隔离等级为SERIALIZABLE |
这是四个隔离级别中限制最大的级别:一个一个排队执行,执行效率奇差,性能开销也最大,所以应只在必要时才使用该选项。
总结
- | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 可能 | 可能 | 可能 |
读已提交 | 可能 | 可能 | |
可重复读 | 可能 | ||
读已提交 |