Escolar Documentos
Profissional Documentos
Cultura Documentos
Para iniciar uma transação no PostgreSQL devemos utilizar o comando BEGIN. Caso
ele não seja fornecido o banco vai se comportar de forma padrão (autocommit), ou
seja, cada comando é considerado uma transação.
Sitaxe:
SAVEPOINT savepoint_name
exemplo:
BEGIN;
INSERT INTO TABELA_01 VALUES (1);
SAVEPOINT PONTO_SALVAMENTO;
INSERT INTO TABELA_01 VALUES (2);
ROLLBACK TO SAVEPOINT PONTO_SALVAMENTO;
INSERT INTO TABELA_01 VALUES (3);
COMMIT;
BEGIN;
INSERT INTO TABELA_01 VALUES (2);
SAVEPOINT PONTO_SALVAMENTO;
INSERT INTO TABELA_01 VALUES (4);
RELEASE SAVEPOINT PONTO_SALVAMENTO;
COMMIT;
SELECT * FROM TABELA_01;
Controle de concorrência no PostGreSQL
Portanto, quando você define o nível de transação para read uncommitted você
está, na verdade, selecionando o nível de isolamento read committed.
Isso é feito, essencialmente, por que esse é o único jeito de tornar o padrão de
níveis de isolamento compatíveis com o modelo MVCC.
Esse comando deve aparecer após um comando BEGIN ou START TRANSACTION e vale
somente para a transação corrente;
Read Committed
-----------------
O comando corrente vê a última versão dos dados antes da sua execução, o comando
seguinte pode pegar uma outra versão atualizada. Resumindo, a cada nova consulta
um novo snapshot é requisitado ao banco de dados e ele reflete todos os dados
“comitados” até aquele momento para a consulta em execução.
o que acontecerá?
A transação T1 (que iniciou antes) fará uma pesquisa localizando todos os cds
cujo código seja maior que 10 e conseguirá, para eles, um bloqueio de
atualização.
A transação T2 (que iniciou depois) fará uma pesquisa por todos os cds cujos
cujo código seja maior que 15, porém não conseguirá alguns bloqueios já que os
registros estão bloqueados/marcados pela primeira transação e irá entrar em
espera (wait).
No exemplo acima uma transação T12 fosse disparada entre os T1 e T2 mas apenas
com o objetivo de leitura leria a última versão atualizada dos dados. Se T1 já
houvesse concluído com sucesso ela leria o valor dos cds atualizados em 50%,
caso contrário o seu valor antes do fim da transação. Observe que mesmo durante
a transação T2 somente os valores atualizados em T1 é que são obtidos.
Serializable
----------------
todos os comandos da transação vêem a mesma versão dos dados. Aquela versão
obtida antes do início dessa transação. Resumindo, todas as consultas executadas
dentro de uma transação desse tipo devolvem sempre o mesmo resultado não havendo
a criação de um novo snapshot por comando.
t1:
-- T1
Begin;
update rec_fatura set valor_total = valor_total * 1.5 where idfatura = 1;
o que acontecerá?
A transação T2 (que iniciou depois) fará a mesma pesquisa, porém, não conseguirá
um bloqueio exclusivo já que o registro está bloqueado/marcado pela primeira
transação e irá entrar em espera (wait).
-- T1
Begin;
-- T1
select * from rec_fatura join rec_cliente using (idcliente) where idfatura = 1;
-- execute T2
update rec_fatura set valor_total = valor_total + 5.0 where idfatura = 1;
--T2
Begin;
--T2
update rec_fatura set valor_total = valor_total + 10.0 where idfatura = 1;
Exemplos:
-- T1
Begin;
-- T1
select * from rec_fatura join rec_cliente using (idcliente) where idfatura = 1
FOR UPDATE;
-- execute T2
update rec_fatura set valor_total = valor_total + 5.0 where idfatura = 1;
--T2
Begin;
--T2
update rec_fatura set valor_total = valor_total + 10.0 where idfatura = 1;
DeadLocks
--------------
T1
BEGIN;
T2
BEGIN;
T1
T2