数据库事务可能大家都很熟悉,在开发过程中也会经常使用到。但是即使如此,可能对于一些细节问题,很多人仍然不清楚。比如很多人都知道数据库事务的几个特性:原子性(Atomicity )、一致性( Consistency )、隔离性或独立性( Isolation)和持久性(Durabilily),简称就是ACID。但是再往下比如问到隔离性指的是什么的时候可能就不知道了,或者是知道隔离性是什么但是再问到数据库实现隔离的都有哪些级别,或者是每个级别他们有什么区别的时候可能就不知道了。
当然这些问题都可以搜索得到,这里作下汇总;
数据库事务ACID特性:
A:原子性(Atomicity ) 原子性意味着每个事务都必须被看作一个不可分割得单元,假设一个事务由两个或者多个任务组成,其中的语句必须同时成功才能认为整个事务是成功的,如果事务失败,系统将会返回到该事务以前的状态;
B:一致性( Consistency ) 不管事务是完全成功还是中途失败,当该事务要使系统处于一致性的时候,就必须要保证一致性,比如 从系统中删除了一个用户的信息,那么与该用户相关的数据也要被删除;
C:隔离性( Isolation) 隔离性是指每个事务只能在自己的空间里发生,事务之间不可见,而事务的结果也只能在它被完全执行过后才能被看到,如果事务之间可以互相看到,那么必然会造成大量数据的破坏;
D:持久性(Durabilily) 当一个事务被成功提交,哪怕这时候系统数据库崩溃,因为事务被完成,数据库的日志已经被更新,持久性就开始发生作用,当数据库恢复时,日志里的记录会被写入到库中;
数据库隔离级别:
这里是数据库设计方面针对上面所述的隔离性做的扩展,因为有很多时候,我们可能并不需要强隔离性。
这里存在四种隔离级别:
(1)序列化(SERIALIZABLE):如果隔离级别是序列化,那么事务必须一个一个按顺序排队执行,这提供了最大限度的隔离,当然这样的机制必然会使系统处理业务的性能受影响,一般情况下,我们不推荐这样设置;
(2)可重复读(REPEATABLE READ) 在这级别上,事务不会排队执行,而且也能保证事务之间执行的变化不被看到,也就是说,在同一个事务中执行同条select语句,所看到的结果都是相同的;
(3)读已提交(READ COMMITTED) 提交读会比可重复读的安全性要差,因为在这一级别上,事务可以看到别的事务已提交的数据,也就是说同条select语句有可能读到不一样的数据;
(4)读未提交(READ UNCOMMITTED)这种级别提供了最小限度的隔离,它使得事务可以看到别的事务未提交的数据,这得多可怕,所以这种最差的隔离级别也是不被推荐使用。
上述的隔离机制都是为了预防哪些问题的发生呢?
并发访问会产生的问题(归类四种):
(1)丢失更新:当多个事务同时对同一行数据操作,因为事务之间不可见,他们都是基于最初的值进行修改,所以可能会导致事务A的更新操作会被事务B的更新操作所覆盖,这就导致数据丢失;
(2)脏读:一个事务可能读到了别的事务未提交的数据,那么就会发生脏读问题;
(3)不可重复读:这与上述的脏读有相似之处,是指在同一个事务中第一次读到的数据可能与第二次读到的数据不一样,因为第二次读到的数据可能正在被其他事务所修改。
(4)幻读:是指在同一个事务中第一次读到的数据在第二次读取中都不到了,因为第二次想要读到的数据可能正在被其他事务所删除。
那么我们熟悉的mysql和oracle是怎样处理这些问题的呢?
mysql支持四种隔离级别;
mysql默认的事务处理级别是‘REPEATABLE-READ‘,也就是可重复读
1.查看当前会话隔离级别
select @@tx_isolation;
2.查看系统当前隔离级别
select @@global.tx_isolation;
3.设置当前会话隔离级别
set session transaction isolatin level repeatable read;
4.设置系统当前隔离级别
set global transaction isolation level repeatable read;
而oracle只支持提交读(READ COMMITTED) 和 序列化(SERIALIZABLE)这两种事务隔离级别。
oracle默认的事务隔离级别是READ COMMITTED,也就是读已提交
所以在这点上,两者之间还是有区别的;
下面的图具有阶梯性质的,容易记;