深入内核:Oracle数据提交与事务隔离的深度解析

崔华,网名 dbsnake

Oracle ACE Director,ACOUG 核心专家

编辑手记:感谢崔华授权我们独家转载其精品文章,也欢迎大家向“Oracle”社区投稿。

大家都知道的一个常识是 - Oracle 里未 commit 的数据除了当前 session 之外,其他 session 是看不到的

我这里演示了一个有趣的例子,在这个例子里我们可以看到,Oracle里未成功 commit 的数据我们也可能能看到

我同时启4个 session。

 

先在 session 1里创建一个表t1,插入一条数据但不 commit:

Session 1:

Connected to Oracle Database 11g

 Enterprise Edition Release 11.2.0.1.0

Connected as scott

SQL> create table t1(id number, name varchar2(10));

Table created

 

SQL> insert into t1 values(1,’CUIHUA’);

1 row inserted

 

SQL> select * from t1;

        ID NAME

———- ———-

         1 CUIHUA

 

此时跳到 session 2,因session 1里刚插入的那条数据还未commit,所以这个时候 session 2是看不到这条数据的:

Session 2:

SQL> select * from t1;

 

        ID NAME

———- ———-

 

接着我们跳到 session 3,把lgwr进程suspend住:

Session 3:

SQL> select spid from v$process where pname=’LGWR’;

 

SPID

————————

2316

 

SQL> oradebug setospid 2316

Oracle pid: 11, Windows thread id: 2316,

 image: ORACLE.EXE (LGWR)

SQL> oradebug suspend

已处理的语句

 

现在我们回到 session 1,执行commit命令,因为 lgwr 进程已经被我们 suspend 住了,所以当前 session 1里要执行的 commit 操作一定会被hang住:

Session1:

SQL> commit;

……这里 hang 住了

 

Oracle 里 commit 操作的流程是这样的:

1、Oracle 先去改这个 transaction 所对应的 undo segment header 中 slot 的状态;

2、改完状态后再 flush log buffer;

现在我们把lgwr hold住了,所以上述步骤2 Oracle是没法做了,但步骤1还是可以做的。

而只要步骤1做完了,其他的 session 就能看到这个transaction所做的改变了(通过ITL中记录的 transaction id 去 check相应的 undo segment header 中 slot 的状态),也就是说对于其他 session 而言,这个 transaction 已经 commit 了,虽然这个 transaction 其实并没有成功commit。

 

好了,我们现在回到session 2,看一下我们现在能否看到刚才insert的那条记录:

Session 2:

SQL> select * from t1;

        ID NAME

———- ———-

         1 CUIHUA

 

从结果里可以看到,刚才看不到的那条记录现在我们已经能看到了,即 session 1对于 session2而言已经 commit 了,虽然 session1的 commit 操作其实并没有成功的做完。

 

现在我们跳到 session 4,执行shutdown abort:

Session 4:

SQL> shutdown abort

ORACLE 例程已经关闭。

 

然后我们再在 session 4中执行 startup,startup 后我们从 alert log 里可以很明显的看到 

Oracle做了 instance recovery:

 

等待上述库成功startup后,我们再次回到session 1,看一下刚才我们已经commit的那条数据是否还在:

Session 1:

SQL> select * from t1;

 

        ID NAME

———- ———-

 

从结果里可以看到,刚才我们 insert 且执行了 commit 操作的那条记录现在已经丢失了。

建议大家动手操作一下,以深入理解Oracle的事务隔离机制,事务恢复原理。


本文出自数据和云公众号,原文链接

时间: 2024-10-12 23:59:35

深入内核:Oracle数据提交与事务隔离的深度解析的相关文章

Oracle数据库事务隔离级别概述

