MySQL
MySQL LOCK TABLE
Ricerca…
Sintassi
LOCK TABLES nome_tabella [LEGGI | SCRIVI]; // Lock Table
TABELLE SBLOCCA; // Sblocca tabelle
Osservazioni
Il blocco viene utilizzato per risolvere problemi di concorrenza. Il blocco è richiesto solo quando si esegue una transazione, che prima legge un valore da un database e successivamente lo scrive nel database. I blocchi non sono mai necessari per l'inserimento, l'aggiornamento o l'eliminazione di operazioni autonome.
Sono disponibili due tipi di serrature
LEGGI BLOCCO: quando un utente legge solo da una tabella.
WRITE LOCK - quando un utente sta eseguendo sia la lettura che la scrittura su un tavolo.
Quando un utente tiene un WRITE LOCK
su una tabella, nessun altro utente può leggere o scrivere su quella tabella. Quando un utente dispone di un READ LOCK
su un tavolo, altri utenti possono anche leggere o sospendere un READ LOCK
, ma nessun utente può scrivere o mantenere un WRITE LOCK
su tale tabella.
Se il motore di archiviazione predefinito è InnoDB, MySQL utilizza automaticamente il blocco a livello di riga in modo che più transazioni possano utilizzare la stessa tabella contemporaneamente per la lettura e la scrittura, senza aspettarsi reciprocamente.
Per tutti i motori di memorizzazione diversi da InnoDB, MySQL utilizza il blocco delle tabelle.
Per maggiori dettagli sul blocco del tavolo Vedi qui
Serrature Mysql
I blocchi tabella possono essere uno strumento importante per ENGINE=MyISAM
, ma raramente sono utili per ENGINE=InnoDB
. Se si è tentati di utilizzare blocchi di tabelle con InnoDB, è necessario riconsiderare il modo in cui si sta lavorando con le transazioni.
MySQL consente alle sessioni client di acquisire esplicitamente blocchi di tabelle allo scopo di collaborare con altre sessioni per l'accesso alle tabelle o di impedire ad altre sessioni di modificare le tabelle durante i periodi in cui una sessione richiede l'accesso esclusivo a tali sessioni. Una sessione può acquisire o rilasciare i blocchi solo per se stesso. Una sessione non può acquisire blocchi per un'altra sessione o rilasciare blocchi bloccati da un'altra sessione.
I blocchi possono essere utilizzati per emulare transazioni o per ottenere maggiore velocità durante l'aggiornamento delle tabelle. Questo è spiegato più in dettaglio più avanti in questa sezione.
Comando: LOCK TABLES table_name READ|WRITE;
è possibile assegnare solo il tipo di blocco a una singola tabella;
Esempio (READ LOCK):
LOCK TABLES table_name READ;
Esempio (WRITE LOCK):
LOCK TABLES table_name WRITE;
Per vedere il blocco è applicato o meno, utilizzare il seguente comando
SHOW OPEN TABLES;
Per svuotare / rimuovere tutti i blocchi, utilizzare il seguente comando:
UNLOCK TABLES;
ESEMPIO:
LOCK TABLES products WRITE:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Sopra l'esempio qualsiasi connessione esterna non può scrivere alcun dato nella tabella prodotti fino al prodotto della tabella di sblocco
ESEMPIO:
LOCK TABLES products READ:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Sopra l'esempio qualsiasi connessione esterna non può leggere alcun dato dalla tabella prodotti fino al prodotto della tabella di sblocco
Blocco a livello di riga
Se le tabelle utilizzano InnoDB, MySQL utilizza automaticamente il blocco a livello di riga in modo che più transazioni possano utilizzare la stessa tabella contemporaneamente per la lettura e la scrittura, senza aspettarsi reciprocamente.
Se due transazioni cercano di modificare la stessa riga e entrambe utilizzano il blocco a livello di riga, una delle transazioni attende che l'altro venga completato.
Il blocco del livello di riga può anche essere ottenuto utilizzando SELECT ... FOR UPDATE
per ogni riga che si prevede venga modificata.
Prendi in considerazione due connessioni per spiegare il blocco del livello di riga in dettaglio
Connessione 1
START TRANSACTION;
SELECT ledgerAmount FROM accDetails WHERE id = 1 FOR UPDATE;
Nella connessione 1, il blocco del livello di riga ottenuto SELECT ... FOR UPDATE
.
Connessione 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
Quando qualcuno tenta di aggiornare la stessa riga nella connessione 2, attenderà che la connessione 1 termini la transazione o che venga visualizzato un messaggio di errore in base all'impostazione innodb_lock_wait_timeout
, che per impostazione predefinita è 50 secondi.
Error Code: 1205. Lock wait timeout exceeded; try restarting transaction
Per visualizzare i dettagli su questo blocco, eseguire SHOW ENGINE INNODB STATUS
---TRANSACTION 1973004, ACTIVE 7 sec updating
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 4, OS thread handle 0x7f996beac700, query id 30 localhost root update
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1
------- TRX HAS BEEN WAITING 7 SEC FOR THIS LOCK TO BE GRANTED:
Connessione 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 250 WHERE id=2;
1 row(s) affected
Ma mentre l'aggiornamento di un'altra riga nella connessione 2 verrà eseguita senza alcun errore.
Connessione 1
UPDATE accDetails SET ledgerAmount = ledgerAmount + 750 WHERE id=1;
COMMIT;
1 row(s) affected
Ora il blocco riga viene rilasciato, perché la transazione è impegnata in Connection 1.
Connessione 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
1 row(s) affected
L'aggiornamento viene eseguito senza errori in Connection 2 dopo che Connection 1 ha rilasciato il blocco riga terminando la transazione.