[20130902]Oracle 11G数据库的一致读性读取行为的改变.txt

简介: [20130902]Oracle 11G数据库的一致读性读取行为的改变.txthttp://www.dbsnake.net/oracle-cr-behavior-change.
[20130902]Oracle 11G数据库的一致读性读取行为的改变.txt

http://www.dbsnake.net/oracle-cr-behavior-change.html

昨天看了崔华的帖子,blog中给出一个例子,例子如下:
create or replace procedure p_demo_cr_read_change is
  cursor c1 is select * from emp where empno=7369;
  employee_rec emp%rowtype;
begin
  open c1;
  dbms_lock.sleep(60);
                                                                    
  fetch c1 into employee_rec;
  while (c1%found) loop
                                                                   
     dbms_output.put_line('employee id: ' || employee_rec.empno);
     dbms_output.put_line('employee name: ' || employee_rec.ename);
                                                                   
    fetch c1 into employee_rec;
  end loop;
  close c1;
end p_demo_cr_read_change;
/

按照以前的理解,如果在open 光标后,结果已经确定,即使别的回话修改了 empno=7369的ename值,显示的结果
 select * from emp where empno=7369;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20


    但从Oracle 11g开始,Oracle更改了在某些特定条件一致读的行为,这使得一些看起来不合常理的行为在Oracle 11g以及后续的版本
中得以出现,即在Oracle 11g以及后续的版本中,当满足一定的条件时,我们就可以马上读到commit后的数据,而不再存在以前的那种
一致读的行为。

    Oracle将这种改动称为"RowCR Optimization",Oracle简单的描述了什么是RowCR Optimization:A brief overview of this
optimization is that we try to avoid rollbacks while constructing a CR block if the present block has no uncommitted
changes.这里的avoid rollback,意味着在满足特定的条件时,Oracle就不做一致读了。

    RowCR Optimization通过隐含参数"_row_cr"来控制,但遗憾的是,Oracle在11g及其后续的版本中将这个参数的默认值改成了TRUE,
这意味着上述这种"在满足特定的条件时,Oracle就不做一致读"的行为在Oracle 11g及其后续的版本中在默认情况下就已经被开启了,
这也许有些激进。国内的某银行在升级到Oracle 11g后就出现了一致读的问题,在这次的CAB技术峰会上,Oracle负责高可用性研发的VP
Wei Hu承认:"我们在默认情况下开启了RowCR Optimization,这也许是不恰当的。"

    这些可能导致与早期的理解不一致,重复他的例子来说明问题:

1. 测试环境:
SCOTT@test> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

--建立过程p_demo_cr_read_change,忽略,执行脚本在上面。

SCOTT@test> select empno,ename from emp where empno=7369;
     EMPNO ENAME
---------- ----------
      7369 SMITH


2.开始测试:
--打开回话1:
set serveroutput on
exec p_demo_cr_read_change

--打开回话2:
update emp set ename='lfree' where empno=7369;
commit ;

--回到回话1:
employee id: 7369
employee name: lfree

PL/SQL procedure successfully completed.

可以发现回话1没有做常规的一致读,而是马上读到了commit后的数据,即此时已经发生了RowCR Optimization。


3.恢复原值,并且删除emp表的主键PK_EMP:
--打开回话2:
update emp set ename='SMITH' where empno=7369;
commit ;
alter table emp drop constraint pk_emp;
select empno,ename from emp where empno=7369;
     EMPNO ENAME
---------- ----------
      7369 SMITH

--然后重复测试:
--打开回话1:
set serveroutput on
exec p_demo_cr_read_change

--打开回话2:
update emp set ename='lfree' where empno=7369;
commit ;

--回到回话1:
employee id: 7369
employee name: SMITH

PL/SQL procedure successfully completed.

--这个结果就是正常的一致性读取。此时并没有做RowCR Optimization,即并没有马上读到commit后的数据,这说明当我们把
--列empno上的主键drop掉后(即drop掉empno上的唯一性索引后),Oracle并没有做RowCR Optimization,而是做了常规的一致读。

