oracle创建全局临时表

And*_*rew 0 oracle plsql stored-procedures locking transactions

我遇到过并行运行许多访问同一个表的程序的情况。当我尝试并行运行这些程序时,我可以看到很少有程序抛出错误ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired。这些表是临时表,我首先删除旧数据然后插入。并再次为下一个程序运行做同样的事情。所以在这种情况下,我遇到了多个过程尝试访问同一个表并尝试执行 DML 操作的情况。我有针对这种情况创建全局临时表的解决方案:

CRATE GLOBAL TEMPORARY TABLE TEMP_ACTIVATE_OPTION(
  ID   NUMBER,
  ... -- your columns
)
ON COMMIT DELETE ROWS; 
Run Code Online (Sandbox Code Playgroud)

但由于我是这个解决方案的新手,我真的不知道它是如何工作的。例如,如果一个过程正在运行并尝试访问该表TEMP_ACTIVATE_OPTION以进行 DML 操作,而另一个过程并行运行并尝试访问同一个表TEMP_ACTIVATE_OPTION进行 DML 操作,那么是否有可能发生数据丢失或冲突?全局临时表如何管理会话或事务?如果过程尝试对该表执行 dml 操作并等待释放表上的锁以便另一个过程可以访问同一个表,它是否对表执行锁定?

PROCEDURE                    "EXT_10024_ACTIVATE_OPTION"(IN_KPI_DEF_ID IN NUMBER DEFAULT 0) AS

IN_EVENT_ID NUMBER;
err_code VARCHAR(100);
err_msg VARCHAR(100);
IN_OBJECT_NAME VARCHAR2(100);

CURSOR KPI_DEF_CUR IS
Select KPI_DEF_ID,BUSINESS_CHECK_PERIOD_ID,BUS_CHK_PRD_ID_1,
CASE WHEN BUSINESS_CHECK_PERIOD_UNIT_ID=11 THEN 'MINUTE'
WHEN BUSINESS_CHECK_PERIOD_UNIT_ID=12 THEN 'HOUR'
WHEN BUSINESS_CHECK_PERIOD_UNIT_ID=13 THEN 'DAY'
WHEN BUSINESS_CHECK_PERIOD_UNIT_ID IS NULL THEN 'MINUTE'
END AS BUSINESS_CHECK_PERIOD_UNIT_ID,
CASE WHEN BUSINESS_CHK_PERIOD_VAL IS NULL THEN 0
ELSE BUSINESS_CHK_PERIOD_VAL END AS BUSINESS_CHK_PERIOD_VAL,
CASE WHEN BUS_CHK_PRD_UNIT_ID_1=11 THEN 'MINUTE'
WHEN BUS_CHK_PRD_UNIT_ID_1=12 THEN 'HOUR'
WHEN BUS_CHK_PRD_UNIT_ID_1=13 THEN 'DAY'
WHEN BUS_CHK_PRD_UNIT_ID_1 IS NULL THEN 'MINUTE'
END AS BUS_CHK_PRD_UNIT_ID_1,
CASE WHEN BUS_CHK_PRD_VAL_1 IS NULL THEN 0
ELSE BUS_CHK_PRD_VAL_1 END AS BUS_CHK_PRD_VAL_1,
EVENT_ID FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION where KPI_DEF_ID = IN_KPI_DEF_ID;

BEGIN

--delete the data from TEMP_SERVICE_OPTION and TEMP_SERVICE_OPTION_EXTRACTION
Delete from TEMP_ACTIVATE_OPTION;
Delete from TEMP_SERVICE_OPTION_EXTRACTION;
Delete from TEMP_SERVICE_OPTION;

DELETE FROM CAPTURED_DATA_ERROR WHERE EVENT_TIMESTAMP < SYSDATE - 60 and EVENT_ID=10024;

-- removed, retrieve  a new START_ID from source first, don't use the last id.
-- SELECT LAST_TASK_ID INTO LAST_SO_ID FROM CAPTURING where DB_TABLE='TEMP_SERVICE_OPTION';
--SELECT MIN(SO.ID) INTO LAST_SO_ID FROM SERVICE_OPTION@FONIC_RETAIL SO WHERE SO.ID >= to_char(SYSDATE -1, 'YYYYMMDDHH24MISS')||'0000';

Select EVENT_ID INTO IN_EVENT_ID FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION where KPI_DEF_ID = IN_KPI_DEF_ID;

FOR KPI_DEF_ROW IN KPI_DEF_CUR
LOOP

