在 COMMIT 之前查看不同 SQL Oracle 会话的更改?
Posted
技术标签:
【中文标题】在 COMMIT 之前查看不同 SQL Oracle 会话的更改?【英文标题】:See changes of a different SQL Oracle session before COMMIT? 【发布时间】:2021-04-06 13:24:24 【问题描述】:我协调了 Oracle PL/SQL DML 脚本的实施,但在生产环境中,我通常会联系 DBA 团队让他们运行脚本,前提是他们具有适当的权限。
有没有办法让我的用户在实际提交更改之前查看更改?我知道更改将在执行脚本的会话中生效,但是有没有办法让不同的会话,而且,不同的用户可以看到它们?
【问题讨论】:
【参考方案1】:包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
。
【讨论】:
只是一个问题:原始会话是否仍然能够提交更改?或者至少他们可以拥有交易?我之所以这样问,是因为 Session-2 的唯一目的是在批准提交之前进行数据分析,但 DBA 组仍然对该过程负责,因此他们需要提交它。 @FelipeVidalOtero 我修改了我的答案,以通过再次调用XA_END
和XA_START
来解释如何多次来回传递事务。
谢谢。我认为这取决于会话的 DML 权限,不是吗?我问是因为我试图运行它:当我使用相同的帐户但不同的选项卡运行它时,它运行正常。但是,使用仅 SELECT 特权用户提供不同的凭据,运行代码“TMRESUME”时,我得到了 ORA-01031(权限不足)。
@FelipeVidalOtero 任何用户都应该能够运行该软件包,它默认授予 PUBLIC。这个查询应该返回EXECUTE
权限:select privilege from all_tab_privs where table_name = 'DBMS_XA' and grantee = 'PUBLIC';
如果没有返回行,那么 DBA 可能会撤销默认授权,这会破坏很多事情。如果是这种情况,请让他们运行grant execute on sys.dbms_xa to public;
包运行后,您可能还需要您的用户拥有force any transaction
权限才能查看未提交的行。【参考方案2】:
无法在另一个会话中查看一个会话的未提交更改。 但是,由于您正在运行 PL/SQL DML 脚本,您可以尝试在脚本中输入日志以查看脚本进度。 您需要使用带有 AUTONOMOUS 事务的单独 PL/SQL 块来记录数据。
【讨论】:
【参考方案3】:不,这是不可能的,这是设计使然。根据定义,RDBMS 的 ACID 属性包括“隔离”,它可以防止单个连接相互了解,即看到另一个会话中的变化。
【讨论】:
【参考方案4】:在提交之前,一个会话无法看到另一个会话所做的更改。
【讨论】:
好的,谢谢。我确实在网络上看到了这一点,以及 UNCOMMITTED 隔离级别的提议(至少我认为我理解这将是假设的方式)。以上是关于在 COMMIT 之前查看不同 SQL Oracle 会话的更改?的主要内容,如果未能解决你的问题,请参考以下文章