Транзакции (хранилище данных sql)transactions (sql data warehouse)

Подготовка

Создадим на сервере базу данных с названием Test и выполним на ней несколько SQL-скриптов. В версии 2005 появился механизм версионности, нам он также понадобится, но вначале нужно включить его на нашей базе данных.

USE master
ALTER DATABASE Test SET ALLOW_SNAPSHOT_ISOLATION ON 
GO
USE test

Создаем «подопытные» таблицы для тестов и заполним их данными. Предположим, что мы собираем поступающую с датчиков информацию в таблицу DevicesData. Поле DeviceId содержит идентификатор устройства, а поле Value — последнее полученное значение.


CREATE TABLE DevicesData (
   DeviceId int not null, 
   Value    int not null,
   CONSTRAINT PK_DevicesData PRIMARY KEY (DeviceId)
)
GO

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

TRUNCATE TABLE DevicesData
DECLARE @n int 
SET @n = 999
DECLARE @List TABLE (n int)
WHILE @n >=  BEGIN
   INSERT INTO @List (n)
   SELECT @n
   SET @n = @n - 1
END
INSERT INTO DevicesData (DeviceId, Value)
SELECT A.n * 1000 + B.n,  
FROM @List A CROSS JOIN @List B
GO

Транзакции с MySQL

MySQL предоставляет пользователям две транзакционные подсистемы хранения данных: InnoDB и NDB Cluster. Существует также несколько подсистем сторонних разработчиков. Наиболее известны сейчас XtraDB и РВХТ. В следующем разделе мы обсудим некоторые свойства каждой из них.

AUTOCOMMIT

По умолчанию MySQL работает в режиме . Это означает, что, пока вы не начали транзакцию явно, каждый запрос автоматически выполняется в отдельной транзакции. Вы можете установить или отключить режим для текущего соединения, задав значение переменной:

Значения и эквивалентны, так же как и . После отправки запроса в режиме вы оказываетесь в транзакции, пока не выполните команду или . После этого MySQL немедленно начинает новую транзакцию. Изменение значения переменной не влияет на нетранзакционные таблицы, такие как MyISAM или Memory, которые не имеют понятия о подтверждении или отмене транзакций.

Некоторые команды, будучи запущенными во время начатой транзакции, застав­ляют MySQL подтвердить транзакцию до их выполнения. Обычно это команды языка определения данных (Data Definition Language, DDL), которые вносят изменения в структуру таблиц, например , но и другие директивы также обладают этим свойством. В документации к своей версии MySQL вы можете найти полный список команд, автоматически фиксирующих транзакцию.

MySQL позволяет устанавливать уровень изолированности с помощью команды , которая начинает действовать со следующей транзак­ции. Можете настроить уровень изолированности для всего сервера в конфигураци­онном файле или только для своей сессии:

MySQL распознает все четыре стандартных уровня изоляции ANSI, a InnoDB все их поддерживает.

Использование нескольких подсистем хранения данных в транзакциях

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

Если вы используете транзакционные и нетранзакционные таблицы (например, та­блицы InnoDB и MyISAM) в одной транзакции, то все будет работать хорошо, пока не произойдет что-то неожиданное.

Однако если потребуется выполнить откат, то невозможно будет отменить измене­ния, внесенные в нетранзакционную таблицу. Из-за этого база данных становится несогласованной, и восстановить ее после такого события нелегко, что ставит под сомнение идею транзакций в целом

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

MySQL обычно не предупреждает и не выдает сообщений об ошибках, если вы вы­полняете транзакционные операции над нетранзакционной таблицей. Иногда при откате транзакции может быть сгенерировано предупреждение Some nontransactional changed tables couldn’t be rolled back (Откат некоторых измененных нетранзакционных таблиц невозможен), но большую часть времени вы не будете знать о том, что рабо­таете с нетранзакционными таблицами.

Явные и неявные блокировки

