sexta-feira, 19 de fevereiro de 2010

Select - Cláusulas FOR UPDATE, FOR SHARE e NOWAIT

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;

3 comentários:

Deleon disse...

Olá!
Poderia explicitar um pouco melhor a aplicabilidade do For Update e quais as implicaçoes que poderao ocorrer caso ele usado em uma transação que possua mais bloqueios, e como ele trata o bloqueio nas tabelas de join.
Um abraço!

nickinha disse...

fiquei boiando aqui literalmente no pai e filho....poderia me explicar melhor....? obrigada

cbleopoldino disse...

Nickinha, as tabelas pai e filho foram criadas para ilustrarem os exemplos.

Elas tem esse nome porque têm elementos que permitem a junção, e temos pelo menos um exemplo com junção de tabelças neste post.