SQL Server na prática

Bloqueios de aplicação para uma operação de negócio

Coordene workers com sp_getapplock, trate os códigos de retorno e separe exclusão temporária de idempotência persistente.

Dois workers podem decidir que uma fatura está pronta antes de qualquer um registrar a conclusão. Uma restrição única pode proteger o número final sem coordenar todos os passos intermediários. Um bloqueio de aplicação oferece um recurso nomeado para sessões cooperantes do SQL Server serializarem essa operação de negócio.

Definir recurso e duração

Nomeie a menor unidade que precisa de exclusão, como invoice:481 em vez de all-invoices. Um nome global serializa clientes independentes sem necessidade. Nomes diferentes, por outro lado, criam bloqueios separados. Centralize a construção e inclua o identificador do tenant quando a numeração for única apenas dentro dele.

O recurso pertence a um banco e a um namespace de principal do banco. O mesmo texto em bancos distintos não cria exclusão compartilhada. Os nomes diferenciam maiúsculas de minúsculas. Use uma representação canônica e respeite o limite documentado de comprimento para evitar colisões por truncamento.

A propriedade transacional costuma ser clara para uma operação curta restrita ao banco. Commit ou rollback libera o bloqueio. A propriedade de sessão tem aplicações, mas exige considerar liberação explícita e reutilização de conexões. Uma conexão do pool não representa uma fronteira de negócio.

Conferir a aquisição

Execute o padrão em um banco de teste sem transação externa. Substitua o trecho indicado pela operação curta real. A verificação do código de retorno impede executar trabalho protegido depois de uma tentativa malsucedida.

IF @@TRANCOUNT <> 0
    THROW 50000, 'This example owns its transaction.', 1;
SET XACT_ABORT ON;
BEGIN TRY
    BEGIN TRAN;
    DECLARE @rc int;
    EXEC @rc = sys.sp_getapplock
        @Resource = N'invoice:481',
        @LockMode = 'Exclusive',
        @LockOwner = 'Transaction',
        @LockTimeout = 5000,
        @DbPrincipal = 'public';
    IF @rc < 0
        THROW 50001, 'Application lock was not acquired.', 1;
    -- Read durable operation record; perform short database work.
    SELECT @rc AS LockResult;
    COMMIT;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 ROLLBACK;
    THROW;
END CATCH;

Um código não negativo indica aquisição bem-sucedida. Um código negativo representa situações como timeout, cancelamento ou escolha como vítima de deadlock. O exemplo desfaz a transação para qualquer falha. Em produção, classifique os casos para registro e tentativas limitadas, mas nunca interprete falha como autorização para continuar.

Os cinco segundos limitam somente a aquisição desse bloqueio. Não limitam esperas posteriores por linhas, atrasos de rede ou a duração completa. Defina separadamente o orçamento da solicitação e garanta limpeza transacional após cancelamento.

Para testar, abra uma transação em A e adquira o recurso sem terminar. B deve atingir seu timeout. Desfaça A e repita B; agora a aquisição deve funcionar. Teste também recursos de faturas diferentes e confirme que avançam independentemente. Encerre explicitamente a transação deixada aberta no exercício.

Preservar garantias duráveis

Somente caminhos que adquirem o mesmo recurso seguem essa coordenação. Uma alteração administrativa direta ou uma versão antiga do aplicativo pode ignorar a convenção. Preserve restrições únicas, chaves estrangeiras e validações de transições permitidas. O bloqueio coordena participantes; não substitui o modelo de dados.

A liberação também não registra que a operação terminou. Se o cliente perder a resposta após o commit, uma nova tentativa pode adquirir o recurso novamente. Grave um identificador durável de operação e seu resultado na mesma transação da mudança de negócio. Sob o bloqueio, consulte esse registro primeiro e devolva o resultado existente para solicitações duplicadas.

Não mantenha a transação aberta durante uma chamada a um serviço de pagamento. Um rollback SQL não desfaz uma cobrança externa concluída. Grave um item de outbox atomicamente e processe a entrega por um caminho idempotente. Caso uma transação precise de vários recursos, adquira-os sempre na mesma ordem: bloqueios de aplicação também podem participar de deadlocks. Meça falhas de aquisição, tempo de espera e idade transacional para confirmar que somente o trabalho da mesma chave disputa exclusão, enquanto operações independentes continuam concorrentes.

Referências técnicas: Microsoft Learn: sp_getapplock · Microsoft Learn: sp_releaseapplock.

Pergunte sobre este artigo

Tem alguma dúvida sobre este tema?

Conte o que você está avaliando ou onde encontrou dificuldades. Responderemos com uma recomendação prática.

Inquiries are not enabled in this preview.

Fazer uma pergunta sobre este artigo