PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : Optimisation » Pouvoir lancer deux fonctions qui utilisent la même table » 16/12/2011 12:02:27

Merci à tous pour vos réponses,

Marc Cousin je vais tenter ta solution.

#2 Optimisation » Pouvoir lancer deux fonctions qui utilisent la même table » 14/12/2011 19:30:10

vince44
Réponses : 4

Bonjour,

Je suis actuellement sur un postGresql 9.1 (depuis peu car migration depuis mysql).
J'ai certains calculs qui s'exécutent en base (base type décisionnel), pour une base mon calcul est trop lent alors je voulais pourvoir lancer plusieurs fois la procédure. J'ai fait ce qu'il fallait, mais un problème dans ma procédure m'embête...

En gros le problème:
- au début de la procédure je mets à jour un champ dans un table pour dire que je suis en cour de traitement puis j'effectue mes calculs. -> En solo ça marche
- Lorsque je lance le deuxième il retape sur les mêmes lignes (que j'ai locké) car mon update fait au début de ma procédure n'est pas commité, il essai donc de locker les mêmes ligne...

Ma question:
- Est-il possible à l'intérieur de ma fonction de faire un 2 commits (un au début puis un autre à la fin).

Si ça peut aider voici la procedure:



CREATE OR REPLACE FUNCTION execCalc()
RETURNS VOID
AS $$
DECLARE statsLocked boolean DEFAULT false;
DECLARE statId INT DEFAULT 0;
DECLARE _tstamp TIMESTAMP;
DECLARE _tag varchar(50) DEFAULT '';
DECLARE deviceId varchar(50) DEFAULT '';
DECLARE _ctx1 varchar(300) DEFAULT '';
DECLARE _ctx2 varchar(300) DEFAULT '';
DECLARE _ctx3 varchar(300) DEFAULT '';
DECLARE _ctx4 varchar(300) DEFAULT '';
DECLARE _ctx5 varchar(300) DEFAULT '';
DECLARE first smallint DEFAULT 0;
DECLARE beginDate TIMESTAMP;
DECLARE endDate TIMESTAMP;
DECLARE curStats refcursor;
DECLARE _bloc int DEFAULT 2500;
BEGIN
    --SELECT pg_try_advisory_lock(12345) INTO statsLocked;
   
    --IF statsLocked = true THEN
   
        PERFORM 1 FROM fill_general_tables();
       
        select cast(value as integer) into _bloc from parametrage where key = 'bloc_exec';
       
        --BEGIN;
        --START TRANSACTION READ COMMITTED
       
            --LOCK TABLE stats_raw_temp IN ACCESS SHARE MODE;
           
            CREATE TEMPORARY TABLE temp_stats_raw_temp ON commit DROP AS
            SELECT * FROM stats_raw_temp WHERE "lock" = false ORDER BY stat_id ASC LIMIT (select _bloc) FOR UPDATE NOWAIT;
       
                  ------C'est ce update là que je voudrais commiter en cours de travaille.
            UPDATE stats_raw_temp SET "lock" = true WHERE stat_id IN (SELECT stat_id FROM temp_stats_raw_temp);
           
        --END;
        --COMMIT;

       
         PERFORM pg_sleep(60);

   
        --PERFORM pg_advisory_unlock(12345);
       
        PERFORM 1 FROM processvisit();


        OPEN curStats FOR SELECT "stat_id","stat_time","tag","device_id","ctx1","ctx2","ctx3","ctx4","ctx5" FROM temp_stats_raw_temp ORDER BY stat_id ASC;
        LOOP
            FETCH curStats INTO statId, _tstamp, _tag, deviceId, _ctx1, _ctx2, _ctx3, _ctx4, _ctx5;
            EXIT WHEN NOT FOUND;
            IF first = 0 THEN
                beginDate := _tstamp;
                first := 1;
            END IF;
            endDate := _tstamp;
            PERFORM 1 FROM processStats(statId, _tstamp, _tag, deviceId, _ctx1, _ctx2, _ctx3, _ctx4, _ctx5);
        end LOOP;
   
        DELETE FROM stats_raw_temp WHERE stat_id IN (SELECT stat_id FROM temp_stats_raw_temp);
        PERFORM 1 FROM processStatsEnd(beginDate, endDate);
       
        PERFORM 1 FROM calc_visit_duration_daily();
        PERFORM 1 FROM calc_visit_duration_monthly();
        PERFORM 1 FROM calc_visit_duration_yearly();   
       
    --END IF;
   
EXCEPTION WHEN TRANSACTION_ROLLBACK then
    UPDATE stats_raw_temp SET "lock" = false WHERE stat_id IN (SELECT stat_id FROM temp_stats_raw_temp);
END;
$$ LANGUAGE PLPGSQL;

Pied de page des forums

Propulsé par FluxBB