В подсистеме хранения InnoDB применяется двухфазный протокол блокировки. Она может устанавливать блокировки в любой момент транзакции, но не снимает их до выполнения команд или . снимаются одновременно. Ранее описанные механизмы блокировки являются неявными. InnoDB обрабатывает блокировки автоматически в соответствии с вашим уровнем изоляции.

Однако InnoDB поддерживает и явную блокировку, которая в стандарте SQL вообще не упоминается:

  • ;
  • .

MySQL также поддерживает команды и , которые реали­зуются на сервере, а не в подсистеме хранения. Они применяются в определенных случаях, но не служат заменой транзакциям. Если вам нужны транзакции, исполь­зуйте транзакционную подсистему хранения.

Нам часто попадаются приложения, которые были перенесены из MyISAM в InnoDB, но в которых по-прежнему используется команда . В этой команде боль­ше нет необходимости, так как применяются построчные блокировки, а проблемы с производительностью она может вызывать серьезные. 

Модель развития базы данных My… 519 просмотров Ирина Светлова Thu, 10 Jan 2019, 12:29:03

Выбор оптимальных типов данных… 1624 просмотров Валерий Павлюков Sun, 27 Oct 2019, 15:24:19

Подсистемы хранения в MySQL 1062 просмотров Ирина Светлова Wed, 09 Jan 2019, 04:26:23

Обзор версий MySQL — какой рел… 2392 просмотров Ирина Светлова Thu, 10 Jan 2019, 08:02:16

Author: Ирина Светлова

Другие статьи автора:

SQL Transaction in IF ELSE statement

The Transactions are much useful if we place them inside any conditional statements such as IF ELSE. For instance, checking for the existing records in the employee table before the insertion, and if it is there, then rollback, else commit, etc.


The below statement is a simple SQL Server Transactions example, where we declared a variable (assuming user going to enter the value). Next, we used the insert statement, next within the If we are checking whether the @sales is less than 1000 or not. If it is true, ROLLBACK the transaction otherwise, Commit the transaction in SQL Select statement.

OUTPUT

Let me show you the records

This time we changed the variable @Sales value to 1450.02

OUTPUT

let me show you the result data in the employee table.

Ведение журнала транзакций

Ведение журнала помогает сделать транзакции более эффективными. Вместо обнов­ления таблиц на диске после каждого изменения подсистема хранения данных может изменить находящуюся в памяти копию данных. Это происходит очень быстро. Затем подсистема хранения запишет сведения об изменениях в журнал транзакции, который хранится на диске и поэтому долговечен. Это тоже доволь­но быстрая операция, поскольку добавление событий в журнал сводится к опе­рации последовательного ввода/вывода в пределах ограниченной области диска вместо случайного ввода/вывода в разных местах. Позже процесс обновит табли­цу на диске. Таким образом, большинство подсистем хранения данных, которые используют этот метод (упреждающую запись в журнал), дважды сохраняют из­менения на диске.

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

Чек-лист рефакторинга

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

Паттерн:

Обернуть в «безопасную» конструкцию с Попыткой, Проверкой активности и пробросом исключения.

Паттерн:

Анализ и Рефакторинг. Автор не понимал, что делает. Начинать вложенные транзакции можно безопасно. Не нужно проверять условие, нужно просто начать вложенную транзакцию. Ниже по модулю он наверняка еще там извращается с их фиксацией. Это гарантированный геморрой.

Примерно похожий вариант:

аналогично: фиксация транзакции по условию — это странно. Почему тут условие? Что, кто-то иной мог уже зафиксировать эту транзакцию? Повод для разбирательства.

Паттерн:

  1. ввести управляемую блокировку во избежание deadlock
  2. ввести вызов метода Заблокировать
  3. обернуть в «попытку», как показано выше

Паттерн:

