用sys用户给scott一个默认表空间
create tablespace lisx datafile '+DATA' ;
alter user scott default tablespace lisx ;
建测试表
create table dept
(deptno number(9),
deptname varchar2(20),
detail varchar2(50)
);
insert into dept values(1,'业扩','新装增容') ;
insert into dept values(2,'账务','账务') ;
insert into dept values(3,'电费','电费') ;
insert into dept values(4,'质量','测试DBA打包') ;
commit ;
打开两个scott的会话
在会话1里面:
SQL> col deptname format a10 ;
SQL> col detail format a20 ;
SQL> select * from dept ;
DEPTNO DEPTNAME DETAIL
---------- ---------- --------------------
1 业扩 新装增容
2 账务 账务
3 电费 电费
4 质量 测试DBA打包
SQL> show user
USER is "SCOTT"
SQL>
SQL>
SQL> update dept set detail='账务2222' where deptno=2 ;
1 row updated.
然后在会话2里:
SQL> set sqlprom 'SQL2>' ;
SQL2>
SQL2>col deptname format a10 ;
SQL2>col detail format a20 ;
SQL2>select * from dept ;
DEPTNO DEPTNAME DETAIL
---------- ---------- --------------------
1 业扩 新装增容
2 账务 账务
3 电费 电费
4 质量 测试DBA打包
SQL2>update dept set detail='账务33333' where deptno=2 ;
如果第一个会话不提交,那么SQL2的修改会失败,一直等待前一个会话释放资源,形成了语句的死锁。
如果会话一提交,那么会话2也可以成功执行,但是因为修改的标准是参照最初的值,所以会覆盖会话1的修改结果。我们称之为不可重复读(Non Repeatable Read)
SQL>commit ;
Commit complete.
SQL2>commit ;
Commit complete.
下面在第二个会话设置
SQL2>alter session set isolation_level=serializable ;
我们看看设置IO隔离级别后的效果,主要是看看能否避免丢失修改。
SQL2>select * from dept ;
DEPTNO DEPTNAME DETAIL
---------- ---------- --------------------
1 业扩 新装增容
2 账务 账务33333
3 电费 电费
4 质量 测试DBA打包
在会话1里设置IO隔离级别
SQL>alter session set isolation_level=serializable ;
Session altered.
SQL> update dept set detail='44444' where deptno=2 ;
1 row updated.
先不提交,在会话2里面执行
SQL2>update dept set detail='55555' where deptno=2 ;
该修改会处于等待状态
然后提交会话1
SQL> commit ;
Commit complete.
会话2里面报错了:
SQL2>update dept set detail='55555' where deptno=2 ;
update dept set detail='55555' where deptno=2
*
ERROR at line 1:
ORA-08177: can't serialize access for this transaction
因此通过设置会话1的隔离级别isolation_level=serializable,避免了其他会话的修改丢失。
理论上serializable还能避免幻影读,但是幻影读不太好实现。
SQL标准中定义了4中IO隔离级别
READ Uncommited
READ Commited 避免了脏读
Repeatable 避免了脏读,不可重复读
Serializable 避免了脏读,不可重复读,幻影读
但是ORACLE只有3中:
READ Commited
Serializable
Read Only
对于READ Uncommited,oracle无法模拟。
对于Repeatable,ORACLE可以通过悲观锁和乐观锁实现Repeatable
Read Only和Serializable的区别是对于丢失修改,前者是禁止修改,后者报错:
ORA-08177: can't serialize access for this transaction