数据库四大特性ACID
- 原子性atomiticy:事务包含的所有操作,要么全成功,要么全部失败回滚
- 一致性consistency:事务必须使数据库从一个一致性状态变成另一个一致性状态
- 隔离性isolation:在多个用户并发访问数据库时,每个事务不能被其他事务所干扰,并发事务之间应该相互隔离
- 持久性durability:事务一旦提交,数据即永久保存
数据库隔离级别
我们在进行数据库开发时经常会遇到程序事务的相关问题,对于脏读、幻读、不可重复读等问题的处理。
数据库隔离级别以及会出现的问题,如下表格:
隔离级别 | 数据丢失 | 脏读 | 不可重复读 | 幻读 |
读未提交Read uncommitted | No | Yes | Yes | Yes |
读已提交 Read Committed | No | No | Yes | Yes |
可重复读 repeatable Read | No | No | No | Yes |
串行化 serializable | No | No | No | No |
Mysql默认是可重复读
Oracle只支持两种级别,读已提交与串行化,默认为读已提交
- 读未提交:一个线程在写事务的时候,添加一个X锁(排它锁),不允许其他线程事务对其进行操作,但是读不受限制,不加锁;会产生脏读
- 脏读:两个事务,一个事务进行了update操作,但未提交而回滚了,此时另一个事务读取到了未提交的数据,故此出现了脏读
- 示例:
事务A | 事务B |
获取数据D的X锁 读取D的值1 D=D+1 D=2 写数据库
事务出错回滚操作 D=1 释放D的X锁
|
读取D的值 D=2 .........
这个时候B就发生了脏读,B得到的是2 其实数据中D依然等于1 |
- 读已提交:事务写数据的时候添加X锁(排他锁),读数据的时候条件S锁(共享锁);并且有约定一个数据对于X锁S锁只能同时存在一个,但是可以同时存在多个S锁,并且规定读取完毕后,立即释放S锁。但是会产生不可重复读
- 不可重复读:同一个事务两次读取的数据不一致,即A事务读取了某个数据后,B事务将数据update了并提交,而A事务再次读取的时候,读到的是B事务修改后的结果,出现了两次读取不一样的情况
- 示例
事务A | 事务B |
获取D的S锁 读取D的值1 D=1 释放D的S锁 .............
再次获取D的S锁 读取D的值2 释放D的S锁 此时D=2
由此就出现了不可重复读 两次读取的数据不一样
| 获取D的X锁 读取D的值2 对其进行修改 D=D+1 释放D的X锁 D=2
|
- 可重复读:对S锁进行修改,由读取完数据后立即释放锁,改成知道事务要准备提交了才释放锁,对于X锁还是保持不变。但是会出现幻读
- 幻读:一个事务对某些数据进行了update,提交了,但是此时另一个事务又insert了一条类似的数据,当第一个事务在此查询的时候,发现还有一条记录没有update,即为幻读
- 示例
事务A | 事务B |
获取D的X锁 读取到所有姓王的记录 修改所有姓王的人的成绩为60分 提交事务 释放D的X锁 此时D数据的年龄全部加了1 .............
获取D的S锁 读取D的数据 释放D的S锁 此时发现怎么还有一条姓王的人 的成绩不是60分 难道我出现幻觉了?
| 新增一条D数据也姓王成绩为50分 提交事务 |
- 串行化:事务只能一件一件的进行,不能并行处理