Informazioni sulla funzione di blocco
Il controllo della concorrenza multi-versione (MVCC) fornisce le impostazioni di concorrenza appropriate per la maggior parte degli scenari. Tuttavia, se un'applicazione richiede blocchi specifici che controllano esattamente quali righe sono interessate e con un livello di blocco specifico, le modalità di blocco esplicite abilitano questo controllo con granularità fine.
In Database di Azure per PostgreSQL sono disponibili tre tipi di blocchi espliciti: blocchi a livello di tabella, blocchi a livello di riga e blocchi a livello di pagina. La transazione iniziale richiede un blocco e, se accettato, il blocco richiesto diventa il blocco esistente. Se un'altra transazione tenta di escludere un blocco sugli stessi dati, il blocco viene concesso se non è in conflitto con la transazione originale.
Due transazioni, ad esempio, possono eseguire simultaneamente una query sugli stessi dati con un'istruzione SELECT. Queste richieste usano un blocco ACCESS SHARE e sono entrambe consentite. In un altro scenario, una transazione esegue una query sui dati con un'istruzione SELECT e un blocco ACCESS SHARE, ma allo stesso tempo un'altra transazione cerca di rimuovere la stessa tabella. La rimozione di una tabella richiede un blocco ACCESS EXCLUSIVE, che in questo scenario non verrebbe concesso.
Blocchi a livello di tabella
I blocchi a livello di tabella acquisiscono i blocchi su un'intera tabella, anche se hanno ROW nel nome. Il blocco di un'intera tabella potrebbe essere necessario se la tabella stessa venisse modificata oppure potrebbe essere più efficiente rispetto all'estrazione di molti blocchi a livello di riga.
Esistono otto tipi di blocco a livello di tabella in Database di Azure per PostgreSQL e i comandi SQL che acquisiscono questi tipi di blocchi sono:
Modalità di blocco | Acquisito da |
---|---|
ACCESS SHARE | Comando SELECT |
ROW SHARE | Comandi SELECT FOR UPDATE e SELECT FOR SHARE |
ROW EXCLUSIVE | Comandi UPDATE, DELETE e INSERT |
SHARE UPDATE EXCLUSIVE | Comandi ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON, REINDEX CONCURRENTLY, alcuni comandi ALTER INDEX e ALTER TABLE e VACUUM (non FULL) |
CONDIVIDI | Comando CREATE INDEX (non CONCURRENTLY) |
SHARE ROW EXCLUSIVE | Comando CREATE TRIGGER e alcuni comandi ALTER TABLE |
EXCLUSIVE | Comando REFRESH MATERIALIZED VIEW CONCURRENTLY |
ACCESS EXCLUSIVE | Comandi DROP TABLE, REINDEX, TRUNCATE, CLUSTER, REFRESH MATERIALIZED VIEW (non CONCURRENTLY), la maggior parte dei comandi ALTER INDEX e ALTER TABLE e VACUUM FULL |
Ogni tipo di blocco esistente blocca l'acquisizione di altri blocchi richiesti. La tabella seguente elenca i blocchi che bloccano l'acquisizione di altri blocchi:
-- | ACCESS SHARE esistente | ROW SHARE esistente | ROW EXCLUSIVE esistente | SHARE UPDATE EXCLUSIVE esistente | SHARE esistente | SHARE ROW EXCL esistente | EXCLUSIVE esistente | ACCESS EXCLUSIVE esistente |
---|---|---|---|---|---|---|---|---|
ACCESS SHARE richiesto | Bloccati | |||||||
ROW SHARE richiesto | Bloccato | Bloccato | ||||||
ROW EXCLUSIVE richiesto | Bloccato | Bloccato | Bloccato | Bloccato | ||||
SHARE UPDATE EXCLUSIVE richiesto | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | |||
SHARE richiesto | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | |||
SHARE ROW EXCLUSIVE richiesto | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | ||
EXCLUSIVE richiesto | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | |
ACCESS EXCLUSIVE richiesto | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato | Bloccato |
Blocchi a livello di riga
I blocchi a livello di riga sono più granulari e hanno effetto solo su un'altra transazione che accede alla stessa riga. Questo tipo di blocco migliora la concorrenza, ma l'acquisizione e l'eliminazione di molti blocchi influiscono negativamente sulle prestazioni. I blocchi a livello di riga vengono acquisiti automaticamente da PostgreSQL e non vengono applicati manualmente.
Esistono quattro tipi di blocco a livello di riga in Database di Azure per PostgreSQL e vengono acquisiti a seconda degli altri tipi di blocco che devono essere bloccati:
-- | FOR KEY SHARE esistente | FOR SHARE esistente | FOR NO KEY UPDATE esistente | FOR UPDATE esistente |
---|---|---|---|---|
FOR KEY SHARE richiesto | Bloccati | |||
FOR SHARE richiesto | Bloccato | Bloccato | ||
FOR NO KEY UPDATE richiesto | Bloccato | Bloccato | Bloccato | |
FOR UPDATE richiesto | Bloccato | Bloccato | Bloccato | Bloccato |
Blocchi a livello di pagina
I blocchi a livello di pagina hanno effetto su una pagina di dati, che in genere è costituita da più righe. Anche se i processi PostgreSQL usano blocchi a livello di pagina, gli sviluppatori di applicazioni in genere non richiedono questo tipo di blocco.
Applicazione manuale dei blocchi e visualizzazione dei blocchi correnti
Per applicare manualmente un blocco a livello di tabella, è possibile usare il comando LOCK con la modalità di blocco richiesta. Il comando LOCK deve trovarsi all'interno di una transazione e i blocchi vengono rilasciati al termine della transazione. Ad esempio:
BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;
Per visualizzare i blocchi attualmente presenti nel database, usare pg_locks. Ad esempio, per visualizzare tutti i blocchi correnti, usare il comando seguente:
SELECT * FROM pg_locks;