Suspender uma transañáo é útil quando se necessita, dentro de uma transação, realizar certas operações que não necessitam ser executadas sob o controle desta transação. Por exemplo, imaginemos o caso de que um cliente faz um pedido, dentro de uma transação e também atualizar seu endereço. Depois, o cliente muda de opinião e a ordem é cancelada. A transação é cancelada, mas você não quee que a mudança de endereço seja revertida. Este é um exemplo típico no qual suspender a transação é útil. Três comandos são utilizados para suspender e reativar as transações:
- SUSPEND TRANSACTION: detém a transação atual. Todos os registros atualizados ou adicionados permanecem bloqueados.
- RESUME TRANSACTION: reativa uma transação suspensa.
- Active transaction: devolve False se a transação for suspensa ou se não houver nenhuma transação atual e True se for iniciada ou reativada.
Este exemplo ilustra a necessidade de suspender uma transação. Em um banco de dados de faturas, queremos obter um novo número da fatura durante uma transação. Este número é calculado e armazenado em uma tabela [Settings]. Em um ambiente multi-usuário, os acessos concorrentes devem estar protegidos; entretanto, devido a transação, a tabela [Settings] poderia ser bloqueada por outro usuário apesar de que estes dados sejam independentes da transação principal. Neste caso, pode suspender a transação quando a tabela for acessada.
START TRANSACTION
...
CREATE RECORD([Invoices])
[Invoices]InvoiceID:=GetInvoiceNum
...
SAVE RECORD([Invoices])
VALIDATE TRANSACTION
O método GetInvoiceNum suspende a transação antes de execut-a-la. Note que este código funcionará mesmo se o método for chamado por fora de uma transação:
C_LONGINT($0)
SUSPEND TRANSACTION
ALL RECORDS([Settings])
If(Locked([Settings]))
While(Locked([Settings]))
MESSAGE("Waiting for locked Settings record")
DELAY PROCESS(Current process;30)
LOAD RECORD([Settings])
End while
End if
[Settings]InvoiceNum:=[Settings]InvoiceNum+1
$0:=[Settings]InvoiceNum
SAVE RECORD([Settings])
UNLOAD RECORD([Settings])
RESUME TRANSACTION
Quando uma transação for suspensa, os seguintes princípios abaixo são aplicados:
- Pode acessar aos registros que foram adicionados ou modificados durante a transação e não podem acessar aos registros que foram eliminados durante a transação.
- Pode criar, salvar, eliminar ou modificar os registros fora da transação.
- Pode iniciar uma nova transação, mas dentro desta transação incluida, não poderá ver os registros ou os valores de registros que foram adicionados ou modificados durante a transação suspensa. Na verdade, esta nova transação é totalmente independente da que foi suspensa, similar a uma transação de outro processo e já que a transação suspensa mais tarde poderia ser reativada ou cancelada, qualquer registro adicionado ou modificado é ocultado automaticamente para a nova transação. Logo que confirme ou cancele a nova transação, pode ver estes registros de novo.
- Todos os registros que são modificados, eliminados ou adicionados dentro da transação suspensa permanecem bloqueados para outros processos. Se tentar modificar ou eliminar estes registros fora da transação ou em uma nova transação, um erro é gerado.
Estas implementações são resumidas no seguinte gráfico:

Os valores editados durante a transação A (registro ID1 toma o valor Val11) não estão disponíveis em uma nova transação (B) criada durante o período "suspenso". Os valores editados durante o período de suspensão (registro ID2 toma o valor Val22 e registro ID3 toma o valor Val33), são conservados depois de que se cancela a transação A.
As funcionalidades específicas foram adicionadas para manejar os erros:
- O registro atual de cada tabela é bloqueado temporáriamente se for modificado durante a transação e for desbloqueado automaticamente quando for reinicada a operação. Este mecanismo é importante para evitar que partes da transação são salvas de forma inesperada.
- Se for executada uma sequencia inválida tal como, iniciar transação / suspender transação / iniciar transação / reativar transação, um erro é gerado. Este mecanismo evita que os desenvolvedores esqueçam de confirmar ou cancelar as sub transações incluidas antes de reativar a operação suspensa.
O comando existente In transaction devolve True quando for iniciada uma transação, mesmo se estiver suspensa. Para saber se a transação atual foi suspensa, é necessário utilizar o novo comando Transação ativa, que devolve False neste caso.
Ambos comandos, entretanto, também devolvem False se não tiver iniciado nenhuma transação. Depois pode ser necessário usar o comando Transaction level, que devolve 0 neste contexto (nenhuma operação iniciada).
O gráfico abaixo ilustra os diversos contextos de transação e os valores correspondentes devolvidos peos comandos de transação:
