Você está basicamente descrevendo um fluxo de trabalho clássico baseado em fila e deve considerar usar um real fila .
Por uma questão de discussão, aqui está como você consegue o que deseja:
- reivindicar recurso específico:
SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK) WHERE key = @key
. Irá bloquear se o recurso já for reivindicado. Use os tempos limite de bloqueio para retornar a exceção se o recurso já for reivindicado.key
deve ser indexado e exclusivo. - próximo recurso disponível:
SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK, READPAST) ORDER BY <accessorder>
. Você deve definir uma ordem para expressar a preferência dos recursos (mais antigos, de maior prioridade, etc.) - liberar um recurso reivindicado:
COMMIT
sua transação.
A essência do problema é usar as dicas de bloqueio corretas, e esse tipo de problema requer dicas de bloqueio explícitas para resolver. UPDLOCK atuará como um bloqueio de 'reivindicação'. ROWLOCK cria a granularidade correta impedindo que o servidor 'otimize' para um bloqueio de página. READPAST permite que você ignore recursos reivindicados. Colocar UPDLOCK nas linhas bloqueará a linha e permitirá que você a atualize mais tarde, mas impedirá outras operações, como SELECTs de leitura comum que serão bloqueados na linha bloqueada. A idéia é que você vai ATUALIZAR a linha de qualquer maneira, o que colocará um inevitável bloqueio X. Se você quiser manter a tabela mais disponível, você pode usar app locks em vez disso, mas é significativamente mais difícil de realizar corretamente. Você precisará solicitar um bloqueio de aplicativo em um descritor de string do recurso, como o valor da chave, ou um
CHECKSUM
da chave ou é %%LOCKRES%%
valor. Os bloqueios de aplicativo permitem que você separe o escopo da 'reivindicação' de uma transação solicitando o bloqueio do aplicativo no escopo da 'sessão', mas você precisa liberar a reivindicação manualmente (os bloqueios de aplicativo com escopo de 'transação' são liberados no momento da confirmação) . Atenção, porém, existem mil maneiras de dar um tiro no pé com bloqueios de aplicativos.