一、两阶段提交
1、准备阶段:
- 确定提交点站点。
- 全局协调器要求所有参与节点(提交点站点除外)承诺提交或回滚事务(无论失败)。
该信息由本地协调员传播。服务器必须在本地或全局协调器(提交点站点除外)之前准备好。本地协调器负责要求依赖节点做好准备。
节点可能的响应:
- 已准备
- 中止
- 只读节点
在分布式事务期间获得的锁将继续被持有。
重做被刷新到本地重做日志。
- 每个节点都会传回自己节点的SCN。
- 全局协调器确定最大SCN。
当所有节点准备成功后,我们进入提交阶段。除了在提交点站点中找到的事务之外,所有事务都处于“不确定”状态,直到提交点阶段成功完成。
2、提交阶段:
1)全局协调器将最大SCN发送到提交点站点并要求其提交。
2) 提交点站点将尝试提交或回滚所有内容。首先在提交点站点释放锁。
3) 如果提交/回滚,提交点站点将通知全局协调员届时进行提交/回滚。
4)信息将向下传播到其客户端/本地协调器,他们将提交/回滚并将信息向下传播到他们的服务器,直到没有更多的服务器。
3、交易何时被视为“可疑”?
当所有节点准备成功后,我们进入提交阶段。除了在提交点站点中找到的事务之外,所有事务都处于“不确定”状态,直到提交点阶段成功完成。
二、Oracle 分布式事务
分布式事务修改与两个或多个数据库相关的数据,它包含跨多个节点的DML语句。为了使分布式事务成功,事务中涉及的所有数据库节点或不需要提交或回滚整个事务。注意分布式事务和远程事务之间的区别;
远程事务包含在同一远程节点上执行的一个或多个 DML 语句
1、分布式事务
insert into table@remotesite;
insert into mytable: --local table
commit;
远程事务
insert into table@remotesite;
commit;
数据库链接用于在执行分布式事务的数据库之间进行通信。位置透明性可以通过同义词、数据库视图或 PL/SQL 过程来实现。
2、全局数据库名称
数据库的全局名称由DB_NAME.DB_DOMAIN组成,其中DB_DOMAIN指定网络域。在分布式环境中,数据库的全局名称在网络中是唯一的,以便可以明确地识别每个数据库,这一点至关重要。
3、两阶段提交
2PC 分为三个阶段:
PREPARE:发起节点要求其引用的每个节点承诺在被告知时执行提交或回滚。准备节点会将重做日志缓冲区刷新到联机重做日志。它将数据块上的锁转换为不确定事务锁,并将其最高的 SCN 值传递给发起节点。
COMMIT:发起节点提交并向其重做日志写入已提交的 SCN。数据块锁被释放。
FORGET:待处理事务表相关数据库视图被清除(dba_2pc_pending/dba_2pc_neighbors)
注意:
准备阶段期间的崩溃会导致回滚
提交阶段期间的崩溃会导致提交或回滚
4、可疑交易
如果分布式事务失败,可能会在一个或多个数据库上留下可疑事务。
当数据库或网络恢复时,有疑问的事务通常会自动解决,这是由 RECO 数据库后台进程完成的。
当两阶段提交因任何类型的系统或网络故障而中断时,就会发生不确定的分布式事务。例如,两个数据库向协调数据库报告它们准备提交,但协调数据库实例在收到消息后立即失败。准备提交的两个数据库现在正在等待结果通知。
5、恢复进程(RECO)
RECO是分布式数据库中的强制后台进程,可自动解决分布式事务中的故障。节点的RECO进程自动连接到参与不确定分布式事务的其他数据库;它可以使用现有连接或与失败事务中涉及的其他节点建立新连接。当 RECO 重新建立数据库之间的连接时,它会自动解析所有可疑事务,从每个数据库的待处理事务表中删除对应的任何行至已解决的交易。
nit.ora 参数distributed_transactions > 0(用于启动RECO)
如果init.ora open_links 设置为0,则不允许分布式事务。
仅当实例允许分布式事务时,才会出现 RECO 进程。
您可以使用带有 ENABLE/DISABLE DISTRIBUTED RECOVERY 选项的 ALTER SYSTEM 语句来启用和禁用 RECO。
如果数据库已装入但未打开,您可以禁用分布式恢复。
select dbid,name,log_mode,open_mode from v$database;
select instance_number,instance_name,status from v$instance;
6、禁用RECO
-To disable RECO:
ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY
-To enable RECO and let it automatically resolve indoubt transactions
ALTER SYSTEM ENABLE DISTRIBUTED RECOVERY;
7、数据库参数
GLOBAL_NAMES:(默认 false):强烈建议将此参数设置为 TRUE,以强制数据库名称在网络中的唯一性。将其设置为 TRUE 会强制所有数据库链接与其连接到的数据库的 global_name 具有相同的名称。
注意:将此参数从 false 更改为 true 可能会导致现有数据库链接不可用。
OPEN_LINKS:(默认为 4)指定一个会话中与远程数据库的并发打开连接的最大数量。这些连接包括数据库链接,以及外部过程和卡带,每个连接都使用单独的进程。它至少应该与任何事务可以引用的数据库的最大数量相同。
DISTRIBUTED_LOCK_TIMEOUT:(默认 60 秒):定义分布式事务等待锁的秒数。如果会话等待锁的时间超过此时间,则会发出 ORA-2049 信号。
COMMIT_POINT_STRENGTH(默认为 1)。值的范围是 0 到 255 之间的任何整数。它的值确定分布式事务中的提交点站点。事务中具有最高 COMMIT_POINT_STRENGTH 值的节点将是提交点站点。应根据数据库中关键共享数据的数量来设置提交点强度。如果未设置提交点站点,Oracle 将确定哪个站点成为提交点站点。
8、视图
DBA_2PC_PENDING
LOCAL_TRAN_ID 交易的本地Id,格式为nnn;其中n是一个数字
GLOBAL_TRAN_ID 全局交易ID,对于所有站点都是唯一的
STATE 以下之一:收集/准备/已提交/强制提交/强制回滚
MIXED YES 表示事务的部分已提交且部分回滚(强制)
ADVICE C表示提交/R表示回滚 仅当应用程序在开始分布式事务之前发出以下语句之一时,才会填充此字段:ALTER SESSION ADVICE COMMIT/ALTER SESSION ADVICE ROLLBACK
TRAN_COMMENT 仅当应用程序发出带有注释的 COMMIT 时,才会填充此列
FAIL_TIME 行插入到视图中的时间
FORCE_TIME 如果是强制交易,则会显示时间;否则为 NULL
RETRY_TIME RECO 进程上次尝试解决事务的时间
OS_USER 创建事务的本地用户的 OS USerID
OS_TERMINAL 交易的本地部分源自的终端
HOST 本地事务发起的机器名称
DB_USER 发起分布式事务的数据库用户名
COMMIT# 如果事务已提交,则此列表示全局提交编号
DBA_2PC_NEIGHBORS
LOCAL_TRAN_ID 交易的本地标识符
IN_OUT 连接类型:IN 用于传入/OUT 用于传出
DATABASE 对于传入连接,这是客户端数据库全局名称/对于传出连接,该值表示数据库链接
DBUSER_OWNER 对于传入连接,Oracle 用户名/对于传出连接,数据库链接的所有者
INTERFACE 用于定位全局提交点站点:对于传入链接,C 表示该站点或传出链接上的后代站点之一是提交点站点。对于传出链接C表示目标数据库DBID是提交点站点。如果我们有疑问,INTERFACE是N,那么顶级数据库要么是提交点站点,要么可以定位提交点站点。
DBID 远程数据库的全局名称
SESS# 该数据库连接的本地会话号。会话按顺序编号,从 1 开始/
BRANCH 该数据库连接的事务分支 ID。传入连接的分支 ID 是两个字节的十六进制数字;第一个字节是远程父级的会话 ID,第二个字节是其分支 ID。
VDBLINK
VDBLINK 列出会话中所有打开的数据库链接,即 IN_TRANSACTION 列设置为 YES 的所有数据库链接。
GVDBLINK 列出会话中所有打开的数据库链接及其相应的实例。该视图在 Oracle Real Application Clusters 配置中非常有用。
确定当前在您自己的会话中打开哪些数据库链接连接可能很有用。请注意,如果您以 SYSDBA 身份连接,则无法查询视图来确定为所有会话打开的所有链接;您只能访问您正在工作的会话中的链接信息。
V$GLOBAL_TRANSACTION
V$GLOBAL_TRANSACTION提供有关当前活动分布式事务的信息。
9、测试失败的分布式事务的恢复
Oracle 提供了一种强制分布式事务失败的方法,以便您可以根据故障点测试和验证分布式事务恢复过程。发出带有注释的COMMIT,例如ORA-2PC-CRASH-TEST-n,-其中 n 是 1 到 10 之间的数字-。
可以测试多种场景,
1 Crash commit point after collect
2 Crash non-commit-point site after collect
3 Crash before prepare (non-commit-point site)
4 Crash after prepare (non-commit-point site)
5 Crash commit point site before commit
6 Crash commit point site after commit
7 Crash non-commit-point site before commit
8 Crash non-commit-point site after commit
9 Crash commit point site before forget
10 Crash non-commit-point site before forget
COMMIT COMMENT 'ORA-2PC-CRASH-TEST-7';
ORA-02054: transaction 1.93.29 in-doubt
ORA-02059: ORA_CRASH_TEST_7 in commit comment
10、分布式事务失败
分布式事务相关的错误消息在 ORA-02040 - ORA-02099 范围内失败
ORA-02053:事务已提交,某些远程数据库可能存在疑问
该事务已在本地提交,但是我们与一个或多个本地协调器失去了通信。
ORA-02054 : 事务不确定
该事务既未在本地提交也未回滚,并且我们已失去与全局协调器的通信。
ORA-02050:事务已回滚,某些远程数据库可能存在疑问
表示两阶段提交期间发生通信错误
ORA-01591:遇到由不确定的分布式事务持有的锁定
上述错误且用户/应用程序无法继续他们的工作。在这种情况下,Oracle 自动回滚用户尝试的事务,并且 DBA 现在必须手动提交或回滚有疑问的事务。
注意:读取会被阻止,因为在事务解决之前,Oracle 不会假定为查询用户显示哪个版本的数据。
ORA-02049 timeout:Distributed transaction waiting for lock
分布式事务在等待获取锁时超时或本身持有锁的时间过长。如果分布式事务在DISTRIBUTED_LOCK_TIMEOUT秒后无法获得所需的锁,则返回以下错误:
三、处置步骤
1、发现问题
用户查询数据库 DB102C 中的本地表遇到以下错误并通知 DBA:
ORA-01591: lock held by in-doubt distributed transaction 10.24.340
在alert中
DISTRIB TRAN <GLOBAL_NAME>.ea27958e.9.46.338
is local tran 10.24.340 (hex=0a.18.154)
insert pending prepared tran, scn=5017243 (hex=0.004c8e9b)
2、查询DBA_2PC_PENDING
select * from dba_2pc_pending where local_tran_id='10.24.340';
LOCAL_TRAN_ID : 10.24.340
GLOBAL_TRAN_ID : <GLOBAL_NAME>.ea27958e.9.46.338
STATE : prepared
MIXED : no
ADVICE :
TRAN_COMMENT :
FAIL_TIME : 02-nov-2010 02:06:02
FORCE_TIME :
RETRY_TIME : 02-nov-2010 02:06:02
OS_USER : <OS_USER_NAME>\<PASSWORD>
OS_TERMINAL : <HOST>
HOST : <HOST>
DB_USER : <DB_USER_NAME>
COMMIT# : 5017243
-
该节点不是全局协调器,因为 local_tran_id 与 Global_Tran_ID 的最后部分不同;即分布式事务不是源自该节点。
-
GLOBAL_TRANSACTION_ID 表示公共事务 ID,对于分布式事务,该 ID 在每个节点上都相同。它的格式为global_database_name.hhhhhhhh.local_transaction_id,其中 global_database_name 是全局协调器的数据库名称,hhhhhhhh以十六进制表示全局协调器的内部数据库标识符。
-
该节点的交易处于 PREPARED 状态
-
查看 ADVICE 和 TRAN_COMMENT 列以获取有关此事务的信息,如果填充了这些列中的任何一个,它们可以帮助您决定是否应回滚或提交事务的本地部分。(COMMIT COMMENT… 或 SET TRANSACTION… NAME 填充 tran_comment 列)
3、查询 DBA_2PC_NEIGHBORS
select * from dba_2pc_neighbors;
LOCAL_TRAN_ID : 10.24.340
IN_OUT : in
DATABASE : <GLOBAL_NAME>
DBUSER_OWNER : <DB_USER_NAME>
INTERFACE : N
DBID : ea27958e
SESS# : 1
BRANCH : 09002E00520100000104
DBA_2PC_NEIGHBORS 提供有关与不确定事务关联的连接的信息。每个连接的信息都不同,具体取决于连接是入站 (IN_OUT = in) 还是出站 (IN_OUT = out)。
IN_OUT = in,表明我们的数据库 (db102c) 是数据库列中指定的 DB102D 客户端的服务器。
DBUSER_OWNER 显示连接到我们的 db102c 数据库的用户
INTERFACE = N 表示 DB102C 或其任何依赖站点都不是提交点站点。
远程节点
select * from dba_2pc_neighbors;
LOCAL_TRAN_ID : 9.46.338
IN_OUT : in
DATABASE :
DBUSER_OWNER : <DB_USER_NAME>
INTERFACE : N
DBID :
SESS# : 1
BRANCH : 0000
-----------------
LOCAL_TRAN_ID : 9.46.338
IN_OUT : out
DATABASE : <GLOBAL_NAME>
DBUSER_OWNER : <DB_USER_NAME>
INTERFACE : N
DBID : bae6b90f
SESS# : 1
BRANCH : 4
对于 OUT 连接:
DBUSER_OWNER 列显示 dblink 的所有者
DATABASE 列显示已访问远程服务器 (db102c) 的数据库链接名称。
本地 txn ID 与 global_transaction_id 的末尾部分匹配,表明该站点是事务发起的全局协调器。
该站点是提交点站点,并且已经提交了事务的本地部分,如状态列所示:
select * from dba_2pc_pending@db102d:
LOCAL_TRAN_ID : 9.46.338
GLOBAL_TRAN_ID : <GLOBAL_NAME>.ea27958e.9.46.338
STATE : committed
MIXED : no
ADVICE :
TRAN_COMMENT :
FAIL_TIME : 02-nov-2010 02:06:02
FORCE_TIME :
RETRY_TIME : 02-nov-2010 02:06:02
OS_USER : <OS_USER>
OS_TERMINAL : <OS_TERMINAL>
HOST : <HOST>
DB_USER : <DB_USER_NAME> COMMIT# : 5017245
结论:该节点已经提交了本地事务,然后崩溃了,导致 GC 仍在等待来自提交点站点的“提交”响应。
4、解决
COMMIT FORCE '<GLOBAL_NAME>.ea27958e.9.46.338','5017245';
-OR-
COMMIT FORCE '10.24.340','5017245';
5、清除视图
exec DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('10.24.340');
在混合事务的情况下,数据库的某些部分已经提交,而其他部分已被强制回滚,请使用
exec DBMS_TRANSACTION.PURGE_MIXED('txnID');
6、ORA-30019
注意:如果使用 UNDO_MANAGEMENT=auto 和 DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY 失败并出现
ORA-30019:自动撤消模式下的非法回滚段操作,请使用以下
解决方法:
-- check the current value of _smu_debug_mode (default 0):
column Parameter format a35
column "Session Value" format a15
column "Instance Value" format a15
SELECT a.ksppinm "Parameter", b.ksppstvl "Session Value", c.ksppstvl "Instance Value"
FROM x$ksppi a, x$ksppcv b, x$ksppsv c
WHERE a.indx = b.indx AND a.indx = c.indx AND a.ksppinm LIKE '/_%' escape '/' AND a.ksppinm like '%smu_debug_mode%' /
-- set it temporarily to 4:
SQL> alter system set "_smu_debug_mode" = 4; -- in 9.2x alter session can be used instead.
SQL> commit;
SQL>execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');
SQL> commit; SQL> alter system set "_smu_debug_mode" = ; SQL> commit;
四、定位可疑分布式事务的sql
1、获取事务id
select local_tran_id, commit#, state from DBA_2PC_PENDING;
2、检查对应的日志
select a.thread#, a.sequence#, b.member from v$log a, v$logfile b where a.group# = b.group# and 1585840 between a.FIRST_CHANGE# and a.NEXT_CHANGE#;
select thread#, sequence#, name from v$archived_log where 1585840 between FIRST_CHANGE# and NEXT_CHANGE#;
3、挖掘日志
exec dbms_logmnr.add_logfile('/u01/app/oracle/product/11.2.0.4.0/dbs/arch1_55_937607111.dbf');
EXECUTE DBMS_LOGMNR.START_LOGMNR (OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);
4、查看日志
select OPERATION, TABLE_NAME, SQL_REDO, USERNAME from V$LOGMNR_CONTENTS where XIDUSN=1 and XIDSLT = 16 and XIDSQN=942 order by SCN asc;
五、其他处置方式
1、处理未冻结的交易
SQL> SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID, STATE, MIXED, COMMIT# FROM DBA_2PC_PENDING;
96.22.163456 TESTDB.723a8559.96.22.163456 prepared no 56759427464
-- To Force Rollback
SQL> ROLLBACK FORCE '96.22.163456'
-- To Force Commit
SQL> COMMIT FORCE '96.22.163456'
如果交易状态为“正在收集”,并且执行上述命令,您可能会看到如下错误:
ORA-02058: no prepared transaction found with ID 96.22.163456
执行下面操作
SQL> EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('96.22.163456');
2、处理卡住的交易
我们的最终目标是在XKTUXE表中看不到交易;并确保 PENDING_TRANS 等字典表与此信息一致。
一、情况一
DBA_2PC_PENDING视图有关于我们事务的条目,但实际上没有事务
条件是;当我们向 DBA_2PC_PENDING、PENDING_TRANS$ 等字典视图发出 select 时,我们会看到事务,但 XKTUXE 视图中不存在该事务。
实际的交易条目视图是 XKTUXE ([K]ernel [T]ransaction [U]ndo Transa[X]tion [E]ntry),其中各列对应于交易 id 的以下部分:
KTUXEUSN.KTUXESLT.KTUXESQN = 96.22.163456 (The concat of KTUXEUSN, KTUXESLT and KTUXESQN gives us the transacion number)
KTUXEUSN=96
KTUXESLT=22
KTUXESQN=163456
因此,当 DBA_2PC_PENDING 有条目但 X$KTUXE 没有条目时
SQL> SELECT LOCAL_TRAN_ID, GLOBAL_TRAN_ID, STATE, MIXED, COMMIT# FROM DBA_2PC_PENDING;
-- Returns: 96.22.163456 TESTDB.723a8559.96.22.163456 prepared no 56759427464
SQL> SELECT * FROM X$KTUXE WHERE KTUXEUSN=96 AND KTUXESLT=22 AND KTUXESQN =163456;
-- Returns: No Rows
方法一
SQL> EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('96.22.163456');
方法二
SQL> DELETE FROM SYS.PENDING_TRANS$ WHERE LOCAL_TRAN_ID = '96.22.163456';
SQL> DELETE FROM SYS.PENDING_SESSIONS$ WHERE LOCAL_TRAN_ID ='96.22.163456' ;
SQL> DELETE FROM SYS.PENDING_SUB_SESSIONS$ WHERE LOCAL_TRAN_ID = '96.22.163456';
SQL> COMMIT;
SQL> DELETE FROM SYS.PENDING_TRANS$ WHERE LOCAL_TRAN_ID = '96.22.163456';
SQL> DELETE FROM SYS.PENDING_SESSIONS$ WHERE LOCAL_TRAN_ID ='96.22.163456' ;
SQL> DELETE FROM SYS.PENDING_SUB_SESSIONS$ WHERE LOCAL_TRAN_ID = '96.22.163456';
SQL> COMMIT;
二、情况二
DBA_2PC_PENDING 视图没有有关我们事务的条目,但有一个事务。
这就像字典不知道的孤儿交易。
尝试强制提交或回滚此事务可能会导致如下错误,因为字典不知道:
SQL> ROLLBACK FORCE '96.22.163456'
-- ORA-02058: no prepared transaction found with ID 96.22.163456
此时我们需要做的是;通过将一些虚拟记录插入字典表(因此视图…)然后强制回滚或提交来将我们的事务从孤立状态中恢复:除了事务 ID 之外,您不必更改插入命令中的参数。
SQL> ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY;
SQL> INSERT INTO PENDING_TRANS$ (LOCAL_TRAN_ID, GLOBAL_TRAN_FMT, GLOBAL_ORACLE_ID, STATE, STATUS, SESSION_VECTOR, RECO_VECTOR, TYPE#, FAIL_TIME,RECO_TIME)
VALUES
(
'96.22.163456',
299354,
'XXXXXXX.12345.1.2.3',
'prepared','P',
hextoraw( '00000001' ),
hextoraw( '00000000' ),
0, sysdate, sysdate
);
SQL> INSERT INTO PENDING_SESSIONS$
VALUES
(
'96.22.163456',
1, hextoraw('05004F003A1500000104'),
'C', 0, 30258592, '',
146
);
SQL> COMMIT;
SQL> ROLLBACK FORCE '96.22.163456'
or
SQL> COMMIT FORCE '96.22.163456'
SQL> ALTER SYSTEM ENABLE DISTRIBUTED RECOVERY;
SQL> ALTER SYSTEM SET "_smu_debug_mode" = 4;
SQL> COMMIT;
SQL> EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('96.22.163456');
SQL> ALTER SYSTEM SET "_smu_debug_mode" = 0;
SQL> COMMIT;
三、情况三
DBA_2PC_PENDING 已进入且存在事务,但 COMMIT 或 ROLLBACK 挂起!
SQL> EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('96.22.163456');
-- ERROR at line 1:
-- ORA-06510: PL/SQL: unhandled user-defined exception
-- ORA-06512: at "SYS.DBMS_TRANSACTION", line 94
-- ORA-06512: at line 1
解决
SQL> DELETE FROM SYS.PENDING_TRANS$ WHERE LOCAL_TRAN_ID = '96.22.163456';
SQL> DELETE FROM SYS.PENDING_SESSIONS$ WHERE LOCAL_TRAN_ID ='96.22.163456' ;
SQL> DELETE FROM SYS.PENDING_SUB_SESSIONS$ WHERE LOCAL_TRAN_ID = '96.22.163456';
SQL> COMMIT;
SQL> ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY;
SQL> INSERT INTO PENDING_TRANS$ (LOCAL_TRAN_ID, GLOBAL_TRAN_FMT, GLOBAL_ORACLE_ID,
STATE, STATUS, SESSION_VECTOR, RECO_VECTOR, TYPE#, FAIL_TIME,RECO_TIME)
VALUES
(
'96.22.163456',
306206,
'XXXXXXX.12345.1.2.3',
'prepared','P',
hextoraw( '00000001' ),
hextoraw( '00000000' ),
0, sysdate, sysdate
);
SQL> INSERT INTO PENDING_SESSIONS$
VALUES
(
'96.22.163456',
1, hextoraw('05004F003A1500000104'),
'C', 0, 30258592, '',
146
);
SQL> COMMIT;
SQL> COMMIT FORCE '96.22.163456';
SQL> EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('96.22.163456');
五、ORA-30013
ORA-30013是指定Undo表空间正在使用时报错。换句话说,这意味着有一些后台进程仍在使用撤消表空间。
当实例提到的撤消表空间已在使用中时,RAC 数据库就会发生这种情况。解决方案是为所有实例设置单独的撤消表空间。
由于 undo_tablespace 是实例本地参数,因此我们必须确保在与发出“Alter system”命令的实例不同的实例上调用“Alter system set undo_tablespace”。
alter system set undo_tablespace= <undo tablespace name> sid='<instance name>';
六、ORA-1548
ORA-1548 是当您尝试删除包含活动回滚段(即回滚所需的段)的表空间或存在需要事务恢复的死事务时报告的错误。只有清除访问Undo Segment的活动(或死)事务后才能删除表空间。如果事务由于各种原因(例如撤消数据文件脱机或不可访问、撤消需要恢复等)而无法回滚,也可能会发生此问题。
select segment_id, segment_name,status,tablespace_name from dba_rollback_segs where status not in ('ONLINE','OFFLINE');
情况 1:撤消段中存在活动或死亡事务。
Select segment_name,status,tablespace_name from dba_rollback_segs where status not in ('ONLINE','OFFLINE') ;
如果存在状态为“部分可用”的段,则意味着它们仍有待处理的活动事务,并且在提交或回滚事务之前您无法删除表空间。如果发生死事务,必须等待恢复完成。
select KTUXEUSN, KTUXESLT, KTUXESQN, KTUXESTA, KTUXECFL, KTUXESIZ
from x$ktuxe
where KTUXESTA='ACTIVE' and KTUXECFL='DEAD';
可以使用 KTUXESIZ 列监视恢复情况。随着恢复的进展,这种情况将会减少。一旦事务恢复,可以尝试删除Undo表空间
情况 2:由失效分布式事务持有的撤消段
在这种情况下,问题是由死分布式事务引起的。在尝试删除撤消表空间之前,我们必须清除失效的分布式事务。
要检查回滚段上是否有任何活动事务:
SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
KTUXESTA Status,
KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta!='INACTIVE';
如果状态显示为“准备”,则意味着这是一个分布式事务,应该提交或回滚。
您可以使用以下查询来检查可疑交易:
SELECT LOCAL_TRAN_ID,GLOBAL_TRAN_ID,STATE,MIXED,COMMIT# FROM DBA_2PC_PENDING;
SELECT LOCAL_TRAN_ID,IN_OUT,DATABASE,INTERFACE FROM dba_2pc_neighbors;
必须清理没有相应 dba_2pc 条目的分布式事务
情况3:当Undo Segment需要恢复时
Select segment_name,status,tablespace_name from dba_rollback_segs where status not in ('ONLINE','OFFLINE') ;
情况 4:如果设置了事件 10513。
检查警报日志文件是否设置了事件 10513。
event="10513 trace name context forever, level 2"
动态修改
SQL> oradebug setorapid <SMON's Oracle PID>
SQL> oradebug event 10513 trace name context forever, level 2
如果设置了事件 10513,则将禁用从 SMON 进行事务恢复,因此撤消段状态不会更改。因此,如果设置了该事件,请在删除该事件后重新启动数据库并监视失效事务的恢复情况。
事件重置后,您可以使用以下方式监控事务恢复进度:
select KTUXEUSN, KTUXESLT, KTUXESQN, KTUXESTA, KTUXECFL, KTUXESIZ
from x$ktuxe
where KTUXESTA='ACTIVE' and KTUXECFL='DEAD';
启用闪回数据存档器 (FBDA)
撤消表空间删除操作被阻止,因为某些事务被标记为必须存档以进行闪回
SELECT a.ksppinm "Parameter",
b.ksppstvl "Session Value",
c.ksppstvl "Instance Value"
FROM sys.x$ksppi a, sys.x$ksppcv b, sys.x$ksppsv c
WHERE a.indx = b.indx
AND a.indx = c.indx
AND a.ksppinm LIKE '%flashback%';
ALTER SYSTEM SET "_disable_flashback_archiver"=0 SCOPE=SPFILE;