Данная транзакция уже не завершится в случае исключения. Нет смысла продолжать цикл. Код требуется переписать, сверяясь с исходной задачей. Дополнительно обеспечить более информативное сообщение об ошибке.

Automatically rollback SQL transactions

As I said earlier, if one of the queries in a group of queries executed inside a transaction fails, all the previously executed SQL statements are rollbacked. Let’s see how transactions can be used to rollback SQL queries:

1 2 3 4 5 6 7 8 9 10 11 12

BEGINTRANSACTION

INSERTINTOBooks

VALUES(20,’Book15′,’Cat5′,2000)

UPDATEBooks

SETprice=’25 Hundred’WHEREid=20


DELETEfromBooks

WHEREid=20

COMMITTRANSACTION

To start a transaction, the BEGIN TRANSACTION statement is used, followed by the set of queries that you want to execute inside the transaction. To mark the end of a transaction, the COMMIT TRANSACTION statement can be used.

In the script above, we execute the same three SQL queries that we did in the last section. However, this time the queries have been executed inside a transaction. Again, the first query will execute successfully and an error will occur while executing the second query. Since the queries are being executed inside a transaction, the failure of the second query will cause all the previously executed queries to rollback. Now, if you select all the records from the Books table, you will not see the new record with id 20, inserted by the first query inside the transaction.

RemarksRemarks

Если установлено значение ON, система находится в неявном режиме транзакции.When ON, the system is in implicit transaction mode. Это означает, что если @@TRANCOUNT = 0, любая из следующих инструкций Transact-SQL начинает новую транзакцию.This means that if @@TRANCOUNT = 0, any of the following Transact-SQL statements begins a new transaction. Это эквивалентно выполнению невидимой инструкции BEGIN TRANSACTION:It is equivalent to an unseen BEGIN TRANSACTION being executed first:

Если задано значение OFF, каждая из предыдущих инструкций T-SQL ограничена невидимыми инструкциями BEGIN TRANSACTION и COMMIT TRANSACTION.When OFF, each of the preceding T-SQL statements is bounded by an unseen BEGIN TRANSACTION and an unseen COMMIT TRANSACTION statement. При значении OFF транзакция выполняется в режиме автофиксации.When OFF, we say the transaction mode is autocommit. Если ваш код T-SQL выдает видимую инструкцию BEGIN TRANSACTION, транзакция выполняется в явном режиме.If your T-SQL code visibly issues a BEGIN TRANSACTION, we say the transaction mode is explicit.

Необходимо понимать несколько важных моментов.There are several clarifying points to understand:

  • Когда транзакция выполняется в неявном режиме, невидимая инструкция BEGIN TRANSACTION не выдается, если @@trancount уже > 0.When the transaction mode is implicit, no unseen BEGIN TRANSACTION is issued if @@trancount > 0 already. Тем не менее все явные инструкции BEGIN TRANSACTION по-прежнему имеют шаг приращения @@TRANCOUNT.However, any explicit BEGIN TRANSACTION statements still increment @@TRANCOUNT.

  • После завершения инструкции INSERT и остальных единиц работы необходимо выполнить инструкции COMMIT TRANSACTION, пока @@TRANCOUNT не вернется к значению 0.When your INSERT statements and anything else in your unit of work is finished, you must issue COMMIT TRANSACTION statements until @@TRANCOUNT is decremented back down to 0. Или выполнить одну инструкцию ROLLBACK TRANSACTION.Or you can issue one ROLLBACK TRANSACTION.

  • Инструкции SELECT, которые не производят выборку из таблицы, не запускают неявные транзакции.SELECT statements that do not select from a table do not start implicit transactions. Например, или не требуют транзакций.For example or do not require transactions.

  • Неявные транзакции могут неожиданно получить значение ON в связи со значениями по умолчанию ANSI.Implicit transactions may unexpectedly be ON due to ANSI defaults. Дополнительные сведения см. в разделе SET ANSI_DEFAULTS (Transact-SQL).For details see SET ANSI_DEFAULTS (Transact-SQL).

    Инструкция IMPLICIT_TRANSACTIONS ON не пользуется популярностью.IMPLICIT_TRANSACTIONS ON is not popular. В большинстве случаев значение ON для параметра IMPLICIT_TRANSACTIONS возникает из-за выбора SET ANSI_DEFAULTS ON.In most cases where IMPLICIT_TRANSACTIONS is ON, it is because the choice of SET ANSI_DEFAULTS ON has been made.

  • Поставщик OLE DB для Native Client SQL ServerSQL Server для SQL ServerSQL Server и драйвер ODBC для Native Client SQL ServerSQL Server при соединении автоматически устанавливают для параметра IMPLICIT_TRANSACTIONS значение OFF.The SQL ServerSQL Server Native Client OLE DB Provider for SQL ServerSQL Server, and the SQL ServerSQL Server Native Client ODBC driver, automatically set IMPLICIT_TRANSACTIONS to OFF when connecting. SET IMPLICIT_TRANSACTIONS по умолчанию устанавливается в значение OFF для соединений с управляемым поставщиком SQLClient и SOAP-запросов, получаемых через конечные точки протокола HTTP.SET IMPLICIT_TRANSACTIONS defaults to OFF for connections with the SQLClient managed provider, and for SOAP requests received through HTTP endpoints.

