变与不变: Undo构造一致性读的例外情况

  • 时间:
  • 浏览:0

那么例外来自哪里呢,在很多例子中,当当我们 给ID列上创建了有一4个索引,原应这前要有一4个普通的索引,却说有一4个主键,那么效果咋样呢:

Oracle恢复默认的读一致性隔离级别。

Table created.

再次回到会话1,PRINT游标变量:

PL/SQL procedure successfully completed.

------------------------------------------------------------

SQL1> CREATE TABLE T_UNDO (ID NUMBER, NAME VARCHAR2(100));

原文发布时间为:2018-11-20

SQL1> EXEC OPEN :C FOR SELECT NAME FROM T_UNDO WHERE ID = 1117;

SQL2> UPDATE T_UNDO SET NAME = 'UPDATED NO ROW CR' WHERE ID = 1117;

回到会话1检查结果:

NAME

PL/SQL procedure successfully completed.

NAME

其中介绍了Oracle咋样使用UNDO来实现多版本一致性读,使用了OPEN CURSOR的土土办法 非常巧妙地在很血块数据的清况 下构发明人人可重现的案例。不过很多案例指在很多小的瑕疵,原应原应一不小心,很原应会原应结果与预期不符,这原应这里有有一4个例外指在。

PL/SQL procedure successfully completed.

UPDATED NO ROW CR

在会话3上执行查询,这前要看了会话2修改提交后的结果:

会话2进行修改:

SQL1> SELECT NAME FROM T_UNDO WHERE ID = 1117;

Table altered.

NAME

原应关闭该参数:

到目前为止,所有前要预期之内的结果,Oracle会利用UNDO来存储UPDATE的前镜像,当查询发现前要访问的数据块SCN大于会话发起的SCN,而前要通过UNDO中存储的前镜像来构造一致性读,找到会话前要读取的修改前的数据。

1 row updated.

SQL1> PRINT :C

SQL> SET SQLP 'SQL1> '

NAME

NAME

NAME

本文来自云栖社区战略媒体合作伙伴“数据和云”,了解相关信息还前要关注“数据和云”。

------------------------------------------------------------

I_EXTERNAL_LOCATION1$

着实Oracle认为很多优化却说针对主键或唯一索引等行级访问生效,造成数据一致性破坏的原应性很小,以后建议对于一致性要求较高的行业尤其是金融相关行业还是将该特征关闭,正确处理以后造成的一致性间题。

会话3检查确认修改结果:

SQL1> ALTER TABLE T_UNDO ADD PRIMARY KEY (ID);

Commit complete.

当当我们 先来模拟一下UNDO构造一致性读的清况 ,对于Oracle而言,默认的隔离级别是READ COMMIT,也却说说有一4个会话必须看了很多会话原应提交的修改,未提交的修改原应在当前要话查询发起之前 提交的修改前要不可见的。

I_EXTERNAL_TAB1$

原应很多例外的原应来自于有一4个隐含函数_row_cr:

检查结果:

------------------------------------------------------------

SQL1> DROP INDEX IND_UNDO_ID;

I_EXTERNAL_LOCATION1$

SQL1> PRINT :C

---------------

1 row updated.

还前要看了例外产生了,一致性读的结果被破坏了,甜得还前要查询到指在在游标打开之前 提交的修改。

UPDATED WITH PK

96920 rows created.

SQL1> PRINT :C

SQL> SET SQLP 'SQL2> '

------------------------------------------------------------

SQL1> EXEC OPEN :C FOR SELECT NAME FROM T_UNDO WHERE ID = 1119;

SQL1> VAR C REFCURSOR

NAME

NAME

System altered.

EXTERNAL_LOCATION$

SQL3> SELECT NAME FROM T_UNDO WHERE ID = 1118;

Index created.

Index dropped.

I_EXTERNAL_TAB1$

SQL1> EXEC OPEN :C FOR SELECT NAME FROM T_UNDO WHERE ID = 1118;

SQL1> ALTER SYSTEM SET "_row_cr" = FALSE;

回到会话1,对CURSOR变量执行PRINT,检查得到的结果:

SQL3> SELECT NAME FROM T_UNDO WHERE ID = 1119;

SQL1> INSERT INTO T_UNDO SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS;

1 row updated.

Oracle11g之前 ,很多隐含参数默认值修改为TRUE,这使得Oracle对于基于主键的访问不再采用默认的一致性读方案。当然Oracle做出很多修改的目的是为了提高性能,以后仅对于单行访问生效,而大偏离 清况 下单行访问的下行速率 非常高,以后对于一致性破坏的影响何必 明显。到18C为止,该参数仍然为TRUE。

在第有一4个会话原应构造了有一4个查询,下面在会话2对这条ID为1119的记录进行修改并提交:

------------------------------------------------------------

SQL2> COMMIT;

SQL2> COMMIT;

Commit complete.

NAME

SQL1> CREATE INDEX IND_UNDO_ID ON T_UNDO(ID);

SQL> SET SQLP 'SQL3> '

再介绍一下OPEN CURSOR,Oracle中当有一4个游标被打开,其结果集就原应选用 了,也却说说很多游标会根据OPEN CURSOR很多时间点对应的SCN来构造一致性查询。以后OPEN CURSOR时,对应的SQL何必 会被执行,在后续FETCH的之前 (对于SQLPLUS而言PRINT命令会触发FETCH),SQL才真正被执行。使用很多土土办法 还前要模拟有一4个大的查询,OPEN CURSOR大概大的查询的开始英语 了了了时间,其早于很多会话的修改提交时间,而FETCH的时间大概大查询读取到这条记录的时间,而该时间晚于很多会话提交的时间:

SQL3> SELECT NAME FROM T_UNDO WHERE ID = 1117;

UPDATED WITH PK

本文作者:xxx

------------------

SQL1> COMMIT;

------------------------------------------------------------

------------------------------------------------------------

会话2修改ID为1118的记录:

SQL2> UPDATE T_UNDO SET NAME = 'UPDATED' WHERE ID = 1119;

SQL2> COMMIT;

SQL1> SELECT NAME FROM T_UNDO WHERE ID = 1119;

Commit complete.

SQL1> SELECT NAME FROM T_UNDO WHERE ID = 1118;

SQL2> UPDATE T_UNDO SET NAME = 'UPDATED WITH PK' WHERE ID = 1118;

Commit complete.

UPDATED