BEGIN
INSERT INTO TEMP_ACTIVATE_OPTION(ID,ICC,ASSIGNED_ANUMBER_ID,SERVICE_ID,PRODUCT_OPTION_ID,STATUS_ID,END_DATE,PRODUCT_TYPE_KEY)
Select DISTINCT(SO.ID),SIM.ICC,SIM.ASSIGNED_ANUMBER_ID,SO.SERVICE_ID,SO.PRODUCT_OPTION_ID,SO.STATUS_ID,SO.END_DATE,SIM.PRODUCT_TYPE_KEY FROM
SIMCARD@FONIC_RETAIL SIM
  JOIN SERVICE_OPTION@FONIC_RETAIL SO ON SO.SERVICE_ID=SIM.ASSIGNED_TO_SERVICE_ID
 where SO.STATUS_ID IN (20,40)
and SO.ID < to_char(SYSDATE - numtodsinterval (  KPI_DEF_ROW.BUSINESS_CHK_PERIOD_VAL,KPI_DEF_ROW.BUSINESS_CHECK_PERIOD_UNIT_ID ), 'YYYYMMDDHH24MISS')||'0000'
 and SO.ID > to_char(SYSDATE - numtodsinterval ( KPI_DEF_ROW.BUS_CHK_PRD_VAL_1, KPI_DEF_ROW.BUS_CHK_PRD_UNIT_ID_1 ), 'YYYYMMDDHH24MISS')||'0000'
and NOT EXISTS(SELECT ID from TEMP_ACTIVATE_OPTION T WHERE T.ID = SO.ID );

EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND exception in EXT_10024_ACTIVATE_OPTION - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID));
RAISE;

END;

commit;

BEGIN
INSERT INTO TEMP_SERVICE_OPTION_EXTRACTION(ID,ICC,ASSIGNED_ANUMBER_ID,SERVICE_ID,PRODUCT_OPTION_ID,STATUS_ID,END_DATE,A_NUMBER,PRODUCT_TYPE_KEY)
Select DISTINCT(SO.ID),SO.ICC,SO.ASSIGNED_ANUMBER_ID,SO.SERVICE_ID,SO.PRODUCT_OPTION_ID,SO.STATUS_ID,SO.END_DATE,AN.A_NUMBER,SO.PRODUCT_TYPE_KEY FROM
TEMP_ACTIVATE_OPTION SO JOIN
PRODUCT_OPTION@FONIC_RETAIL PO ON SO.PRODUCT_OPTION_ID = PO.ID JOIN
PRODUCT_CONFIG@FONIC_RETAIL PC ON PO.OPTION_KEY=PC.DEFAULT_PRODUCT_OPTIONS
JOIN PRODUCT_TYPE@FONIC_RETAIL PT ON PC.ID = PT.PRODUCT_CONFIG_ID
JOIN TEMP_ACTIVATE_OPTION SO ON SO.PRODUCT_TYPE_KEY=PT.KEY
JOIN
A_NUMBER@FONIC_RETAIL AN ON SO.ASSIGNED_ANUMBER_ID = AN.ID
where SO.STATUS_ID IN (20,40)
and NOT EXISTS(SELECT ID from TEMP_SERVICE_OPTION_EXTRACTION T WHERE T.ID = SO.ID );

EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND exception in EXT_10024_ACTIVATE_OPTION - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID));
RAISE;

END;

commit;

BEGIN
--SELF_REGISTRATION ACTIVATE OPTION
INSERT INTO TEMP_SERVICE_OPTION(ID,SERVICE_ID,PRODUCT_OPTION_ID,STATUS_ID,EVENT_TIMESTAMP,END_DATE,EVENT_ID,SUBSCRIPTION_ID,ORDER_NUMBER,A_NUMBER)
Select DISTINCT(SO.ID),SO.SERVICE_ID,SO.PRODUCT_OPTION_ID,SO.STATUS_ID,to_date(substr(SO.ID, 1, 14), 'YYYYMMDDHH24MISS'),SO.END_DATE,
IN_EVENT_ID
,TSM.SUBSCRIPTION_ID,TSM.ORDER_NUMBER,SO.A_NUMBER
from TEMP_SERVICE_OPTION_EXTRACTION SO JOIN TMP_SOAP_MONITORING_IDS TSM
ON SO.A_NUMBER = TSM.MSISDN
where SO.STATUS_ID IN (20,40) and TSM.ORDER_TYPE='SELF_REGISTRATION' and
TSM.CREATE_DATE < SYSDATE - numtodsinterval (  KPI_DEF_ROW.BUSINESS_CHK_PERIOD_VAL,KPI_DEF_ROW.BUSINESS_CHECK_PERIOD_UNIT_ID )
and TSM.CREATE_DATE > SYSDATE - numtodsinterval ( KPI_DEF_ROW.BUS_CHK_PRD_VAL_1, KPI_DEF_ROW.BUS_CHK_PRD_UNIT_ID_1 )
and NOT EXISTS(SELECT ID from TEMP_SERVICE_OPTION T WHERE T.ID = SO.ID )
and TSM.WEB_SERVICE_NAME ='RatorWebShopService' and TSM.WEB_METHOD_NAME ='placeShopOrder';

EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND exception in EXT_10024_ACTIVATE_OPTION - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID));
RAISE;

END;

END LOOP;

commit;

--INSERT TEMP DATA INTO CAPTURED_DATA_01 TABLE
Insert into CAPTURED_DATA_01(SUBSCRIPTION_ID,ENV_ID,BRAND_ID,BP_ID,EVENT_ID,ORDER_ID,STATUS_DESCRIPTION,STATUS_CODE,EVENT_TIMESTAMP)
Select DISTINCT(DCR.SUBSCRIPTION_ID),BBE.ENV_ID,TSM.BRAND_ID,BBE.BP_ID,DCR.EVENT_ID,
DCR.ORDER_NUMBER,
CASE WHEN DCR.STATUS_ID=20 THEN 'OK'
WHEN DCR.STATUS_ID=40 THEN 'ERROR'
END,DCR.STATUS_ID,
DCR.EVENT_TIMESTAMP from TEMP_SERVICE_OPTION DCR JOIN TMP_SOAP_MONITORING_IDS TSM ON TSM.SUBSCRIPTION_ID=DCR.SUBSCRIPTION_ID
JOIN
RATOR_MONITORING_CONFIGURATION.ENV_BRAND_BP_EVENT BBE ON BBE.EVENT_ID = DCR.EVENT_ID JOIN
RATOR_MONITORING_CONFIGURATION.ENVIRONMENT ENV on BBE.ENV_ID=ENV.ENV_ID
JOIN RATOR_MONITORING_CONFIGURATION.BRAND BR ON BBE.BRAND_ID = BR.BRAND_ID
JOIN RATOR_MONITORING_CONFIGURATION.BUSINESS_PROCESS BP ON BBE.BP_ID = BP.BP_ID
AND NOT EXISTS(SELECT CD.SUBSCRIPTION_ID FROM CAPTURED_DATA_01 CD WHERE CD.EVENT_ID = DCR.EVENT_ID AND CD.SUBSCRIPTION_ID = DCR.SUBSCRIPTION_ID);

EXCEPTION WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);

DBMS_OUTPUT.PUT_LINE('OTHERS exception in EXT_10072_REQ_SENT_SPAIN - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID) || err_code || '----' || err_msg || 'OBJECT_NAME->');
RAISE;

COMMIT;


END EXT_10024_ACTIVATE_OPTION;
Run Code Online (Sandbox Code Playgroud)

Tim*_*ler 5

这是关于临时表的官方手册。

临时表的定义对所有会话都是可见的,但临时表中的数据仅对将数据插入该表的会话可见。

总之,你可以觉得仿佛全局临时表的私有实例为您的会话创建该表的当您第一次访问表。内部实际发生的事情是另一回事,但您应该将其留给 Oracle - 您在抽象级别看到的是一个对您的会话完全私有的表。

没有其他会话可以访问您的会话在 GTT 中的数据,并且一旦您关闭会话,数据总是会丢失。没有其他会话可以“锁定”您会话中的行,因为它们不可见,并且不会发生冲突。

您还应该区分事务和会话特定的 GTT。它们分别使用ON COMMIT DELETE ROWS和创建ON COMMIT PRESERVE ROWS,并完全按照这些说明进行操作:特定于事务的 GTT 会在COMMIT您每次发出时清除您的表,而特定于会话的数据会保留数据,直到您的会话结束或您手动将其删除。

您应该注意的一个缺点是,要发出除 truncate 之外的 DDL 语句(例如,alter table),您必须首先终止使用所述 GTT 实例的所有会话。相应地计划您的维护。

  • 没有。两者都将使用自己的数据,没有冲突或任何事情。这就是 GTT 的用途。就像使用常规表一样,您可以有十几个会话同时执行 DML,但由于所有数据都是私有的,因此根据定义不会发生行级冲突。此外,过程不能“拥有”会话 - 您通过连接到您的数据库(使用用户名/密码)并执行过程和/或任何其他语句*在您已启动的会话中来启动会话。 (2认同)