SQL Server - обеспечение того, что только одна транзакция пытается создать таблицу - PullRequest
2 голосов
/ 07 декабря 2011

Внутреннему приложению необходимо динамически создавать таблицы SQL на основе некоторых предоставленных критериев. Есть несколько потребителей этого приложения.

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND  TABLE_NAME = 'SomeTableName')) 
BEGIN
   -- Create table in here.
END

Для этого у меня есть вышеуказанная базовая конструкция внутри sproc. Я знаю о возможных условиях состязания, поэтому мое первое решение состояло в том, чтобы добавить несколько подсказок о блокировке в инструкцию SELECT, чтобы гарантировать, что все другие транзакции, проверяющие наличие таблицы, будут заблокированы до завершения других транзакций. Однако независимо от того, какие подсказки я использовал, это не сработает.

Моим следующим решением было обернуть создание таблицы в TRY..CATCH, чтобы, даже если это не помогло, я мог просто игнорировать ошибку. Однако сбой оператора CREATE TABLE обрекает транзакцию, поэтому я не могу продолжить, даже если игнорирую ошибку.

Мое последнее решение, которое работает, состояло в том, чтобы использовать конструкцию TRY..CATCH, и если возникла ошибка, тогда переходим к вершине sproc, где создается новая транзакция, и все проходит нормально, так как таблица существует во второй раз .

Я не доволен решением, так как это похоже на взлом. Любой гуру SQL, кто знает чистое решение этой проблемы?

Просто для пояснения, решение, которое я обсуждал выше, не оказывает большого влияния на производительность, поэтому я действительно ищу чистое решение, которое не имеет большого влияния на производительность.

1 Ответ

2 голосов
/ 07 декабря 2011

Используйте семафоры (или ручную блокировку) с sp_getapplock (верх кода) и sp_releaseapplock (низ кода), чтобы обеспечить только один процесс.

2-й процесс завершится с ошибкой, ожиданием или тайм-аутом в зависимости от параметров sp_getapplock

...