Tenho um teste sintético, que reproduz algum erro que temos no ambiente de produção. Aqui estão os 2 scripts para reproduzi-lo:
1º
DBCC TRACEOFF(-1,3604,1200) WITH NO_INFOMSGS;
SET NOCOUNT ON;
IF @@TRANCOUNT > 0 ROLLBACK
IF object_id('test') IS NOT NULL
DROP TABLE test
IF object_id('TMP_test') IS NOT NULL
DROP TABLE TMP_test
IF object_id('test1') IS NOT NULL
DROP TABLE test1
CREATE TABLE test(Id INT IDENTITY PRIMARY KEY)
GO
INSERT test DEFAULT VALUES
GO 2000
WHILE 1 = 1
BEGIN
CREATE TABLE TMP_test(Id INT PRIMARY KEY)
INSERT TMP_test SELECT * FROM test
WAITFOR DELAY '0:00:00.1'
BEGIN TRAN
EXEC sp_rename 'test', 'test1'
EXEC sp_rename 'TMP_test', 'test'
EXEC sp_rename 'test1', 'TMP_test'
DROP TABLE TMP_test
commit
END
2º
SET NOCOUNT ON;
DECLARE @c INT
WHILE 1 = 1
BEGIN
SELECT @c = COUNT(*) FROM Test IF @@ERROR <> 0 BREAK
SELECT @c = COUNT(*) FROM Test IF @@ERROR <> 0 BREAK
/* and repeat this 10-20 times more*/
SELECT @c = COUNT(*) FROM Test IF @@ERROR <> 0 BREAK
END
Então, o problema é que quando executo o 1º script em uma sessão e deixo rodando, e depois executo o 2º em sessão separada, posso obter este tipo de erro:
Msg 208, Nível 16, Estado 1, Linha 13 Nome de objeto inválido 'Teste'.
A questão é - POR QUE vejo esse erro no caso de haver um COMMIT
no final do ciclo do primeiro script e nunca recebo um se houver um ROLLBACK
?
Tenho a sensação de que está de alguma forma conectado à situação, quando o script é confirmado, ainda há a tabela com o nome test
, mas é um objeto diferente e o segundo script precisa se recompilar. E tudo bem. Mas por que ele recebe o erro de tabela perdida? AFAIK - quando eu renomeio a tabela dentro de uma transação - ela mantém o bloqueio Sch-M no final da transação?
Alguém pode responder ou me guiar para os artigos técnicos que posso ler profundamente e entender o motivo?