问题描述
我协调了 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 属性包括“隔离”,它可以防止单个连接相互了解,即查看另一个会话中的更改。