Как транзакция T-SQL не является поточно-ориентированной? - PullRequest
2 голосов
/ 12 февраля 2009

Следующий (очищенный) код иногда выдает эти ошибки:

Невозможно удалить таблицу 'database.dbo.Table', поскольку она не существует или у вас нет разрешения.
В базе данных уже есть объект с именем «Таблица».

begin transaction  
    if exists (select 1 from database.Sys.Tables where name ='Table') 
        begin drop table database.dbo.Table end 

    Select top 3000 *
    into database.dbo.Table
    from OtherTable
commit

select * from database.dbo.Table

Код может быть запущен несколько раз одновременно. Кто-нибудь знает, почему он ломается?

Ответы [ 3 ]

7 голосов
/ 12 февраля 2009

Могу я спросить, почему ты это делаешь первым? Вам действительно следует подумать об использовании временных таблиц или найти другое решение.

Я не уверен, что DDL-отчеты ведут себя в транзакциях так же, как DML-операторы, и видели в блоге сообщение со странным поведением и созданием хранимых процедур в DDL.

Кроме того, вы можете проверить уровень изоляции транзакции и установить для него значение Serialized.

Редактировать

На основании быстрого теста я запустил один и тот же sql в двух разных соединениях, и когда я создал таблицу, но не зафиксировал транзакцию, вторая транзакция заблокировалась. Похоже, это должно работать. Я все еще предостерегаю против этого типа дизайна.

3 голосов
/ 13 февраля 2009

В какой части кода вы запрещаете множественный доступ к этому ресурсу?

begin transaction  
    if exists (select 1 from database.Sys.Tables where name ='Table') 
        begin drop table database.dbo.Table end 

    Select top 3000 *
    into database.dbo.Table
    from OtherTable
commit

Начать транзакцию не делает это. Он настраивается только для сценария фиксации / отката для любых строк, добавляемых в таблицы.

(если существует, отбрасывание) - это состояние гонки, а также воссоздание таблицы с помощью (select..into). Многочисленные люди, заскочившие в этот код сразу, наверняка вызовут всевозможные ошибки. Некоторые создают таблицы, которые другие только что уничтожили, другие отбрасывают таблицы, которые больше не существуют, а другие отбрасывают таблицы, в которые некоторые заняты вставкой. UGH!

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

1 голос
/ 12 февраля 2009

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

...