IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Oracle Discussion :

Ordre d'exécution des requêtes


Sujet :

Oracle

  1. #1
    Membre régulier
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 235
    Points : 82
    Points
    82
    Par défaut Ordre d'exécution des requêtes
    Bonjour à tous,

    Je réalise un select sur une table pour collecter des enregistrements basé sur un marqueur de temps qui est stocké dans un champ de chaque enregistrement. Mon problème est comment être certain que pendant mon select il n'y va pas une écriture dans cette table avec ce marqueur de temps ?

    Est-ce qu'Oracle exécute les requêtes une à une ou bien en parallèle ? Si c'est en parallèle est-ce qu'il y a moyen de mettre un lock pendant mon select pour que les insertion soient faites en décalées ?

    Merci d'avance.

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849
    Par défaut
    Pas besoin, Oracle ira lire la donnée existante au début du lancement de la requête sans bloquer l'éciture de nouvelles données.
    Data Concurrency and Consistency

  3. #3
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 158
    Points : 1 948
    Points
    1 948
    Par défaut
    Une fois que ta requête est exécutée elle ne sélectionnera pas toute nouvelle ligne insérée. Par contre si tu exécutes une 2è fois cette requête et que les lignes insérées ont été commitées entre temps alors oui une 2è exécution les sélectionnera.
    Si tu veux être sûr de travailler avec le même nombre de lignes, au cas où tu dois mettre à jour par la suite ces données sélectionnées, insère leurs ids (rowid ou pk) dans une table temporaire.

  4. #4
    Membre émérite
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2013
    Messages
    1 998
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2013
    Messages : 1 998
    Points : 2 501
    Points
    2 501
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    Une fois que ta requête est exécutée elle ne sélectionnera pas toute nouvelle ligne insérée. Par contre si tu exécutes une 2è fois cette requête et que les lignes insérées ont été commitées entre temps alors oui une 2è exécution les sélectionnera.
    Pas d'accord!
    Tout dépend du niveau d'isolation de ta base : de la lecture ici http://www.dba-oracle.com/t_oracle_isolation_level.htm .
    Idem si tu exécutes ton deuxième SELECT dans la même transaction ou non : s'il est dans une deuxième transaction, alors oui tu verras le nouveau INSERT mais si tu es dans la même transaction que le premier SELECT, normalement tu ne dois pas le voir (et encore, cela dépend de ton fameux niveau d'isolation).

    Petite question : ton deuxième SELECT a lieu dans un programme PL/SQL ou non?

  5. #5
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 158
    Points : 1 948
    Points
    1 948
    Par défaut
    Tu bidouilles souvent le niveau d'isolation d'une base Oracle? Perso j'ai jamais vu une base Oracle où le niveau d'isolation défaut avait été changé.

    1ère session, je fais mon SELECT. J'ai mis un dbms_lock.sleep pour pouvoir faire un insert et commit dans une autre session:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    declare
    v_cnt number;
     
    begin
    select count(*) into v_cnt from gva_table;
    dbms_output.put_line('v_cnt :' || v_cnt);
     
    dbms_lock.sleep(30);
     
    select count(*) into v_cnt from gva_table;
    dbms_output.put_line('v_cnt :' || v_cnt);
     
    end;
    /
     
    v_cnt :4
    v_cnt :5

  6. #6
    Membre régulier
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 235
    Points : 82
    Points
    82
    Par défaut
    Petite question : ton deuxième SELECT a lieu dans un programme PL/SQL ou non?
    C'est un script python qui est lancé par cron toutes les 5mn.

    L'idée du rowid est parfait pour mon cas, je suis certain de ne pas passer à côté d'un enregistrement. Au lieu d'enregistrer les rowid dans une table temporaire j'enregistre le dernier de la requête dans un fichier et la prochaine fois que mon script se lance, il récupère cet id et prend tout ceux qui sont supérieur.

    Edit : A priori le rowid n'ira pas. Dans ma question initial je n'ai pas précisé que les tables sources audith et auditl sont vidées toutes les nuits, donc le "compteur" rowid repart à 0 : https://www.developpez.net/forums/d4...id/#post328026

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT a1.rowid, a.tbl_0, a.evt_0, TO_CHAR(a.dat_0, 'dd-mm-yyyy'), a.hou_0, a.id1_0, a.id2_0, a1.col_0, a1.nval_0, a.SEQ_0 
    FROM audith a
    INNER JOIN auditl a1 ON a1.seq_0 = a.seq_0
    WHERE
            (a.tbl_0 = 'SDELIVERY' OR
            a.tbl_0 = 'SDELIVERYD' OR
            a.tbl_0 = 'SORDER' OR
            a.tbl_0 = 'SORDERP' OR
            a.tbl_0 = 'SORDERQ' OR
            a.tbl_0 = 'SINVOICE' OR
            a.tbl_0 = 'SINVOICEV' OR
            a.tbl_0 = 'OPPOR' OR
            a.tbl_0 = 'SALESREP') AND
            a1.rowid_0 > 'DERNIERROWID'
    ORDER BY a1.rowid DESC;
    Exemple de résultat de ma sans la notion de rowid

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SELECT a.tbl_0, a.evt_0, TO_CHAR(a.dat_0, 'dd-mm-yyyy'), a.hou_0, a.id1_0, a.id2_0, a1.col_0, a1.nval_0, a.SEQ_0 
    FROM audith a
    INNER JOIN auditl a1 ON a1.seq_0 = a.seq_0
    WHERE
            (a.tbl_0 = 'SDELIVERY' OR
            a.tbl_0 = 'SDELIVERYD' OR
            a.tbl_0 = 'SORDER' OR
            a.tbl_0 = 'SORDERP' OR
            a.tbl_0 = 'SORDERQ' OR
            a.tbl_0 = 'SINVOICE' OR
            a.tbl_0 = 'SINVOICEV' OR
            a.tbl_0 = 'OPPOR' OR
            a.tbl_0 = 'SALESREP') AND
            TO_CHAR(a.dat_0, 'dd-mm-yyyy') = TO_CHAR(sysdate, 'dd-mm-yyyy') AND
            a.hou_0 > '102000'
    ORDER BY a1.SEQ_0  DESC
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    TBL_0    |EVT_0 |TO_CHAR(A.DAT_0,'DD-MM-YYYY')|HOU_0 |ID1_0         |ID2_0    |COL_0    |NVAL_0        |SEQ_0 |
    ---------+------+-----------------------------+------+--------------+---------+---------+--------------+------+
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|SOHNUM   |NORHIL22022276|378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|ITMREF   |98109-1       |378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|SOPLIN   |1000          |378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|SOQSTA   |1             |378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|QTY      |1             |378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|ODLQTY   |0             |378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|DLVQTY   |0             |378946|
    SORDERQ  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|SOQSEQ   |1000          |378946|
    SORDERP  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|TSICOD(3)|              |378945|
    SORDERP  |INSERT|18-02-2022                   |102703|NORHIL22022276|1000~1000|TSICOD(4)|              |378945|
    ...
    Dans cette exemple je récupère tout les enregistrements supérieur 10h20:00, ici on voit apparaitre ceux de 10h27:03. Dans mon script j'enregistre que le dernier enregistrement a été horodaté à 10h27:03. Je relance ma requête en changeant le supérieur sur a.hou qui devient :
    Rappel : cron lance le script toutes les 5mn.

    Si j'ai bien compris il est possible que pendant mon 1ere select d'autres enregistrements ai été écrit avec le même horodatage : 102703 puisque étant réalisé à cette heure. Du coups mon second select passe totalement à côté. Il faudrait que la colonne a.hou_0 descende à la microseconde ?

  7. #7
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 957
    Points : 4 386
    Points
    4 386
    Par défaut
    Citation Envoyé par flipflip Voir le message
    Si j'ai bien compris il est possible que pendant mon 1ere select d'autres enregistrements ai été écrit avec le même horodatage : 102703 puisque étant réalisé à cette heure. Du coups mon second select passe totalement à côté. Il faudrait que la colonne a.hou_0 descende à la microseconde ?
    cela diminuera fortement la probabilité de rater un enregistrement mais ne la réduira pas nécessairement à 0.

    Vous pourriez calculer le hash des valeurs de colonnes et conserver celui de la dernière ligne traitée en plus du hou_0,
    le critère de sélection pourrait alors être (en pseudo code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    a.hou >=  DERNIER_HOU AND hash(du row a) <> DERNIER_HASH_ROW_A

  8. #8
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 158
    Points : 1 948
    Points
    1 948
    Par défaut
    La question c'est de savoir ce que tu fais de toutes ces lignes que tu sélectionnes toutes les 5 min? En quoi l'ajout de nouvelles lignes pose problème?

  9. #9
    Membre émérite
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2013
    Messages
    1 998
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2013
    Messages : 1 998
    Points : 2 501
    Points
    2 501
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    Tu bidouilles souvent le niveau d'isolation d'une base Oracle? Perso j'ai jamais vu une base Oracle où le niveau d'isolation défaut avait été changé.
    Non mais c'est bien que flipflip sache comment fonctionne une base de données et comment est géré l'isolation des données.

    Ah, dernière chose, pas la peine de modifier le niveau d'isolation de la base, tu peux le faire dans une session et même dans une transaction.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ALTER SESSION SET ISOLATION_LEVEL=SERIALIZABLE;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE NAME 'TRAN1';

  10. #10
    Membre régulier
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 235
    Points : 82
    Points
    82
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    La question c'est de savoir ce que tu fais de toutes ces lignes que tu sélectionnes toutes les 5 min?
    Je recompose un fichier sql pour que cela soit ré-importé dans une base mysql qui est utilisé comme datawarehouse pour notre BI (Metabase).

    En quoi l'ajout de nouvelles lignes pose problème?
    L'ajout de lignes n'est pas un problème, c'est la dé-synchronisation mon problème.

    Exemple :
    • imaginons qu'un premier select a été fait à 7h20:10;
    • des données s'enregistre dans les tables et je lance à nouveau mon second select à 7h25:00. La requête va jusqu'au bout et j'inscris dans un fichier l'heure du dernier lancement, soit 7h25:00;
    • prochain lancement à 7h30:00. Dans mon troisième select la condition where est que hou_0 > 7h25:00. Il va me prendre tout les enregistrements compris entre 7h25:01 le dernier enregistrement.


    C'est ici qu'intervient le problème et il faut se concentrer sur le 7h25:00. Pendant mon 2eme select au même moment il y a des enregistrements qui ont été ajoutés avec le marqueur 7h25:00 et ce n'est pas une erreur car ils se sont bien passés pendant se laps de temps. Du coups, dans le 3eme select, comme je prends ceux supérieur à 7h25:00 j'exclue forcément ces enregistrements. Au final, ils ne sont pas dans le 2eme select car non existant à l'instant T et ils ne sont pas dans le 3eme car le marqueur de temps est dépassé.


    Données dans au second select
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    TBL_0    |EVT_0 |TO_CHAR(A.DAT_0,'DD-MM-YYYY')|HOU_0 |ID1_0         |ID2_0    |COL_0    |NVAL_0        |SEQ_0 |
    ---------+------+-----------------------------+------+--------------+---------+---------+--------------+------+
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|SOHNUM   |NORHIL22022276|378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|ITMREF   |98109-1       |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|SOPLIN   |1000          |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|SOQSTA   |1             |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|QTY      |1             |378946|
    Données dans les tables au troisième select
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TBL_0    |EVT_0 |TO_CHAR(A.DAT_0,'DD-MM-YYYY')|HOU_0 |ID1_0         |ID2_0    |COL_0    |NVAL_0        |SEQ_0 |
    ---------+------+-----------------------------+------+--------------+---------+---------+--------------+------+
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|SOHNUM   |NORHIL22022276|378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|ITMREF   |98109-1       |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|SOPLIN   |1000          |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|SOQSTA   |1             |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|QTY      |1             |378946|
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|ODLQTY   |0             |378946| --> enreg fait pendant le second select
    SORDERQ  |INSERT|18-02-2022                   |072500|NORHIL22022276|1000~1000|DLVQTY   |0             |378946| --> enreg fait pendant le second select
    En 1 semaine de test et validation de données cela c'est produit une fois, mais c'est la fois de trop car les données deviennent incohérentes et surtout, sauf à tout ré-importer, le décalage ne se corrigera jamais.

    cela diminuera fortement la probabilité de rater un enregistrement mais ne la réduira pas nécessairement à 0.
    J'ai pensé à l'idée du hash vendredi soir mais j'avoue ne pas avoir eu le courage de me lancer la dedans avant le week-end Je viens de faire un test

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SELECT a.tbl_0, a.evt_0, TO_CHAR(a.dat_0, 'dd-mm-yyyy'), a.hou_0, a.id1_0, a.id2_0, a1.col_0, a1.nval_0, a.SEQ_0, ORA_HASH(a.TBL_0||a.EVT_0||a.HOU_0||a.ID1_0||a1.COL_0||a1.NVAL_0||a.SEQ_0) hash 
    FROM audith a
    INNER JOIN auditl a1 ON a1.seq_0 = a.seq_0
    WHERE
            (a.tbl_0 = 'SDELIVERY' OR
            a.tbl_0 = 'SDELIVERYD' OR
            a.tbl_0 = 'SORDER' OR
            a.tbl_0 = 'SORDERP' OR
            a.tbl_0 = 'SORDERQ' OR
            a.tbl_0 = 'SINVOICE' OR
            a.tbl_0 = 'SINVOICEV' OR
            a.tbl_0 = 'OPPOR' OR
            a.tbl_0 = 'SALESREP') AND
    	TO_CHAR(a.dat_0, 'dd-mm-yyyy') = TO_CHAR(sysdate, 'dd-mm-yyyy') AND 
            a.HOU_0 >= '080000' AND ORA_HASH(a.TBL_0||a.EVT_0||a.HOU_0||a.ID1_0||a1.COL_0||a1.NVAL_0||a.SEQ_0) <> '4294387501'
    ORDER BY a.HOU_0  DESC
    J'obtiens bien un hash unique pour chaque enreg.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TBL_0     |EVT_0 |TO_CHAR(A.DAT_0,'DD-MM-YYYY')|HOU_0 |ID1_0         |ID2_0      |COL_0       |NVAL_0         |SEQ_0 |HASH      |
    ----------+------+-----------------------------+------+--------------+-----------+------------+---------------+------+----------+
    SORDERP   |INSERT|21-02-2022                   |083444|NORHIL22022351|2000~2000  |TSICOD(3)   |               |391841|4294952083|
    SORDERQ   |UPDATE|21-02-2022                   |085408|NORHIL22022341|1000~1000  |DLVQTY      |1              |392276|4294827484|
    SDELIVERYD|INSERT|21-02-2022                   |080023|LIVHIL22021931|1000       |ITMREF      |0-36117        |389467|4294761504|
    SDELIVERY |INSERT|21-02-2022                   |085836|LIVHIL22021973|           |TSCCOD(2)   |DER            |392462|4294387501|
    SDELIVERYD|INSERT|21-02-2022                   |081645|LIVHIL22021948|4000       |TSICOD(1)   |               |390584|4294129044|
    SDELIVERYD|INSERT|21-02-2022                   |080639|LIVHIL22021939|3000       |NETPRINOT   |0              |389897|4293792934|
    SDELIVERYD|INSERT|21-02-2022                   |085608|LIVHIL22021971|3000       |REP1        |006            |392354|4293655423|
    Pour que la condition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            a.HOU_0 >= '080000' AND ORA_HASH(a.TBL_0||a.EVT_0||a.HOU_0||a.ID1_0||a1.COL_0||a1.NVAL_0||a.SEQ_0) <> '4294387501'
    Marche il faudrait que je n'ai qu'un seul nouvel enregistrement avec le marqueur 080000, hors il est possible que plusieurs enregistrements ai la même heure et je devrais prendre le hash supérieur et non différent. Hors à priori le calcul de hash n'est pas forcément "augmentant"

    Non mais c'est bien que flipflip sache comment fonctioinne une base de données et comment est géré l'isolationd es données.
    Surtout que j'aime bien comprendre comment ça marche. Je n'ai pas encore tout compris et mon faible niveau d'anglais n'aide pas.

  11. #11
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849
    Par défaut
    Vous pouvez regarder cette discussion qui m'a l'air de correspondre à votre problème :
    Selecting rows that have changed via timestamp problematic with non-blocking read

    Particulièrement cette réponse :
    something I just thought of....


    Your logic to sync must be something like:


    T0 - log into source database;
    T1 -
    T2 - get NEW_DATE/TIME to be used for next sync;
    T3 - get all rows in table(s) where timestamp >= DATE/TIME from last sync;
    T4 - logout


    Ok, you are worried about missing rows in oracle such that they were in flight transactions (modifications taking place during T1 basically)

    They would have a timestamp T1, but you would have a timestamp T2 for the next retrieval and hence would "miss them"


    If you change T2 to:

    select nvl( min(to_date(start_time,'mm/dd/rr hh24:mi:ss')),sysdate)
    from v$transaction;

    what you'll have is the date time of either

    a) right now if no one is doing a transaction (no chance of a missed record) or
    b) the timestamp of the last time no one WAS doing an in flight transaction


    sure -- it opens the window for dups (but you have that already -- the dup window is not a nano-second or even a second, it it the time it takes for T3 to complete which could be measurable) but it prevents you from missing anything and leaves your code intact.

  12. #12
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 158
    Points : 1 948
    Points
    1 948
    Par défaut
    Dans tes tables source tu dois bien avoir un identifiant unique (pk par exemple)? Dans ce cas c'est cet identifiant qu'il faut utiliser pour ta sélection.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    select * from les_tables...
    where id > max(id) de_la_précédente_extraction

  13. #13
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    Dans tes tables source tu dois bien avoir un identifiant unique (pk par exemple)? Dans ce cas c'est cet identifiant qu'il faut utiliser pour ta sélection.
    Tu ne peux pas garantir que l'id généré pour la transaction 1 soit bien commité avant l'id généré pour la transaction 2.

    Je pense que le seul moyen est d'aller regarder dans V$transactions s'il y a des transactions en cours pour en déduire une date de fin de collectes des données.
    Il faut juste gérer le problèmes des données potentiellement déjà collectées.

    Évidemment il est toujours possible de mettre un lock exclusif sur l'ensemble de la table, mais ça perturbera également fortement le système transactionnelle existant.

  14. #14
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 158
    Points : 1 948
    Points
    1 948
    Par défaut
    C'est pas faux. Il faudrait en savoir davantage sur le mécanisme d'alimentation des tables. En général je suis pas chaud pour aller voir dans une vue dynamique Oracle quand on fait du métier, d'autant plus qu'il n'aura pas forcément les privilèges pour aller la consulter.
    Si possibilité d'ajouter une colonne "statut" à la table source, alors il y aurait possibilité de mettre à jour ce statut une fois les lignes extraites. Au prochain SELECT il ne sélectionnerait que les lignes au statut "en attente".

  15. #15
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Ce que vous avez besoin c'est de faire du CDC (change data capture) basés sur les logs.

    Oracle a un outil qui marche bien mais très coûteux (Goldengate).
    Oracle propose aussi son LogMiner (je viens de voir qu'ils le décommissionnent en 19) qui est au moins la première brique mais nécessite du développement.
    Sinon de nombreux éditeurs proposent des solutions de CDC (en général basées sur le logminer précité, je me demande comment ils vont gérer les bases 19+).

  16. #16
    Membre émérite
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2013
    Messages
    1 998
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2013
    Messages : 1 998
    Points : 2 501
    Points
    2 501
    Par défaut
    Qu'est-ce que tu entends par décommissionner ?

  17. #17
    Membre régulier
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 235
    Points : 82
    Points
    82
    Par défaut
    C'est pas faux. Il faudrait en savoir davantage sur le mécanisme d'alimentation des tables. En général je suis pas chaud pour aller voir dans une vue dynamique Oracle quand on fait du métier, d'autant plus qu'il n'aura pas forcément les privilèges pour aller la consulter.
    Malheureusement j'ai pas accès à cette info, c'est la machinerie de Sage X3

    Si possibilité d'ajouter une colonne "statut" à la table source, alors il y aurait possibilité de mettre à jour ce statut une fois les lignes extraites. Au prochain SELECT il ne sélectionnerait que les lignes au statut "en attente".
    C'est une bonne idée. Cela impose du dev pour mon intégrateur et puis du coups je jette mon script python car on a une règle : interdiction d'écrire directement dans la base hors ERP sous peine de pendaison par les c...heuveux.

    Oracle a un outil qui marche bien mais très coûteux (Goldengate).
    On m'en a parlé mais c'est largement au dessus de nos moyens Pour logminer, pour le moment nous sommes encore en 10gR2 mais d'ici l'année prochaine on va migrer sur plus récent, du coups je me vois pas trop investir sur un programme qui n'existe plus.

    <mode DBA Mc Gyver>
    Je pourrais faire un count(*) avoir le nombre d'enregistrement à l'instant T, j'écris ce résultat dans un fichier. Au prochain lancement je refais un count(*) et cela me permet de faire un limit

    Exemple :
    - select 1 : count = 1500 enreg
    - j'écris 1500
    - select 2 : count = 1520 enreg
    - limit entre (1500+1),1520
    </mode DBA Mc Gyver>
    C'est pas propre, c'est pas dans les règles de l'art mais avec beaucoup de chance cela pourrait marcher ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    SELECT * FROM 
    (
    	SELECT t.*, ROWNUM rnum FROM
    	(
    		SELECT a.tbl_0, a.evt_0, TO_CHAR(a.dat_0, 'dd-mm-yyyy'), a.hou_0, a.id1_0, a.id2_0, a1.col_0, a1.nval_0, a.SEQ_0
    		FROM audith a
    		INNER JOIN auditl a1 ON a1.seq_0 = a.seq_0
    		WHERE
    		        (a.tbl_0 = 'SDELIVERY' OR
    		        a.tbl_0 = 'SDELIVERYD' OR
    		        a.tbl_0 = 'SORDER' OR
    		        a.tbl_0 = 'SORDERP' OR
    		        a.tbl_0 = 'SORDERQ' OR
    		        a.tbl_0 = 'SINVOICE' OR
    		        a.tbl_0 = 'SINVOICEV' OR
    		        a.tbl_0 = 'OPPOR' OR
    		        a.tbl_0 = 'SALESREP') AND
    		   		TO_CHAR(a.dat_0, 'dd-mm-yyyy') = TO_CHAR(sysdate, 'dd-mm-yyyy')
    		ORDER BY a.HOU_0 ASC
    	) t
    	WHERE ROWNUM <= :MAX_ROW_TO_FETCH)
    WHERE rnum >= :MIN_ROW_TO_FETCH;
    Dans Dbeaver cela marche en remplissant les variables :MAX_ROW_TO_FETCH et MIN_ROW_TO_FETCH. Mais me vient une question. ROWNUM donne le nombre de lignes au moment de la requête ou bien est-ce une valeur fixe, genre est-ce que ma ligne 6 renvoyé par le rownum à 17h09:00 sera la même ligne que la 6 renvoyé par le rownum de 17h15:00 ?

  18. #18
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Citation Envoyé par Ikebukuro Voir le message
    Qu'est-ce que tu entends par décommissionner ?
    Apparemment c'est l'option "CONTINUOUS MINE" qui est dépréciée :
    https://docs.oracle.com/en/database/...0-14102C60DC98

  19. #19
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 957
    Points : 4 386
    Points
    4 386

  20. #20
    Membre régulier
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2008
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mai 2008
    Messages : 235
    Points : 82
    Points
    82
    Par défaut
    Bonjour à tous,

    J'ai continué à creuser sur l'idée d'utiliser le limit pour récupérer les derniers enregistrements. Maintenant ma requête ressemble à ça (pour rappel c'est intégré dans un script python) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    SET TRIMSPOOL ON 
    SET HEAD OFF 
    SET HEADING OFF 
    SET HEADSEP OFF 
    SET FEEDBACK OFF 
    SET ECHO OFF 
    SET PAGES 0
    SET PAGESIZE 0 
    SET TAB OFF 
    SET LINESIZE 1000
    SET TERMOUT OFF
    SET COLSEP |
     
    spool """ + fileSrc + """ 
    SELECT colonnes||'|'||rnum FROM
    (
            SELECT 
                    /* + FIRST_ROWS(n) */ 
                    t.tbl_0||'|'||t.evt_0||'|'||t.dat_0||'|'||t.hou_0||'|'||t.id1_0||'|'||t.id2_0||'|'||t.col_0||'|'||t.nval_0||'|'||t.seq_0 colonnes,
                    ROWNUM rnum
            FROM (
                    SELECT a.tbl_0,a.evt_0,TO_CHAR(a.dat_0, 'dd-mm-yyyy') dat_0,a.hou_0,a.id1_0,a.id2_0,a1.col_0,a1.nval_0,a.seq_0
                    FROM XXXX.audith a
                    INNER JOIN XXXX.auditl a1 ON a1.seq_0 = a.seq_0
                     WHERE
                            (a.tbl_0 = 'SORDER' OR
                            a.tbl_0 = 'SORDERP' OR
                            a.tbl_0 = 'SORDERQ' OR
                            a.tbl_0 = 'SDELIVERY' OR
                            a.tbl_0 = 'SDELIVERYD' OR
                            a.tbl_0 = 'SINVOICE' OR
                            a.tbl_0 = 'SINVOICEV' OR
                            a.tbl_0 = 'OPPOR' OR
                            a.tbl_0 = 'SALESREP') AND
                            TO_CHAR(a.dat_0, 'dd-mm-yyyy') = TO_CHAR(sysdate, 'dd-mm-yyyy')
                    ORDER BY a.HOU_0 ASC
            ) t
            WHERE ROWNUM <= 1000000) /* MAX */
    WHERE rnum > """ + numrow + """; /* MIN */
    spool off
    exit
    A chaque lancement mon script récupère dans un fichier le numéro de ligne du dernier enregistrement précédament exporté et l'utilise comme point de départ pour exporter tout ceux supérieurs. Les premiers tests ont l'air concluant et vu le faible nombre de lignes écrites entre chaque requêtes, le temps de traitement est largement acceptable et sans impact sur la prod.

    il va juste falloir que je gère le changement de jour, en effet les tables d'audit(l, h) sont purgées toutes les nuits, donc lors du premier lancement de l'export après purge le numéro de ligne doit être à 0 et non le dernier numéro de ligne de la précédente requête.

Discussions similaires

  1. [Power BI] Ordre d'exécution des requêtes
    Par italia57 dans le forum Power BI
    Réponses: 0
    Dernier message: 10/11/2014, 11h53
  2. [EG] Ordre d'exécution des requêtes d'un projet
    Par Pierre-Henri ROBLOT dans le forum Outils BI
    Réponses: 7
    Dernier message: 12/09/2014, 13h16
  3. Ordre d'exécution des requêtes
    Par magicbisous-nours dans le forum Requêtes
    Réponses: 2
    Dernier message: 01/10/2012, 16h02
  4. [JMeter] Ordre aléatoire d'exécution des requêtes
    Par aya02 dans le forum Tests et Performance
    Réponses: 0
    Dernier message: 27/10/2010, 11h42
  5. ordre d'exécution des événements onblur et onfocus
    Par letycaf dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 23/05/2006, 15h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo