J'ai une situation où je suis en train d'exécuter de nombreuses procédures parallèles qui accèdent à la même table. Lorsque j'essaie d'exécuter ces procédures parallèlement, je peux voir que quelques procédures lancent une erreur ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
. Ces tables sont des tables temporaires dans lesquelles je supprime d'abord les anciennes données avant de les insérer. Et encore faire la même chose pour la prochaine procédure. Donc, dans ce cas, j'ai une situation où plusieurs procédures tentent d'accéder à la même table et essaient d'effectuer des opérations DML. Je solution de création de table temporaire globale pour ce cas:Créer une table temporaire globale dans Oracle
CRATE GLOBAL TEMPORARY TABLE TEMP_ACTIVATE_OPTION(
ID NUMBER,
... -- your columns
)
ON COMMIT DELETE ROWS;
Mais comme je suis nouveau à cette solution, je ne sais pas vraiment comment cela fonctionne. Par exemple, si une procédure est en cours et tente d'accéder à la table TEMP_ACTIVATE_OPTION
pour les opérations DML et qu'une autre procédure s'exécute parallèlement et tente d'accéder à la même table TEMP_ACTIVATE_OPTION
pour les opérations DML alors y a-t-il une possibilité de perte de données ou de conflit? Comment les tables temporaires globales gèrent-elles les sessions de transaction? Est-ce qu'il effectue un verrou sur la table si la procédure essaie de faire des opérations dml sur cette table et attend de libérer le verrou sur la table pour qu'une autre procédure puisse accéder à la même table?
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 [email protected]_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
[email protected]_RETAIL SIM
JOIN [email protected]_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
[email protected]_RETAIL PO ON SO.PRODUCT_OPTION_ID = PO.ID JOIN
[email protected]_RETAIL PC ON PO.OPTION_KEY=PC.DEFAULT_PRODUCT_OPTIONS
JOIN [email protected]_RETAIL PT ON PC.ID = PT.PRODUCT_CONFIG_ID
JOIN TEMP_ACTIVATE_OPTION SO ON SO.PRODUCT_TYPE_KEY=PT.KEY
JOIN
[email protected]_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;
Est-ce que CAPTURED_DATA_ERROR est une table temporaire? Si non, alors je m'attendrais à ce que la suppression sur cette table soit la cause de l'ORA-00054, pas les tables temporaires (car elles ne causeraient pas cette erreur). Aussi: 'distinct' est *** NON *** une fonction. Cela s'applique toujours aux colonnes ** all ** dans l'instruction 'select'. 'distinct (so.id)' n'a aucun sens. –
Comment peut être supprimer sur CAPTURED_DATA_ERROR crée un problème? Ce n'est pas une table temporaire mais il y a très peu de données. – Andrew
Cela peut arriver lorsqu'une deuxième transaction tente de supprimer les * mêmes * lignes d'une autre transaction (même si je m'attendais à ce que le second attende). –