Não sou muito experiente com SQL Server, então talvez esteja faltando alguma coisa
A minha situação é a seguinte:
- A sessão 1 executa um CREATE TABLE (ou outras instruções CREATE) com autocommit desativado e o CREATE não está sendo confirmado.
- A sessão 2 executa uma
sp_table
instrução, mas trava enquanto a sessão 1 não está confirmando o DDL
O cenário em que isso acontece são os desenvolvedores trabalhando no banco de dados. Alguns deles navegando nas tabelas, alguns deles fazendo DDL. Se um usuário esquecer de confirmar o DDL, todas as outras sessões que desejam listar as tabelas serão bloqueadas. Observe que o sp_tables
é emitido, por exemplo, pelo cliente SQL (através da API do driver JDBC), portanto, não é algo que possa ser alterado.
O banco de dados com o qual estou trabalhando tem snapshot_isolation ativado e o nível de isolamento está definido como leitura confirmada ( SET ALLOW_SNAPSHOT_ISOLATION ON
e SET READ_COMMITTED_SNAPSHOT ON
)
Minha suposição era que essas configurações deveriam fazer com que o SQL Server se comportasse melhor em relação ao bloqueio em sessões simultâneas (por exemplo, como PostgreSQL e Oracle, onde SELECTs nunca são bloqueados por nenhum gravador) - mas aparentemente esse não é o caso.
Então, existe alguma maneira de tornar o SQL Server mais amigável em situações de leitura/gravação simultâneas em relação ao DDL? (além de enviar DDL apenas no modo de confirmação automática).
Não, não há como configurar o SQL Server para fazer o que você deseja.
No isolamento de instantâneo, a chamada para
sp_tables
fica bloqueada aguardando um bloqueio de chave compartilhada em uma das tabelas de base do sistema (sysschobjs
) ao fazer umSELECT
fromsys.all_objects
O tópico Using Row Versioning-based Isolation Levels em BOL diz:
Mesmo sob
TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
a chamada parasp_tables
ends up blocking, no entanto, enquanto o straight forwardSELECT ... FROM sys.all_objects
não está mais bloqueado, a mesma consulta faz referência àHAS_PERMS_BY_NAME
função naWHERE
cláusula. Isso parece iniciar uma transação do sistema (CMetadataAccessor::CMetadataAcce
) em um nível de isolamento mais alto e acaba ficando bloqueado aguardando um bloqueio de chave compartilhadasysschobjs
novamente.Uma ideia: agendar um trabalho a cada 15 segundos para procurar DDLs não confirmados ociosos e encerrar as sessões e revertê-las.