[Db] contatore server side

Domenico L. domenico.lorusso a pleiade.it
Mer 3 Gen 2007 13:05:15 CET


Marcello Vezzelli ha scritto:
> Domenico L. wrote:
>>
>>> Ma fare una lock table in questi casi serve a qualcosa o è una 
>>> bestialità?
>> No mysql 5 ha il lock a livello di riga quindi tutto bene.
>
>
>>
>> Mi lascia un po' da pensare il concetto che è possibile cancellare 
>> l'ultima, in un ambiente concorrente il concetto di ultima è una cosa 
>> che non ci si può permettere di avere.
>
> Supponiamo che la transazione che si occupa di cancellare l'ultima 
> fattura faccia una lock table... consideriamo la cancellazione 
> dell'ultima fattura un evento raro e va bene gestirlo in questo modo.
>
> Se qualcuno posta durante la cancellazione, si becca un errore del 
> tipo "table locked" e fa il rollback. Corretto?
> Gestendo la cosa lato applicativo, si aspetta un attimino e si 
> riprova. Parliamo veramente di centesimi di secondo, ma la questione è 
> concettuale quindi vale la pena discuterne... supponiamo che la 
> cancellazione di un record duri un tempo lungo a sufficienza.
> Finita la transazione della cancellazione, il nuovo post otterrà 
> correttamente il valore numfatt facendo una select dell'ultimo numero 
> di fattura in tabella incrementato di uno.
> Domandone: da quanto ho letto, l'esecuzione del trigger BEFORE INSERT 
> è atomica su ogni tabella, corretto? Ovvero il trigger gira fuori da 
> qualsiasi transazione, quindi sono tutti sequenziali.
uhm.... credo tu abbia capito ma hai scritto il contrario....
allora il dml come tu ben sai deve essere atomico (ACID)

Ora fare una insert (o update o delete) produce l'esecuzione atomica di:


before update (con vincoli sull'accesso alla tabella)
inserimento
validazione constraints (salvo differimento)
after update


Da questa osservazione possiamo iniziare a delineare un soluzione:

tabella Sequenza (id autorincremet ciclico) unica per tutto il db

Before INSERT:
    insert into Sequenza return_isertd_id into id;
    set new:numfat=id;


insert


After Insert:
    delete from Sequenza where id=new.numfat;
   
    begin
        select id+1 into xId
        from fat_seq
        where anno=new.anno for update; #se esiste
        update fat_seq
               set id = xId
        where anno=new.anno;
   exception
        when no_data_found then
            insert into fat_Seq values(new.anno, 1);
          xId = 1;
       when others then raise;
end;

    update fattura
       set numfat=xId
    where anno=new.anno and numfat=new.numfatt
       and ....
    ;
   

   
Più o meno il codice purtroppo non sono sicuro sia corretto, però la 
logica dovrebbe esserci :-)

ciauz

-- 
Domenico L.                             icq: 645 44 861

per stupire mezz'ora basta un libro di storia,
io cercai di imparare la Treccani a memoria... [F.d.A.]



Maggiori informazioni sulla lista Db