Pessoal, preciso de ajuda para entender o motivo de uma trigger
bloquear um select (update em outra tabela com sub select).
Vejam o exemplo:

Minhas duas tabelas:
create table tb_produtoestoque (
  id integer not null,
  produto_id integer not null,
  qt_estoque numeric(18,4) not null);
alter table tb_produtoestoque add constraint produtoestoque_pk primary key(id);
--alter table tb_produtoestoque add constraint prodestoque_prod_fk
foreign key (produto_id) references tb_produto(id);

create table tb_produtoestoquehistorico (
  id integer not null,
  produtoestoque_id integer not null,
  qt_estoquehistorico numeric(18,4) not null,
  dt_cadastro timestamp default current_timestamp not null,
  dt_processamento timestamp);
alter table tb_produtoestoquehistorico add constraint
produtoestoquehistorico_pk primary key(id);
alter table tb_produtoestoquehistorico add constraint
prodhistorico_prodestoque_fk foreign key (produtoestoque_id)
references tb_produtoestoque(id);

create sequence seq_produtoestoquehistorico;


Trigger na tabela produtoestoquehistorico:
create or replace function pct_produtoestoquehistorico() returns trigger as $$
declare
begin
  if ((new.id is null) or (new.id < 1)) then
    new.id := nextval('seq_produtoestoquehistorico');
  end if;
  return NEW;
end;
$$ language 'plpgsql';

create trigger trg_produtoestoquehistorico before insert on
tb_produtoestoquehistorico for each row execute procedure
pct_produtoestoquehistorico();


Zerando os estoques dos produtos 1, 2 e 3 :
insert into tb_produtoestoque values (1, 1, 0), (2, 2, 0), (3, 3, 0);

Inserindo historico para os produtos 1, 2 e 3 cada um com 2
quantidades totalizando um estoque de 3uni por produto:
insert into tb_produtoestoquehistorico
values (null, 1, 1, CURRENT_TIMESTAMP, null), (null, 1, 2,
CURRENT_TIMESTAMP, null),
       (null, 2, 1, CURRENT_TIMESTAMP, null), (null, 2, 2,
CURRENT_TIMESTAMP, null),
       (null, 3, 1, CURRENT_TIMESTAMP, null), (null, 3, 2,
CURRENT_TIMESTAMP, null);

Agora, em uma transação isolada: inserir um novo registro de histórico
para o produto 1
begin;
insert into tb_produtoestoquehistorico values (null, 1, 1,
CURRENT_TIMESTAMP, null);

Mantendo a transação anterior aberta (utilizando outro terminal), em
uma nova transação atualizar o estoque do produto 1:
begin;
update tb_produtoestoque set
       qt_estoque = qt_estoque + coalesce((select sum(t1.qt_estoquehistorico)
                                                                 from
tb_produtoestoquehistorico t1
                                                               where
t1.produtoestoque_id = tb_produtoestoque.id
                                                                  and
t1.dt_processamento is null), 0)
 where id in (select t1.produtoestoque_id
                     from tb_produtoestoquehistorico t1
                   where t1.dt_processamento is null);

Percebam que o update ficou aguardando a primeira transação.
Porque o update na tabela produtoestoque é mantido em waiting?
Porque a trigger manteve o lock (ExclusiveLock) sobre a tabela de histórico?

Utilizo PostgreSQL 9.2.4
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a