Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292

    transazoni VS lock table

    Buon giorno a tutti,
    vorrei chiarire un dubbio che mi porto dietro da parecchio, di norma quando si parla di concorrenza si tirano fuori due strade: lock e transazioni.
    E' chiaro il funzionamento del lock, è certo che assicuri l'accesso singolo ai dati togliendo quindi "ogni" dubbio sulla integrità dei dei dati.
    Le transazioni però mi pare di capire che abbiano un ruolo un pò di verso, assicurano che una serie di operazioni su database vadano, in gruppo, a buon fine in modo da garantire una coerenza delle istruzioni eseguite, ma non effetuano un lock sulle tabelle quindi si potrebbe comunque incappare in una situazione di concorrenza ad esempio in update su un dato.

    Come è possibile far conciliare le due cose? magari aggiungendo un ulteriore controllo alla fine delle operazioni prima della commit, come nell'esempio qui sotto?

    -inizio transazione
    -condizione1 necessaria a far partire le operazioni
    ---operazione1
    ---operazione2
    ---operazione3
    -se le tre operazioni sono andate a buon fine si ricontrolla la condizione1 (per controllare non sia cambiata nel frattempo a causa di altro utente) e si esegue la commit

    E' forse questo l'unico modo?

    Ringrazio in anticipo sperando in un chiarimento.

  2. #2
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    direi proprio di no, o meglio "ni".
    Le transazioni esistono in vari livelli di "indipendenza" (il che significa anche parallelismo minore), normalmente indicati con l'acronimo ACID.

    Ogni livello ha i suoi pregi e difetti, ossia puoi avere phantom rows oppure no e chi più ne ha ne metta.

    Più rendi rigidi i requisiti, più ti avvicini ad una serializzazione con lock, più (ovviamente) diminuiscono le prestazioni.

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    ciao franzauker,
    ho dato una lettura ai livelli di indipendenza come mi hai consigliato, mi pare di capire che per avere un lock delle tabelle bisogna impostare la transazione con livello SERIALIZABLE.
    Leggendo però la guida su HTML.IT viene specificato:

    SERIALIZABLE: ......... la semplice lettura di un dato provoca il blocco degli aggiornamenti fino al termine della transazione; in sostanza è come se ogni SELECT venisse effettuata con la clausola LOCK IN SHARE MODE

    il chè però non mi è molto chiaro.
    Vediamo se ho capito bene:

    -inizio transazione SERIALIZABLE
    -condizione1 necessaria a far partire le operazioni = SELECT1
    ---operazione1
    ---operazione2
    ---operazione3
    ---se tutto ok COMMIT

    l'operazione SELECT1 esegue un lock in lettura alla tabella che viene rilasciato solo al momento della commit/rollback renedendo inutile l'ulteriore controllo finale?

    Grazie mille

  4. #4
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    Originariamente inviato da arkus
    (...)
    il chè però non mi è molto chiaro
    (...)
    l'operazione SELECT1 esegue un lock in lettura alla tabella che viene rilasciato solo al momento della commit/rollback renedendo inutile l'ulteriore controllo finale?

    Grazie mille
    no, pone un lock equivalente ad una "specie" di lock di scrittura, e non sulla tabella, bensì sulla riga (stiamo parlando di innodb, ovviamente).

    Meno contortamente: le altre sessioni possono leggere il dato (sempre riga), ma non eliminarlo o cancellarlo. Attenzione che può scattare il meccanismo MVCC.

    Essenzialmente blocca con un mutex l'accesso [scrittura/cancellazione] alle righe, in questo senso quindi "serializza" strettamente gli accessi in una vera e propria queue (se ci sono scritture in altre sessioni).

    Non hai parallelismo in questo caso.

    Tanto per capirci è qualcosa di (vagamente) simile a pigliare il bigliettino in coda al fornaio per essere serviti uno alla volta
    [vabbè è scritta proprio rozzamente, ma spero si capisca ]

    Per inciso nel caso di mysql entra in gioco l'autocommit settato, ed eventualmente l'ottimizzatore che può "capire" una query in sola lettura (nel qual caso non mette alcun blocco).

    ------
    Si capisce? boh

  5. #5
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    ti ringrazio franzauker, quindi in fin dei conti conviene la prima strada, cioè lasciare una transazione standard ed effettuare un secondo controllo prima di dare il comando commit

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    Originariamente inviato da arkus
    ti ringrazio franzauker, quindi in fin dei conti conviene la prima strada, cioè lasciare una transazione standard ed effettuare un secondo controllo prima di dare il comando commit
    no, per il semplice motivo che il secondo controllo... non serve a nulla (o meglio non garantisce nulla) in ambiente MVCC

    Magari prova a spiegare esattamente cosa vuoi fare e cosa "ti turba"

  7. #7
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    ti ringrazio per l'attenzione,

    ho un campo nel database chiamato "accessibile" che può essere nello stato true o false.

    Accessibile = select accessibile From table;
    if (Accessibile){
    START TRANSACTION
    letture e scritture su database che devono andare a buon fine tutte
    update table SET accessibile = false
    if(tutto ok) COMMIT
    }

    la mia preoccupazione è che due utenti possano contemporaneamente trovare lo stato di accessibile = true e andare a sovrascriversi a vicenda le operazioni dentro il primo if

  8. #8
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    la transazione deve partire da prima del test del valore, non dopo.

    se proprio "non ti fidi" e/o usi un engine senza supporto delle transazioni (a costo ovviamente di una serializzazione) puoi sempre fare qualcosa tipo

    (attenzione che devi mettere esplicitamente anche le tabelle lockate in lettura, a seconda della versione di mysql che usi. mettile, così non devi sbatterti)

    LOCK TABLES tabella1 READ, tabella2 WRITE
    SELECT ... from ...
    update ... set ...
    UNLOCK TABLES

    EDIT se invece vuoi test non bloccanti
    puoi usare GET_LOCK (col timeout),
    IS_FREE_LOCK e RELEASE_LOCK, e magari
    inventarti una qualche strategia tipo CSMA/CD per aumentar man mano (e random) gli intervallini di test

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.