Как использовать транзакции с SQL Server DDL?


20

У меня есть таблица входа в систему, в которую все вставки выполняются с помощью одной хранимой процедуры.

CREATE TABLE dbo.LogTable(
    LogRefnr int IDENTITY(1, 1) NOT NULL,
    LogQuery varchar(255) NOT NULL,
    LogTime datetime NOT NULL,
    logQueryDuration int NULL,
    LogSessionID int NULL,
 CONSTRAINT PK_Log PRIMARY KEY CLUSTERED  (LogRefnr)
)
go


Create procedure DBO.LogInsert ( @Query varchar(255), @time datetime, @duration int, @SessinID int) as
begin
    Insert into LogTable ( LogRefnr, LogQuery, logQueryDuration, LogSessionID)
    Values  (@Query, @time, @duration, @SessinID);
end;
GO

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

Моя идея состоит в том, чтобы использовать следующий скрипт

begin Transaction

exec sp_rename LogTable, LogTableOld;

CREATE TABLE dbo.LogTable(
    LogRefnr int IDENTITY(46000000, 1) NOT NULL,            -- greater than select max(LogRefnr) from LogTableOld
    LogQuery varchar(255) NOT NULL,
    LogTime datetime NOT NULL,
    logQueryDuration int NULL,
    LogSessionID int NULL,
 CONSTRAINT PK_Log2 PRIMARY KEY CLUSTERED  (LogRefnr);
)
go

sp_recompile LogTable;
go

Commit;

Это работает и имеет минимальное влияние на другие процедуры, вызывающие LogInsert?


2
Вам не нужен sp_recompile. Кэш процедур для любых объектов, использующих объект dbo.LogTable, автоматически истекает при переименовании объекта.
Мрденни

Ответы:


24

Да. Транзакции применяются к партиям DDL и span.

Я бы сделал что-то вроде этого. Обратите внимание на использование SERIALIZABLE ISOLATION для обеспечения полной изоляции и XACT_ABORT, который вызывает откат при любой ошибке.

SET XACT_ABORT ON
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
begin Transaction
GO
exec sp_rename LogTable, LogTableOld;
GO
CREATE TABLE dbo.LogTable(
    LogRefnr int IDENTITY(46000000, 1) NOT NULL,            -- greater than select max(LogRefnr) from LogTableOld
    LogQuery varchar(255) NOT NULL,
    LogTime datetime NOT NULL,
    logQueryDuration int NULL,
    LogSessionID int NULL,
 CONSTRAINT PK_Log2 PRIMARY KEY CLUSTERED  (LogRefnr);
)
go
EXEC sp_recompile LogTable;
go

Commit;

1
Можете ли вы дать ссылку на ссылку, показывающую, что транзакции SQL Server применяются к пакетам DDL и span? Эта очевидные страницы BOL не упоминают об этом.
Ник Чаммас

2
@ Ник: я никогда не искал. Я знаю, что это работает, поскольку я использую это все время. До вас, чтобы поверить мне или опровергнуть меня или попробовать это для себя. Конечно, транзакции для каждого соединения похожи на различные операторы set, которые я использую. Соединение состоит из нескольких партий. Что еще тебе нужно?
ГБН

Я верю вам, но я надеялся на некоторую «официальную» документацию, которая перечисляет все действия, которые связаны с явными транзакциями, а какие нет. Например, на переменные таблицы не влияют откаты транзакций (что, на мой взгляд, нарушает принцип наименьшего сюрприза ).
Ник Чаммас,

2
Почти тот же код, но транзакция не работает: stackoverflow.com/questions/47868213/…
aleyush
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.