On 15-04-2015 13:16, Rosana de Oliveira wrote:
> 1. Qual a explicação literária e do Postgresql para esta tentativa mal
> sucedida de obter o lock?
> 
Vamos entender o que ocorreu na transação A.

begin;
insert into animal values (108, 'viralata', 1);

euler=# select relation::regclass,locktype,virtualtransaction as
vtxn,pid,mode from pg_locks order by pid,relation;
  relation   |   locktype    | vtxn | pid  |       mode
-------------+---------------+------+------+------------------
 pessoa      | relation      | 2/21 | 2794 | RowShareLock
 pessoa_pkey | relation      | 2/21 | 2794 | AccessShareLock
 animal      | relation      | 2/21 | 2794 | RowExclusiveLock
             | virtualxid    | 2/21 | 2794 | ExclusiveLock
             | transactionid | 2/21 | 2794 | ExclusiveLock

A inserção foi na tabela animal mas como há uma chave estrangeira para
tabela pessoa, o SGBD tem que garantir que ninguém irá modificar o
registro envolvido (por isso ele coloca um RowShareLock na tabela pessoa).

> 1.1 Quem 'lockou' o quê?
> 
Na segunda transação:

euler=# begin;
BEGIN
euler=# select nome from pessoa  for update;

euler=# select relation::regclass,locktype,virtualtransaction as
vtxn,pid,mode from pg_locks order by pid,relation;
  relation   |   locktype    | vtxn | pid  |        mode
-------------+---------------+------+------+---------------------
 pessoa      | relation      | 3/41 | 2728 | RowShareLock
 pessoa      | tuple         | 3/41 | 2728 | AccessExclusiveLock
 pessoa_pkey | relation      | 3/41 | 2728 | AccessShareLock
             | transactionid | 3/41 | 2728 | ShareLock
             | virtualxid    | 3/41 | 2728 | ExclusiveLock
 pessoa      | relation      | 2/21 | 2794 | RowShareLock
 pessoa_pkey | relation      | 2/21 | 2794 | AccessShareLock
 animal      | relation      | 2/21 | 2794 | RowExclusiveLock
             | transactionid | 2/21 | 2794 | ExclusiveLock
             | virtualxid    | 2/21 | 2794 | ExclusiveLock

[não usei o NOWAIT para deixar a transação B esperando para que eu possa
obter a saída dos locks]

O SELECT ... FOR UPDATE tenta obter um AccessExclusiveLock (segunda
linha) em todas as tuplas da tabela mas isso não é possível porque uma
das tuplas (codp = 1) está com um lock "FOR KEY SHARE" (vide tabela 13-3
em [1]) para impossibilitar alguém de alterar o codp da tupla 1 ou mesmo
remover a tupla 1 (essa garantia é necessária para manter a integridade
dos dados).

> 2. Só de curiosidade, fizemos o mesmo teste no Oracle e não ocorreu erro
> algum.
>    E agora?
>    Quem poderá nos defender??   rss
> 
Muito estranho ele não falhar (no caso do NOWAIT) ou ficar esperando
(sem NOWAIT) pois isso pode acarretar perda de integridade. O que
acontece se na transação B você alterar o codp de 1 para 2?

Vale ressaltar que em versões anteriores a 9.3, UPDATE em tuplas de uma
chave estrangeira (como é o caso dos seus UPDATEs na transação B) ficam
bloqueados. A partir da 9.3, eles podem ser feitos desde que você *não*
altere a chave primária da tabela pessoa.


[1] http://www.postgresql.org/docs/9.4/static/explicit-locking.html


-- 
   Euler Taveira                   Timbira - http://www.timbira.com.br/
   PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento
_______________________________________________
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a