Influenciar nos mecanismos de bloqueio do banco de dados nem sempre é um processo intuitivo. No entanto, pode ser bastante útil para garantia da confiabilidade de resultados e para ajustes de desempenho.
A existência de bloqueios sobre os dados acessados durante o acesso concorrente não pode ser ignorada em sistemas com grande número de transações concorrentes mesmo no Postgres que utiliza o protocolo de bloqueios multiversão (MVCC - MultiVersion Concurrency Control).
O PostgreSQL oferece algumas cláusulas relativamente simples que permitem este tipo de controle no caso de consultas no banco de dados: FOR UPDATE, FOR SHARE e NOWAIT.
O uso de consultas com a cláusula FOR UPDATE obriga o servidor a bloquear os registros consultados para leitura e escrita durante o transcorrer da transação. Desta forma se garante que o que está sendo visualizado corresponde ao que está armazenado no banco de dados.
Por sua vez, a cláusula FOR SHARE efetua bloqueio de escrita, mas permite que leituras sejam feitas aos dados consultados.
Em resumo, a cláusula FOR UPDATE restringe os acessos aos dados consultados, enquanto que a FOR SHARE explicitamente autoriza acessos de leitura aos dados consultados. O tipo de transação é que determina se e quando utilizar estas cláusulas.
É importante salientar que ambas as cláusulas se referem apenas os dados que são recuperados na consulta.
Adicionalmente, a cláusula NOWAIT pode ser utilizada tanto com FOR UPDATE quanto com FOR SHARE, e força a ocorrência de erro caso o servidor tenha de esperar para a obtenção de bloqueios nos dados consultados. Desta forma, sacrifica-se a transação para que não se perca tempo na fila de espera por bloqueios.
As cláusulas UNION, INTERSECT e EXCEPT até o momento não são compatíveis com FOR UPDATE e FOR SHARE.
Para os próximos exemplo, serão utilizadas as seguintes tabelas:
CREATE TABLE pai (codpai integer,nomepai varchar(50));
CREATE TABLE filho (codpai integer,codfilho integer,nomefilho varchar(50));
Exemplos:
1 - Sintaxe simples com FOR UPDATE.
SELECT * FROM pai FOR UPDATE;
2 - Sintaxe simples com FOR SHARE.
EXPLAIN SELECT * FROM pai FOR SHARE;
3 - Uso de FOR SHARE em consulta com junção.
SELECT *
FROM pai p, filho f
WHERE p.codpai = f.codpai
FOR SHARE;
4 - Uso de NOWAIT.
SELECT * FROM pai FOR UPDATE NOWAIT;
5 - Uso de FOR UPDATE em transação de atualização.
BEGIN;
SELECT * FROM pai FOR UPDATE;
UPDATE pai SET nomepai = nomepai ' Father';
COMMIT;