В SQL Server 2005 эмулируется автономная транзакция - PullRequest
1 голос
/ 19 января 2011

Мне нужно хранить некоторые данные журнала в разных таблицах, даже если транзакция откатывается.

Я уже узнал, что в SQL Server невозможно сделать что-то подобное

begin tran t1
insert ...
insert ...
select ...
       begin tran t2
         insert into log
       commit tran t2
rollback tran t1
select * from log -- IS EMPTY ALWAYS

Поэтому я пытаюсь взломать SQL Server, который я добавил CLR, который собирается экспортировать данные для LOG на диск локального сервера в формате XML. Код CLR прост, как может быть:

File.WriteAllText(fileName, xmlLog.Value.ToString());

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

Вот несколько вопросов:

  • Есть ли другой лучший способ выполнить автономную транзакцию в SQL Server 2005
  • Как может быть плохо удерживать мою транзакцию незафиксированной, когда SQL Server выполняет CLR (объем данных, записываемых SQL, относительно мал - около 50 - 60 записей с 3 целыми числами и 4 числами с плавающей запятой)

1 Ответ

3 голосов
/ 22 января 2011

Я бы предложил использовать переменную таблицы, поскольку транзакция на нее не влияет (это один из методов, перечисленных в блоге, отмеченном Мартином ниже вопроса).Подумайте об этом, что будет работать в SQL Server 2005:

DECLARE @TempLog TABLE (FieldList...)

BEGIN TRY

    BEGIN TRAN

    INSERT...

    INSERT INTO @TempLog (FieldList...) VALUES (@Variables or StaticValues...)

    INSERT...

    INSERT INTO @TempLog (FieldList...) VALUES (@Variables or StaticValues...)

    COMMIT TRAN

END TRY
BEGIN CATCH

    IF (@@TRANCOUNT > 0)
    BEGIN
        ROLLBACK TRAN
    END

    /* Maybe add a Log message to note that we ran into an error */
    INSERT INTO @TempLog (FieldList...) VALUES (@Variables or StaticValues...)

END CATCH

INSERT INTO RealLogTable (FieldList...)
    SELECT FieldsList
    FROM @TempLog

Обратите внимание, что, хотя мы используем тот факт, что переменные таблицы не являются частью транзакции, это создает потенциальную ситуацию, когда этокод выполняет COMMIT, но выдает ошибки (или происходит сбой сервера) перед INSERT INTO RealLogTable, и вы потеряете запись для данных, которые его внесли. В этот момент будет отключение, поскольку есть данные, но нет записи об ихвставлено, насколько это касается RealLogTable.Но это только очевидный компромисс для возможности обойти транзакцию.

...