Чтобы просмотреть текущее значение параметра для IMPLICIT_TRANSACTIONS, выполните следующий запрос.To view the current setting for IMPLICIT_TRANSACTIONS, run the following query.

一般备注General Remarks

BEGIN TRANSACTION 使 @@TRANCOUNT 按 1 递增。BEGIN TRANSACTION increments @@TRANCOUNT by 1.

BEGIN TRANSACTION 代表一点,由连接引用的数据在该点逻辑和物理上都一致的。BEGIN TRANSACTION represents a point at which the data referenced by a connection is logically and physically consistent. 如果遇上错误,在 BEGIN TRANSACTION 之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态。If errors are encountered, all data modifications made after the BEGIN TRANSACTION can be rolled back to return the data to this known state of consistency. 每个事务继续执行直到它无误地完成并且用 COMMIT TRANSACTION 对数据库作永久的改动,或者遇上错误并且用 ROLLBACK TRANSACTION 语句擦除所有改动。Each transaction lasts until either it completes without errors and COMMIT TRANSACTION is issued to make the modifications a permanent part of the database, or errors are encountered and all modifications are erased with a ROLLBACK TRANSACTION statement.

BEGIN TRANSACTION 为发出本语句的连接启动一个本地事务。BEGIN TRANSACTION starts a local transaction for the connection issuing the statement. 根据当前事务隔离级别的设置,为支持该连接所发出的 Transact-SQLTransact-SQL 语句而获取的许多资源被该事务锁定,直到使用 COMMIT TRANSACTION 或 ROLLBACK TRANSACTION 语句完成该事务为止。Depending on the current transaction isolation level settings, many resources acquired to support the Transact-SQLTransact-SQL statements issued by the connection are locked by the transaction until it is completed with either a COMMIT TRANSACTION or ROLLBACK TRANSACTION statement. 长时间处于未完成状态的事务会阻止其他用户访问这些锁定的资源,也会阻止日志截断。Transactions left outstanding for long periods of time can prevent other users from accessing these locked resources, and also can prevent log truncation.

虽然 BEGIN TRANSACTION 启动一个本地事务,但是在应用程序接下来执行一个必须记录的操作(如执行 INSERT、UPDATE 或 DELETE 语句)之前,它并不被记录在事务日志中。Although BEGIN TRANSACTION starts a local transaction, it is not recorded in the transaction log until the application subsequently performs an action that must be recorded in the log, such as executing an INSERT, UPDATE, or DELETE statement. 应用程序能执行一些操作,例如为了保护 SELECT 语句的事务隔离级别而获取锁,但是直到应用程序执行一个修改操作后日志中才有记录。An application can perform actions such as acquiring locks to protect the transaction isolation level of SELECT statements, but nothing is recorded in the log until the application performs a modification action.

