SQL Server запускает асинхронное обновление из триггера? - PullRequest
2 голосов
/ 01 сентября 2011

Если пользователь вставляет строки в таблицу, я бы хотел, чтобы SQL Server выполнил некоторую дополнительную обработку, но не в контексте транзакции пользователя.

например, пользователь предоставляет доступ на чтение к папке:

UPDATE Folders SET ReadAccess = 1
WHERE FolderID = 7

Что касается пользователя, я хочу, чтобы это был конец атомарной операции.На самом деле я должен сейчас найти все дочерние файлы и папки и дать им ReadAccess.

EXECUTE SynchronizePermissions

Это потенциально длительная операция (более 2 с).я хочу, чтобы эта длительная операция произошла " позже ".Это может произойти через 0 секунд, и до того, как у углеродного блока появится возможность подумать об этом, выполняется асинхронное обновление.

Как я могу выполнить эту требуемую операцию асинхронно , когда она требуется (то есть срабатывает )?

идеально будет:

CREATE TRIGGER dbo.Folders FOR INSERT, UPDATE, DELETE AS
   EXECUTEASYNCHRONOUS SynchronizePermissions

или

CREATE TRIGGER dbo.Folders FOR INSERT, UPDATE, DELETE AS
   EXECUTE SynchronizePermissions WITH(ASYNCHRONOUS)

Rightтеперь это происходит как триггер:

CREATE TRIGGER dbo.Folders FOR INSERT, UPDATE, DELETE AS
   EXECUTE SynchronizePermissions

и пользователь вынужден ждать 3 секунды каждый раз, когда он вносит изменения в таблицу Folders.

я думал осоздание запланированной задачи для пользователя, которая запускается каждую минуту, и проверка на наличие флага PermissionsNeedSynchronizing:

CREATE TRIGGER dbo.Folders FOR INSERT, UPDATE, DELETE AS
   UPDATE SystemState SET PermissionsNeedsSynchronizing = 1

Двоичный файл запланированной задачи может проверять этот флаг, запускается, еслиустановлен флаг:

DECLARE @FlagValue int
SET @FlagValue = 0;

UPDATE SystemState SET @FlagValue = PermissionsNeedsSynchronizing+1
WHERE PermissionsNeedsSynchronizing = 1

IF @FlagValue = 2
BEGIN
   EXECUTE SynchronizePermissions

   UPDATE SystemState SET PermissionsNeedsSynchronizing = 0
   WHERE PermissionsNeedsSynchronizing = 2
END

Проблема с запланированной задачей заключается в том, что: - самое быстрое выполнение - каждые 60 секунд - оно страдает от решения опроса - для него требуется исполняемый файл

Я бы предпочел, чтобы SQL Server мог запускать запланированную задачу:

CREATE TRIGGER dbo.Folders FOR INSERT, UPDATE, DELETE AS
   EXECUTE SynchronizePermissionsAsychronous


CREATE PROCEDURE dbo.SynchronizePermissionsAsychronous AS

   EXECUTE sp_ms_StartWindowsScheduledTask @taskName="SynchronousPermissions"

Проблема заключается в следующем: - нет sp_ms_StartWinodowsScheduledTask системной хранимой процедуры

Так что я ищу идеи для лучших решений.


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

CREATE TRIGGER dbo.UpdateFundsTransferValues FOR INSERT, UPDATE AS

UPDATE FundsTransfers
SET TotalOrderValue = (SELECT ....[snip]....),
    TotalDropValue = (SELECT ....,[snip]....)
WHERE FundsTransfers.FundsTransferID IN (
    SELECT i.FundsTransferID
    FROM INSERTED i
)

И проблема, с которой я сталкиваюсь сегодня, - это способ асинхронного обновления некоторыхметаданные после вставки или изменения строки:

CREATE TRIGGER dbo.UpdateCDRValue FOR INSERT, UPDATE AS

UPDATE LCDs
SET CDRValue = (SELECT ....[snip]....)
WHERE LCDs.LCDGUID IN (
    SELECT i.LCDGUID
    FROM INSERTED i
)

Обновление 2 : я думал о создании нативной или управляемой dll и использовании ее в качестверасширенная хранимая процедура.Проблема в том, что

  • вы не можете написать скрипт для двоичного файла
  • Теперь мне разрешено это делать

Ответы [ 3 ]

6 голосов
/ 01 сентября 2011

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

1 голос
/ 01 сентября 2011

Создайте задание агента SQL и запустите его с помощью sp_start_job..Это не должно ждать завершения

Однако вам необходимо соответствующее разрешение для запуска заданий

Члены SQLAgentUserRole иSQLAgentReaderRole может запускать только те задания, которые им принадлежат.Члены SQLAgentOperatorRole могут запускать все локальные задания, включая те, которые принадлежат другим пользователям.Члены sysadmin могут запускать все локальные и многосерверные задания.

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

В противном случаепереходите к таблице очередей, предложенной Аароном, она чище и лучше

0 голосов
/ 13 октября 2013

Мы столкнулись с этой проблемой некоторое время назад, и я нашел решение, которое прекрасно работает. У меня есть процесс, работающий в фоновом режиме - но, как и вы, я не хотел, чтобы он проводил опрос каждые 60 секунд.

Вот шаги:

(1) Наш триггер не запускает само обновление базы данных. Он просто выбрасывает «файл флага» в папку, отслеживаемую фоновым процессом.

(2) Фоновый процесс отслеживает эту папку с помощью Windows Уведомление об изменении (это действительно классная часть, потому что вам не нужно опрашивать папку - ваш процесс спит, пока Windows не уведомит его о появлении файла). Всякий раз, когда Windows вызывает фоновый процесс, он запускает обновление базы данных. Затем он удаляет файл (ы) флагов, снова переходит в спящий режим и говорит Windows активировать его, когда в папке появляется другой файл.

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

Для этого необязательно компилировать собственный исполняемый файл: многие языки сценариев могут использовать уведомление об изменении Windows. Я написал фоновый процесс на Perl, и это заняло всего несколько минут.

...