- 事务的ACID属性
- 5种状态
- 隔离级
- 事务隔离性中出现的几种问题
- 不同数据库支持的隔离级别
事务
在数据库中事务是工作的逻辑单元,一个事务由一个或多个完成相关行为的SQL语句组成,通过事务机制保证这一组SQL语句所做的操作要么全部执行执行成功,要不全部不执行
事务的ACID属性
-
原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 -
一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
- 比如:转账,假设用户A和用户B两者的钱加在一起是1000元,那么不管A和B之间如何转账,转几次帐。事务结束后两个用户的钱加在一起还得是1000
-
隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,即并发执行的各个事务之间不能互相干扰。 -
持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
5种状态
-
活动状态(active)
事务在执行时的状态叫活动状态。 -
部分提交状态(Partial Committed)
事务中最后一条语句被执行后的状态叫部分提交状态。 -
失败状态(Failed Committed)
事务不能正常执行的状态叫失败状态。 -
提交状态(Committed)
事务在部分提交后,将往硬盘上写入数据,当最后一条信息写入后的状态叫提交状态。进入提交状态的事务就成功完成了。 -
中止状态(Aborted)
事务回滚并且数据库已经恢复到事务开始执行前的状态叫中止状态。
隔离级别
于是数据库定义了4种隔离级:
ANSI/ISO SQ92标准:
隔离级别 | 描述 |
---|---|
READ UNCOMMITTED(读未提交数据) | 允许事务读取未被其他事务提交的变更,脏读、不可重复读和幻读的问题都会出现 |
READ COMMITED(读已提交数据) | 只允许事务读取已经被其他事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然会出现 |
REPEATABLE READ(可重复读) | 确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读,但幻读的问题\依然存在 |
SERIALIZABLE(串行化) | 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可以避免,但性能十分低 |
以及其分别可能出现的问题,级别越高其效率也就越低
隔离级别 | 脏读 | 不可重复度 | 幻读 |
---|---|---|---|
read uncommitted | ✓ \checkmark ✓ | ✓ \checkmark ✓ | ✓ \checkmark ✓ |
read Committed | X | ✓ \checkmark ✓ | ✓ \checkmark ✓ |
repeatable read | X | X | ✓ \checkmark ✓ |
serializable | X | X | X |
事务隔离性中出现的几种问题
对于不同的隔离级别有不同的隔离问题:
-
脏读: 是指一个事务处理过程读取了另一个未提交事务中的数据 。
即当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。 -
不可重复读:是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
例如,事务A在读取某一数据,而事务B立马修改了这个数据并且提交事务给数据库,事务A再次读取该数据就得到了不同的结果,发生了不可重复读。
注 : 不 可 重 复 读 和 脏 读 的 区 别 是 , 脏 读 是 某 一 事 务 读 取 了 另 一 个 事 务 未 提 交 的 脏 数 据 , 而 不 可 重 复 读 则 是 读 取 了 前 一 事 务 提 交 的 数 据 。 \textcolor{Red}{注:不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交\\的脏数据,而不可重复读则是读取了前一事务提交的数据。 } 注:不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
- 幻读:是指在两个连续的查找之间一个并发的修改事务修改了查询的数据集,导致这两个查询返回了不同的结果。是事务非独立执行时发生的一种现象。
例如事务A,对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务B又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务A的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务B中添加的,就好像产生幻觉一样,这就是发生了幻读。
又或者事务A和事务B:
事务B查询表中的数据特定条件的数据,刚查完所有满足的记录,此时事务A有添加了几条满足条件的记录,并提交的事务,如果事务B再次查询,就会查询出比上次更多的结果。
幻 读 和 不 可 重 复 读 都 是 读 取 了 另 一 条 已 经 提 交 的 事 务 ( 这 点 就 与 脏 读 不 同 ) , 所 不 同 的 是 不 可 重 复 读 查 询 的 都 是 同 一 个 数 据 项 , 而 幻 读 针 对 的 是 一 批 数 据 整 体 ( 比 如 数 据 的 个 数 ) 。 \textcolor{Red}{ 幻读和不可重复读都是读取了另一条已经提交的事务(这点就与脏读不\\同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(\\比如数据的个数)。} 幻读和不可重复读都是读取了另一条已经提交的事务(这点就与脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
不同数据库支持的隔离级别
- 对于Oracle支持的隔离级别:
ORACE提供了SQ92标准中的read committed和seriaizabe,同时提供了非SQ92标准的read-ony。默认级别是read committed。
注 : s e r i a l i z a b l e 仅 仅 能 看 见 在 本 事 务 开 始 前 由 其 它 事 务 提 交 的 更 改 和 在 本 事 务 中 所 做 的 更 改 . r e a d − o n l y 仅 仅 能 看 见 在 本 事 务 开 始 前 由 其 它 事 务 提 交 的 更 改 和 在 本 事 务 中 所 做 的 更 改 。 \textcolor{Red}{注:serializable 仅仅能看见在本事务开始前由其它事务提交的更改和\\在本事务中所做的更改. \\ read-only 仅仅能看见在本事务开始前由其它事务提交的更\\改和在本事务中所做的更改。} 注:serializable仅仅能看见在本事务开始前由其它事务提交的更改和在本事务中所做的更改.read−only仅仅能看见在本事务开始前由其它事务提交的更改和在本事务中所做的更改。
- Mysql支持的隔离级别:
就是以上四种。默认是最低级。