整理自Oracle 11g R2 官方文档 <concepts> 001 概述     Oracle数据库提供如下事务隔离级别:     ·已提交读隔离级别     ·可串行化隔离级别     ·只读隔离级别 002 读提交隔离级别2-1 概述     在(默认的)已提交读隔离级别中,事务中执行的每个查询,仅看到在查询 开始之前提交的数据--而不是事务开始之前提交的数据.这一隔离级别适合于几乎不可能发生事务冲突的数据库环境.     已提交读事务中的查询可以避免读取在查询过程中所提交的数据.例

Spring五个事务隔离级别和七个事务传播行为

Spring五个事务隔离级别和七个事务传播行为 1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据. 2. 不可重复读 :是指在一个事务内,多次读同一数据.在这个事务还没有结束时,另外一个事务也访问该同一数据.那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的.这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读.例如

mysql中不同事务隔离级别下数据的显示效果

  事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都不会执行.也就是说,事务内的语句要么全部执行,要么一句也不执行. 事务的特性:acid,也称为事务的四个测试(原子性,一致性,隔离性,持久性) automicity:原子性,事务所引起的数据库操作,要么都完成,要么都不执行 consisitency:一致性,事务执行前的总和和事务执行后的总和是不

查看ORACLE事务隔离级别方法(转)

众所周知,事务的隔离级别有序列化(serializable),可重复读(repeatable read),读已提交(read committed),读未提交(read uncommitted).根据隔离级别的等级,对事务隔离的严格度也不同,如序列化的隔离级别最严格,并发的效果就越不理想,各种数据库都有对事务隔离的支持,那么如何查看ORACLE对事务的隔离级别呢?还是做个试验验证吧 一 首先做个测试表,表结构和其中的数据如下 ID PHONE 43071 126811 二 打开一个session,

MSSQL与Oracle数据库事务隔离级别与锁机制对比_oracle

一,事务的4个基本特征 Atomic(原子性): 事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要 么全部成功,要么全部失败. Consistency(一致性): 只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初 状态. Isolation(隔离性): 事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正 确性和完整性.同时,并行事务的修改必须与其他并行事务的修改 相互独立. Durability(持久性): 事务结束后,事务处理的结果必须能够得到固化. 以上属于废话

查看ORACLE事务隔离级别方法

众所周知,事务的隔离级别有序列化(serializable),可重复读(repeatable read),读已提交(read committed),读未提交(read uncommitted).根据隔离级别的等级,对事务隔离的严格度也不同,如序列化的隔离级别最严格,并发的效果就越不理想,各种数据库都有对事务隔离的支持,那么如何查看ORACLE对事务的隔离级别呢?还是做个试验验证吧 一 首先做个测试表,表结构和其中的数据如下     ID    PHONE   43071 126811 二 打开一

SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

原文:SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因 原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中的事务概念,ACID 原则,事务中常见的问题,问题造成的原因和事务隔离级别等这些方面的知识好好的整理了一下. 其实有关 SQL Server 中的事务,说实话因为内容太多, 话题太广,稍

表单数据-使用springmvc中controller怎么实现JSP页面数据提交到oracle数据库,求代码。

问题描述 使用springmvc中controller怎么实现JSP页面数据提交到oracle数据库,求代码. 如何使用controller进行JSP页面输入数据的存储,如图,怎么写这个功能的代码,将咨询内容提交到后台数据库中,然后在后台管理的页面进行对该问题的回复.求大神给写个代码.谢谢. 解决方案 你要把数据传递到后台,然后在保存到数据库里面,建议使用Ajax操作,先把数据传递到后台,通过业务逻辑保存好了之后,再把你的回复通过Ajax的回调函数返回到界面 解决方案二: 怎么写的,求给个代码.

MySQL InnoDB存储引擎的事务隔离级别

我们知道,在关系数据库标准中有四个事务隔离级别: 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据 提交读(Read Committed):只能读取到已经提交的数据.Oracle等多数数据库默认都是该级别 可重复读(Repeated Read):可重复读.在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别.在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读 串行读(Serializable):完全串行化的读,每次读都需