在一系列嵌套的事务中用一个事务名给多个事务命名对该事务没有什么影响。Naming multiple transactions in a series of nested transactions with a transaction name has little effect on the transaction. 系统仅登记第一个(最外部的)事务名。Only the first (outermost) transaction name is registered with the system. 回滚到其他任何名称(有效的保存点名除外)都会产生错误。A rollback to any other name (other than a valid savepoint name) generates an error. 事实上,回滚之前执行的任何语句都不会在错误发生时回滚。None of the statements executed before the rollback is, in fact, rolled back at the time this error occurs. 这些语句仅当外层的事务回滚时才会进行回滚。The statements are rolled back only when the outer transaction is rolled back.

如果在语句提交或回滚之前执行了如下操作,由 BEGIN TRANSACTION 语句启动的本地事务将升级为分布式事务:The local transaction started by the BEGIN TRANSACTION statement is escalated to a distributed transaction if the following actions are performed before the statement is committed or rolled back:

  • 执行一个引用链接服务器上的远程表的 INSERT、DELETE 或 UPDATE 语句。An INSERT, DELETE, or UPDATE statement that references a remote table on a linked server is executed. 如果用于访问链接服务器的 OLE DB 访问接口不支持 ITransactionJoin 接口,则 INSERT、UPDATE 或 DELETE 语句会失败。The INSERT, UPDATE, or DELETE statement fails if the OLE DB provider used to access the linked server does not support the ITransactionJoin interface.

  • 当启用了 REMOTE_PROC_TRANSACTIONS 选项时,将调用远程存储过程。A call is made to a remote stored procedure when the REMOTE_PROC_TRANSACTIONS option is set to ON.

SQL ServerSQL Server 的本地副本成为事务控制器并且使用 MicrosoftMicrosoft 分布式事务处理协调器 (MS DTC) 来管理分布式事务。The local copy of SQL ServerSQL Server becomes the transaction controller and uses MicrosoftMicrosoft Distributed Transaction Coordinator (MS DTC) to manage the distributed transaction.


使用 BEGIN DISTRIBUTED TRANSACTION 可以将事务作为分布式事务显式执行。A transaction can be explicitly executed as a distributed transaction by using BEGIN DISTRIBUTED TRANSACTION. 有关详细信息,请参阅 BEGIN DISTRIBUTED TRANSACTION (Transact-SQL)。For more information, see BEGIN DISTRIBUTED TRANSACTION (Transact-SQL).

SET IMPLICIT_TRANSACTIONS 设置为 ON 时,BEGIN TRANSACTION 语句创建两个嵌套的事务。When SET IMPLICIT_TRANSACTIONS is set to ON, a BEGIN TRANSACTION statement creates two nested transactions. 有关详细信息,请参阅 SET IMPLICIT_TRANSACTIONS (Transact-SQL)For more information see, SET IMPLICIT_TRANSACTIONS (Transact-SQL)

Пример транзакции

Пример: необходимо перевести с банковского счёта номер 5 на счёт номер 7 сумму в 10 денежных единиц. Этого можно достичь, к примеру, приведённой последовательностью действий:

  1. Прочесть баланс на счету номер 5.
  2. Уменьшить баланс на 10 денежных единиц.
  3. Сохранить новый баланс счёта номер 5.
  4. Прочесть баланс на счету номер 7.
  5. Увеличить баланс на 10 денежных единиц.
  6. Сохранить новый баланс счёта номер 7.

Эти действия представляют собой логическую единицу работы «перевод суммы между счетами», и таким образом, являются транзакцией. Если прервать данную транзакцию, к примеру, в середине, и не аннулировать все изменения, легко оставить владельца счёта номер 5 без 10 единиц, тогда как владелец счета номер 7 их не получит.

