数据库锁
数据库事务的四大特性
ACID
- A(atomicity)
原子性
事务中的操作要么都执行,要么都不执行. - C(consistency)
一致性
事务只能将数据库从一个正确的状态转化为另一个正确的状态.例如银行的数据库中不论如何转账,应该保证所有人总钱数使固定的. - I(isolation)
隔离性
隔离性是指数据库允许多个并发事务同时对数据进行读写和修改的能力. 隔离性可以分为四种级别- read-uncommited(未提交读)
- read-commited(提交读)
- repeatable-read(可重复读)
- serializable(串行化)
- D(durability)
持久性
数据库并发访问产生的问题和数据库的隔离级别
数据库并发访问产生的问题
- 更新丢失
- 脏读
- 不可重复读
- 幻读
更新丢失
事务1 | 事务2 |
---|---|
开始事务 | |
开始事务 | |
read a = 100 | |
read a = 100 | |
a = a - 10 (a = 90) | |
提交 | |
a = a - 10 (a = 90) | |
提交 | |
造成更新丢失(此处应该为80) |
多个事务同时对一个数据进行更新,最终造成一部分事务的更新丢失.
脏读
事务1 | 事务2 |
---|---|
开始事务 | |
开始事务 | |
read a = 100 | |
a = a - 10 (a = 90) | |
read a = 90 | |
回滚 | |
读到脏数据 |
一个事务读到了另一个事务修改之后的数据,但是之后后者进行了回滚,因此读到了脏数据.
不可重复读
事务1 | 事务2 |
---|---|
开始事务 | |
开始事务 | |
read a = 100 | |
read a = 100 | |
a = a - 10 (a = 90) | |
read a = 90 | |
造成不可重复读 |
在一个事务两次查询数据的过程中另一个事务更新了数据,造成了为进行任何写操作的事务两次读取到了不一样的数据.
幻读
例子1
事务1 | 事务2 |
---|---|
开始事务 | |
开始事务 | |
查询得知数据库中有3条数据 | |
向数据库中添加一条数据 | |
将所有行的指定列加1 | |
最终修改的行数为4造成了幻读 |
例子2
事务1 | 事务2 |
---|---|
开始事务 | |
开始事务 | |
查询得知没有id为1的数据 | |
添加一条id为1的数据 | |
尝试添加id为1的数据(插入失败) | |
最初查询结果为0条,第2次查询的结果为1条,造成幻读 |
定义
一个事务读取两次,得到的记录条数不一致
事务的隔离级别
隔离级别 | 更新丢失 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
未提交读 | 不允许出现 | 允许出现 | 允许出现 | 允许出现 |
提交读 | 不允许出现 | 不允许出现 | 允许出现 | 允许出现 |
可重复读 | 不允许出现 | 不允许出现 | 不允许出现 | 允许出现 |
串行化 | 不允许出现 | 不允许出现 | 不允许出现 | 不允许出现 |
未提交读
在该隔离级别下会出现脏读,大部分情况下不允许脏读,但是这种模式数据库的并发是最好的
提交读
这种模式是Oracle和SQL server的默认隔离级别
可重复读
可重复读是MySQL的默认隔离级别.这种隔离级别但是可能会造成幻读,MySQL的InnoDB引擎可以通过next-key locks机制来避免幻读.
串行化
串行调度
:不允许事务并发执行,事务一个接一个串行执行.
可串行化调度
:如果存在调度S,对于数据库的任何状态,该调度的执行结果等于一个串行调度的执行结果,则称该调度为可串行化调度
.
该级别下可以解决幻读的问题,但是对并发的支持相对较差.