Oracle中事务隔离机制
事务的概念挺简单,要么全执行要么全不执行,就像银行转账,这被奉为经典案例!谈事务必提,我就不提了。事务分显示提交和隐式提交,还有一种自动提交。
显示提交必须手动敲入commit或rollback命令。DML必须显示提交,包括的命令:update、insert、delete,这几个很好理解,但select也需要显示提交,有点难理解,select只是个查询语句,而且select似乎是DQL不是DML。我们可以考虑下select into from语句,select into是一个plsql语言中的复制语句,和:=实现的目标一样。
隐式提交就是DDL、DCL,包括create、drop、alter,grant、revoke。
事务隔离级别:一个事务对数据库的修改与并行的另一个事务的隔离程度。
两个并发事务同时访问数据库表相同的行时,可能存在以下三个问题:
1、幻想读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想。
2、不可重复读取:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同,这称为不可重复读。
3、脏读:事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据,然后T1执行回滚操作,取消刚才的修改,所以T2所读取的行就无效,也就是脏数据。
为了处理这些问题,SQL标准定义了以下几种事务隔离级别
READ UNCOMMITTED 幻想读、不可重复读和脏读都允许。
READ COMMITTED 允许幻想读、不可重复读,不允许脏读
REPEATABLE READ 允许幻想读,不允许不可重复读和脏读
SERIALIZABLE 幻想读、不可重复读和脏读都不允许
Oracle数据库支持READ COMMITTED(Oracle默认)和SERIALIZABLE这两种食物隔离级别。Oracle不支持脏读。
针对幻想读、不可重复读、脏读,我们举例说明:
1.两个session,右边的session中create语句完成,左面就可以查询到此表,说明create是隐式提交的。
create table t(id number primary key,name varchar2(10));
desc t;
2.右边的session插入两条数据,不写commit,然后查询时可以查询出插入的数据;但左边的session查询不到插入的数据
insert into t values(1,’mark’);
insert into t values(2,’judy’);
select id,name from t;
select id,name from t;
3.在右边的session中输入commit,然后左边的session再查询即可查询到插入的数据
commit;
select id,name from t;
通过2,3就可以理解insert语句需要显示提交的
4.在右边的session里查询name=judy的语句,然后在左边的session里再插入一条name=judy的语句并提交,然后再次查询在右边的session里查询
select id,name from t where name=’judy’;
insert into t values(3,’judy’);
commit;
select id,name from t where name=’judy’;
这步就可以理解oracle支持幻想读的。
5.右边的session里查询id=2的语句,然后左边的session里删除id=2行,开始不提交,然后再提交,分别在右边的session再次执行查询id=2的语句
select id,name from t where id=2;
delete from t where id=2;
select id,name from t where id=2;
commit;
select id,name from t where id=2;
这步就可以确定delete需要显示提交,oracle支持不可重复读。
6.在右边的session里更新id=1的行,然后在左边的session查询id=1,然后再在右边的session里查询,然后rollback,再查询id=1
update t set name=’judy’ where id=1;
select id,name from t where id=1;
select id,name from t where id=1;
rollback;
select id,name from t where id=1;
select id,name from t where id=1;
这步就可以确定update也需要显示提交的,同样确定了oracle不支持脏读。
有部分内容参考网上,其他纯属个人理解!