Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292

    lock table + transaction alternativa

    [php,mysql]

    Ciao a tutti,
    mi trovvo in una situazione in cui avrei bisogno sia di effettuare una lock sia di effettuare una transizione.
    La tabella su cui fare il lock è in lettura concorrente, in base all'esito della lettura devono essere fatte altre letture più scritture che richiedo una transazione perchè devono avare alla fine diquesta dati coerenti, legati tra loro.

    Fino ad ora simulavo la lock table in questo modo:

    -stato di partenza: lettura della tabella concorrente (quella a cui dovrei far il lock)

    -start transaction
    -lettuta/scrittura1
    -lettuta/scrittura2
    ....
    -lettuta/scritturaX

    Se tutte le operazioni sono andate a buon fine rieseguo la prima lettura della tabella concorrente per verificare che lo stato nel frattempo non sia cambiato,
    se uguale allora effetuo la commit altrimenti un rollback.

    Quindi simulo la lock table effettuando un secondo controllo per verificare che lo stato sia ancora quello di partenza.

    Ci sono strade migliori o comunque più eleganti? Penso che questa strada non sia comunque esente da bug, con il secondo controllo credo di abbassare drasticamente la probabilità che vengano fatte due operazioni contemporanee con lo stesso stato di partenza (situazione che vorrei evitare), ma non non credo che venga annullata completamente la possibilità per come avverrebbe con una lock table.

    Grazie

  2. #2
    Da quel che ho capito, ti basta fare all'inizio della transazione una SELECT FOR UPDATE, che mette un lock in scrittura sulle righe che vengono lette. Come transaction level usa REPEATABLE READ, così i dati che leggi sono coerenti tra loro.

    Oppure usa SERIALIZABLE che trasforma automaticamente le SELECT in SELECT FOR UPDATE.
    STK/Unit: Unit Test framework per MariaDB
    http://stk.wikidot.com/stk-unit

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    Ciao in the web,
    intanto ti ringrazio per la risposta,
    non sono convinto di aver capito esattamente come funzioni, correggimi se sbaglio,
    se io nella query dello stato iniziale utilizzo una select for update mi blocca tutta la tabella in scrittura e lettura finche non viene effettuato un rollback o una commit?

  4. #4
    La differenza è questa:
    * LOCK TABLE blocca tutta la tabella
    * SELECT FOR UPDATE blocca solo le righe che vengono lette. (è molto meglio se usi un indice univoco nella where, altrimenti potrebbe bloccare anche altre righe)

    Se vuoi bloccare TUTTE le righe della tabella e impedire gli inserimenti, ci vuole il lock della tabella, altrimenti basta una SELECT FOR UPDATE.

    Ma sinceramente non ho capito bene il tuo problema. In particolare, perché vuoi il lock? E perché fai un controllo alla fine? Se vuoi semplicemente che le righe che leggi siano coerenti tra loro, ti basta un repeatable read.
    http://dev.mysql.com/doc/refman/5.5/...ansaction.html
    STK/Unit: Unit Test framework per MariaDB
    http://stk.wikidot.com/stk-unit

  5. #5
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    la lock table non posso utilizzarla per via delle tabelle innodb,

    provo a farti un esempio concreto.

    accesso tramite un codice usa e getta univoco.
    al momento dell'accesso controllo una disponibilita, se verificata allora registro l'accesso e la disponibilità viene messa a false.

    questi passaggi li traduco in query scritte alla buona:

    //controllo che il codice esista
    $res1 = select * from list_code where code = '$code'
    if(count($res1)==0) codice inesistente => exit;

    //controllo che il codice non sia stato già utilizzato
    $res2 = select * from used_code where code = '$code'
    if(count($res2)>0) codice già utilizzato => exit;

    //controllo disponibilità
    $res3 = slect * FROM disponibilità WHERE state = '1' AND date = 'now'
    if (count($res3 )== 1){

    $save1 = insert $code in used_code;
    $save2 = update disponibilità set state = '0' where date = 'now'
    $save3 =altra insert
    se tutti i salvataggi ok allora commit altrimenti roolback.
    }else{
    $save1 = insert $code in used_code;
    $save3 =altra insert
    se tutti i salvataggi ok allora commit altrimenti roolback.

    }


    i problemi sono:
    -controllo codice già utilizzato = capita raramente che vengano fatte 2 richieste contemporaneamente con lo stesso codice, senza lock vengono permessi due accessi con lo stesso codice.
    -disponibilità

    Per la disponibilità potrei quindi risolvere con la select for update che andrebbe a bloccare in lettura e scrittura il record caratterizzato dalla where,
    ma per la prima select servirebbe invece un lock di tutta la tabella

  6. #6
    Ok, ora ho capito.

    Secondo me non è necessario, ma se vuoi essere più sicuro, puoi usare SELECT GET_LOCK():
    http://dev.mysql.com/doc/refman/5.0/...ction_get-lock

    La funzione acquisisce un lock con un certo nome. Se un'altra sessione ha già acquisito un lock con lo stesso nome, GET_LOCK() aspetta finché questo lock non viene liberato e restituisce TRUE. Se invece il lock non si libera entro un timeout deciso da te, restituisce FALSE.

    Ricorda però di fare un DO RELEASE_LOCK() appena puoi.
    STK/Unit: Unit Test framework per MariaDB
    http://stk.wikidot.com/stk-unit

  7. #7
    Comunque puoi anche usare LOCK TABLES, anche se è innodb. Se innodb_table_locks è 0 impostala a 1.
    STK/Unit: Unit Test framework per MariaDB
    http://stk.wikidot.com/stk-unit

  8. #8
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    Farò delle prove con il get lock.

    lock table pensavo non andasse bene per quanto riportato sulla documentazione:

    LOCK TABLES is not transaction-safe and implicitly commits any active transaction before attempting to lock the table


    O in questo caso potrebbe andar bene perchè la transazione viene avviata dopo aver effettuato la lock?

  9. #9
    In generale non ti direi di usarlo, però in questo caso non dovrebbe dare problemi perché dopo il LOCK TABLES non usi più list_code.

    Se ci fosse già una transazione attiva, farebbe il commit e ne inizierebbe un'altra.

    Comunque chiama UNLOCK TABLES appena puoi
    STK/Unit: Unit Test framework per MariaDB
    http://stk.wikidot.com/stk-unit

  10. #10
    Utente di HTML.it
    Registrato dal
    Oct 2009
    Messaggi
    292
    Sei stato gentilissimo,
    appena possibile farò delle prove.

    Grazie mille

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 © 2026 vBulletin Solutions, Inc. All rights reserved.