4.在列empno上创建一个名为i_emp_empno的非唯一性索引,还原原值:
update emp set ename='SMITH' where empno=7369;
commit ;
create  index i_emp_empno on emp(empno);
--索引为不唯一索引。
select empno,ename from emp where empno=7369;
     EMPNO ENAME
---------- ----------
      7369 SMITH

--然后重复测试:
--回到回话1:
employee id: 7369
employee name: SMITH

PL/SQL procedure successfully completed.

--同样也没有做RowCR Optimization,说明如果索引非唯一,Oracle也没有做RowCR Optimization,而是做了常规的一致读。

5.在列empno上创建一个名为i_emp_empno的唯一性索引,还原原值:
update emp set ename='SMITH' where empno=7369;
commit ;
drop index i_emp_empno ;
create  unique index i_emp_empno on emp(empno);
select empno,ename from emp where empno=7369;
     EMPNO ENAME
---------- ----------
      7369 SMITH

--然后重复测试:
--回到回话1:
employee id: 7369
employee name: lfree

PL/SQL procedure successfully completed.

--列empno存在唯一性索引的情形下,Oracle选择做了RowCR Optimization。

6.还原原值,并且修改系统隐含参数"_row_cr"=false:
update emp set ename='SMITH' where empno=7369;
commit ;
alter system set "_row_cr" = false scope=memory;

--然后重复测试:
--回到回话1:
employee id: 7369
employee name: SMITH

PL/SQL procedure successfully completed.

--可以即使列empno上存在唯一性索引,Oracle此时也没有做RowCR Optimization,即并没有马上读到commit后的数据,这说明隐含参数
--"_row_cr"确实能控制RowCR Optimization的开启与否。

    Oracle在描述RowCR Optimization时曾经提到其生效的前提条件为:A brief overview of this optimization is that we try to
avoid rollbacks while constructing a CR block if the present block has no uncommitted changes.

7.还原原值,并且修改系统隐含参数"_row_cr"=true:
update emp set ename='SMITH' where empno=7369;
commit ;
alter system set "_row_cr" = true scope=memory;

--打开回话1:
set serveroutput on
exec p_demo_cr_read_change

--打开回话2:
update emp set ename='lfree' where empno=7369;
commit ;
update emp set ename='lfree1' where empno=7369;

--回到回话1:
employee id: 7369
employee name: SMITH

PL/SQL procedure successfully completed.

--显示Oracle此时做了常规的一致读,即在被访问的数据块存在未commit的数据的情形下不会发生RowCR Optimization。
--注:我这里测试跟作者不一样,估计版本问题11.2.0.3修复了这个错误,作者的版本是11.2.0.1.

8.还原原值,继续测试:我自己补充的
update emp set ename='SMITH' where empno=7369;
commit ;

--打开回话1:
set serveroutput on
exec p_demo_cr_read_change

--打开回话2:修改empno=7369为8001
update emp set empno =8001 where empno=7369;
commit ;

--回到回话1:
employee id: 7369
employee name: SMITH

PL/SQL procedure successfully completed.

--显示Oracle此时做了常规的一致读。

    最后,我们来总结一下,从上述测试过程我们可以得到如下结论:

    在Oracle 11g以及后续的版本中,默认情况下(即隐含参数"_row_cr"的值为TRUE的情况下),如果是通过唯一性索引去访问数据,
则我们就可以马上读到commit后的数据,而不再存在以前的那种一致读的行为。

     补充1点:我个人认为是否会出现一些“错误”还是有待观察,毕竟这种方式与原来的不同。
 
目录
相关文章
|
1月前
|
存储 Oracle 关系型数据库
数据库数据恢复—ORACLE常见故障的数据恢复方案
Oracle数据库常见故障表现: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE ASM存储破坏。 3、ORACLE数据文件丢失。 4、ORACLE数据文件部分损坏。 5、ORACLE DUMP文件损坏。
121 11
|
2月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
2月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
1月前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。
|
2月前
|
SQL Oracle 关系型数据库
Oracle数据库优化方法
【10月更文挑战第25天】Oracle数据库优化方法
61 7
|
3天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
39 0
|
30天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
60 3
|
30天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
75 3
|
30天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
90 2
|
1月前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
269 15

热门文章

最新文章

推荐镜像

更多