В каких случаях следует применять автономные транзакции

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

  •  Механизм протоколирования. Требуется записать информацию об ошибке в та­блицу базы данных, а также выполнить откат внутренней транзакции, приведшей к ошибке. При этом вы не хотите, чтобы из таблицы-журнала были удалены и дру­гие записи об ошибках. Сделайте внутреннюю транзакцию автономной! Вероятно, это самая распространенная причина для использования автономных транзакций в коде .
  •  Фиксация и откат в триггерах базы данных. Определив триггер как автономную транзакцию, все выполненные им изменения можно фиксировать или отменять, и это никак не отразится на транзакции, приведшей к срабатыванию триггера. Для чего это может быть нужно? Например, в триггере базы данных можно выполнить действие, которое не зависит от статуса транзакции, вызвавшей срабатывание триг­гера. Предположим, вы хотите отслеживать все действия с таблицей независимо от того, было это действие завершено или нет. А может, вы хотите отслеживать действия, завершившиеся неудачей. Примеры использования этого приема пред­ставлены в сценариях autontrigger*.sql на сайте книги.
  •  Многократно используемые компоненты приложения. Для программ этого типа возможность определять автономные транзакции жизненно необходима. В совре­менных системах, особенно в распределенном и многоуровневом мире Интернета, необходимы независимые программные единицы, выполняемые без каких-либо побочных эффектов для среды вызова. Автономные транзакции играют важную роль в этой области.
  •  Предотвращение каскадных триггерных ошибок. Такие ошибки возникают в ситу­ации, когда триггер уровня строки таблицы пытается читать или записывать данные в таблицу, из которой он сработал. Но если преобразовать триггер в автономную транзакцию, включив директиву и закрепив изменения в теле триггера, код последнего сможет запрашивать содержимое таблицы, но при этом будет видеть только уже закрепленные изменения. Иначе говоря, в таблице не будут видны изменения, внесение которых привело к срабатыванию триггера. Кроме того, код триггера не сможет изменять содержимое таблицы.
  •  Вызов пользовательских функций в коде SQL, изменяющем таблицы. Oracle позволяет вызывать в командах пользовательские функции — при условии, что функция не обновляет базу данных (и с некоторыми дополнительными ус­ловиями). Но если функция будет определена как автономная транзакция, вы можете выполнять в ней операции вставки, обновления и удаления в ходе запроса. Данная возможность продемонстрирована в сценарии trcfunc.sql на сайте книги.
  •  Счетчик попыток. Допустим, вы хотите предоставить пользователю N попыток обращения к ресурсу, причем количество попыток должно сохраняться между под­ключениями к базе данных. Для этого необходима команда , независимая от транзакции. Примеры представлены в файлах retry.pkg и retry.tst на сайте книги.

Аномалия сериализации (Потерянное обновление)

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

Документация на сайте PostgreSQL PRO пишет, что Read Committed допускает . Отечественная Wikipedia, не настаивая на то, что таблица относится именно к PostgreSQL, пишет, что Read Commited предотвращает . Английская Википедиа о таком феномене чтения данных . Но немецкая Википедия приводит в своей версии таблицы феномен , указывая на то, что Read Committed может быть не подвержен потере обновлений с дополнительной защитой через курсор (Cursor Stability). Украинская Википедия поддерживает русскоязычную версию статьи, испанская Википедия поддерживает английскую версию статьи. Англоязычная документация по PostgreSQL от документации с сайта PostgreSQL PRO.

Добавление метода транзакции в InventoryDAL

А теперь посмотрим, как работать с транзакциями ADO.NET программным образом. Откройте созданный ранее проект AutoLotDAL Code Library и добавьте в класс InventoryDAL новый общедоступный метод ProcessCreditRisk(), предназначенный для работы с кредитными рисками (в данном примере для простоты не используется параметризованный запрос, но в производственном методе его следует задействовать):

