在 COMMIT 之前查看不同 SQL Oracle 会话的更改?

问题描述

我协调了 Oracle PL/sql DML 脚本的实现,但要在生产环境中执行此操作,我通常会联系 DBA 团队让他们运行脚本,前提是他们拥有适当的权限。

有没有办法让我的用户在实际提交更改之前查看更改?我知道更改将在执行脚本的会话中处于活动状态,但是有没有办法让不同的会话以及不同的用户看到它们?

解决方法

DBMS_XA 可以将未提交的事务从一个会话转移到另一个会话。第二个会话可以查看未提交的数据,并且可以提交、回滚或再次传递事务。以下示例基于 this oracle-base article,虽然它对我有用,但我之前从未在生产中使用过此功能,因此可能存在我不知道的复杂情况。

首先创建一个示例使用的表:

--DROP TABLE tab1;

CREATE TABLE tab1 (
  id  NUMBER
);

会话 1

将事务超时从 60 秒更改为更大的值:

DECLARE
  l_return  PLS_INTEGER;
BEGIN
  l_return := SYS.DBMS_XA.xa_settimeout(500);
END;
/

开始交易,传入一个幻数来命名交易(999):

DECLARE
  l_xid     DBMS_XA_XID := DBMS_XA_XID(999);
  l_return  PLS_INTEGER;
BEGIN
  l_return := SYS.DBMS_XA.xa_start(xid  => l_xid,flag => DBMS_XA.TMNOFLAGS);
END;
/

在这里做真正的工作,无需提交:

INSERT INTO tab1 (id) VALUES (1);

结束事务以便另一个会话可以稍后附加到它:

DECLARE
  l_xid     DBMS_XA_XID := DBMS_XA_XID(999);
  l_return  PLS_INTEGER;
BEGIN
  l_return := SYS.DBMS_XA.xa_end(xid  => l_xid,flag => DBMS_XA.TMSUSPEND);
END;
/

数据从我们的会话中消失了——这个表不包括我们刚刚插入的行。另一个会话需要附加到全局事务并提交或回滚。

select * from tab1;

第 2 节

最初,这个会话看不到数据:

select * from tab1;

附加到全局事务,使用相同的幻数(999):

DECLARE
  l_xid     DBMS_XA_XID := DBMS_XA_XID(999);
  l_return  PLS_INTEGER;
BEGIN
  l_return := SYS.DBMS_XA.xa_start(xid  => l_xid,flag => DBMS_XA.TMRESUME);
END;
/

现在只有这个会话可以看到新行:

select * from tab1;

第二个会话可以提交、回滚或将事务传递给另一个会话。要传递交易,请再次调用 DBMS_XA.XA_END 并进行另一个会话,然后调用 DBMS_XA.XA_START

,

在提交之前,一个会话无法看到另一个会话所做的更改。

,

无法在另一个会话中查看一个会话未提交的更改。 但是,由于您正在运行 PL/SQL DML 脚本,因此您可以尝试在脚本中登录以查看脚本进度。 您需要使用带有 AUTONOMOUS 事务的单独 PL/SQL 块来记录数据。

,

不,这是不可能的,这是设计使然。根据定义,RDBMS 的 ACID 属性包括“隔离”,它可以防止单个连接相互了解,即查看另一个会话中的更改。