Comprendere il 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.
Ad esempio, due transazioni possono eseguire query sullo stesso dati contemporaneamente con un'istruzione SELECT. Queste richieste usano un blocco ACCESS SHARE e sono entrambe consentite. In un altro scenario, una transazione esegue query sui dati con un'istruzione SELECT e un blocco ACCESS SHARE, ma allo stesso tempo un'altra transazione tenta di eliminare la stessa tabella. L'eliminazione 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 in un'intera tabella, anche se contengono ROW nel nome. Il blocco di un'intera tabella potrebbe essere necessario se la tabella stessa viene modificata o potrebbe essere più efficiente rispetto all'esecuzione 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 |
|---|---|
| CONDIVISIONE DI ACCESSO | 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) |
| SHARE | Comando CREATE INDEX (non CONCURRENTLY) |
| SHARE ROW EXCLUSIVE | Comando CREATE TRIGGER e alcuni comandi ALTER TABLE |
| Esclusivo | Comando REFRESH MATERIALIZED VIEW CONCURRENTLY |
| ACCESSO ESCLUSIVO | 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 impedisce 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 | Bloccati | Bloccati | ||||||
| ROW EXCLUSIVE richiesto | Bloccati | Bloccati | Bloccati | Bloccati | ||||
| SHARE UPDATE EXCLUSIVE richiesto | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | |||
| SHARE richiesto | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | |||
| SHARE ROW EXCLUSIVE richiesto | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | ||
| EXCLUSIVE obbligatorio | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | |
| RICHIESTA DI ACCESSO ESCLUSIVO | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati | Bloccati |
Blocchi a livello di riga
I blocchi a livello di riga sono più granulari e influiscono 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 di quali altri tipi di blocco devono essere bloccati:
| -- | FOR KEY SHARE esistente | FOR SHARE esistente | FOR NO KEY UPDATE esistente | FOR UPDATE esistente |
|---|---|---|---|---|
| FOR KEY SHARE obbligatorio | Bloccati | |||
| Richiesta di condivisione | Bloccati | Bloccati | ||
| FOR NO KEY UPDATE obbligatorio | Bloccati | Bloccati | Bloccati | |
| Richiesta DI AGGIORNAMENTO | Bloccati | Bloccati | Bloccati | Bloccati |
Blocchi a livello di pagina
I blocchi a livello di pagina influiscono 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. Per esempio:
BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;
Per visualizzare i blocchi attualmente mantenuti nel database, utilizzare pg_locks. Ad esempio, per visualizzare tutti i blocchi correnti, utilizzare il comando seguente:
SELECT * FROM pg_locks;