Здесь используется входной параметр типа bool, который указывает, нужно ли генерировать произвольное исключение при попытке обработки нежелательного клиента. Это позволит имитировать непредвиденные ситуации, которые могут привести к неудачному завершению транзакции. Понятно, что здесь это сделано лишь в демонстрационных целях; в реальности метод транзакции не должен позволять вызывающему процессу разрушать всю логику по своему усмотрению!

Мы используем два объекта SqlCommand, представляющие каждый шаг предстоящей транзакции. После получения имени и фамилии клиента по входному параметру custID с помощью метода BeginTransaction() объекта подключения получаем нужный объект SqlTransaction. Если этого не сделать, логика вставки/удаления не будет выполняться в транзакционном контексте.

Если (и только если) значение логического параметра равно true, то после вызова ExecuteNonQuery() для обеих команд генерируется исключение. В этом случае все ожидающие подтверждения операции базы данных аннулируются. Если исключение не было сгенерировано, оба шага фиксируются в таблицах базы данных при вызове Commit(). Скомпилируйте измененный проект AutoLotDAL и проверьте, нет ли ошибок.

标记的事务Marked Transactions

WITH MARK 选项使事务名被置于事务日志中。The WITH MARK option causes the transaction name to be placed in the transaction log. 将数据库还原到早期状态时,可使用标记事务代替日期和时间。When restoring a database to an earlier state, the marked transaction can be used in place of a date and time. 有关详细信息,请参阅 使用标记的事务一致地恢复相关的数据库的事务(完全恢复模式)和 RESTORE (Transact-SQL)。For more information, see Use Marked Transactions to Recover Related Databases Consistently (Full Recovery Model) and RESTORE (Transact-SQL).

另外,若要将一组相关数据库恢复到逻辑上一致的状态,必须使用事务日志标记。Additionally, transaction log marks are necessary if you need to recover a set of related databases to a logically consistent state. 标记可由分布式事务置于相关数据库的事务日志中。Marks can be placed in the transaction logs of the related databases by a distributed transaction. 将这组相关数据库恢复到这些标记将产生一组在事务上一致的数据库。Recovering the set of related databases to these marks results in a set of databases that are transactionally consistent. 在相关数据库中放置标记需要特殊的过程。Placement of marks in related databases requires special procedures.

只有当数据库由标记事务更新时,才在事务日志中放置标记。The mark is placed in the transaction log only if the database is updated by the marked transaction. 不修改数据的事务不被标记。Transactions that do not modify data are not marked.

在已存在的未标记事务中可以嵌套 BEGIN TRAN new_name WITH MARK**。BEGIN TRAN new_name WITH MARK can be nested within an already existing transaction that is not marked. 嵌套后,new_name 便成为事务的标记名,不论是否已为事务提供了名称**。Upon doing so, new_name becomes the mark name for the transaction, despite the name that the transaction may already have been given. 在以下示例中, 是标记名。In the following example, is the name of the mark.

嵌套事务时,尝试标记一个已标记的事务将产生警告(非错误)消息:When nesting transactions, trying to mark a transaction that is already marked results in a warning (not error) message:

«BEGIN TRAN T1 WITH MARK …;»»BEGIN TRAN T1 WITH MARK …;»

«UPDATE table1 …;»»UPDATE table1 …;»

«BEGIN TRAN M2 WITH MARK …;»»BEGIN TRAN M2 WITH MARK …;»

«Server: Msg 3920, Level 16, State 1, Line 3″»Server: Msg 3920, Level 16, State 1, Line 3»

«WITH MARK option only applies to the first BEGIN TRAN WITH MARK.»»WITH MARK option only applies to the first BEGIN TRAN WITH MARK.»

«The option is ignored.»»The option is ignored.»


С этим читают