Чи можу я запустити збережену процедуру та негайно повернутися, не чекаючи, коли вона закінчиться?


41

У нас є збережена процедура, яку користувачі можуть запускати вручну, щоб отримати оновлені номери для звіту, який постійно використовується протягом дня.

У мене є друга збережена процедура, яку слід запустити після запуску першої збереженої процедури, оскільки вона базується на числах, отриманих від цієї першої збереженої процедури, однак запуск займає більше часу і призначений для окремого процесу, тому я не хочу цього робити змусити користувача чекати, поки ця друга зберігається процедура запуститься.

Чи є спосіб, щоб одна збережена процедура запустила другу збережену процедуру та поверталася негайно, не чекаючи результатів?

Я використовую SQL Server 2005.


Як називаються збережені процедури? Веб-додаток ASP.NET? SSRS?
Mr.Brownstone


@ Mr.Brownstone Зазвичай його викликають із веб-програми ASP.Net, хоча його можуть викликати більш ніж один із них. Мені доведеться ще раз перевірити. Він також періодично запускається вручну з SSRS.
Рейчел

@MartinSmith Я колись працював з брокером служби SQL і сподівався, що буде простіший спосіб. Здається, така складна установка для чогось такого простого, як це.
Рейчел

1
@MartinSmith - це майже те, про що я думав - також, що стосується SSRS ні, ти не можеш, але те, що ти міг би зробити, це включити в програму Report Viewer і перемістити в нього свої rdl - таким чином можна було б робити дзвінки асинхронізації для звітів.
Mr.Brownstone

Відповіді:


27

Схоже, існує кілька способів цього досягти, але я виявив, що найпростішим способом було пропозиція Мартіна встановити процедуру в роботі SQL і запустити її за допомогою асинхронної команди sp_start_job з моєї збереженої процедури.

EXEC msdb.dbo.sp_start_job @job_name='Run2ndStoredProcedure'

Це працює тільки для мене, оскільки мені не потрібно вказувати жодні параметри для моєї збереженої процедури.

Інші пропозиції, які можуть працювати в залежності від вашої ситуації, є

  • Використання сервісного брокера SQL, як це пропонують Мартін та Себастьян . Це, мабуть, найкраща пропозиція, якщо ви не заперечуєте над складністю його налаштування та вивченням його роботи.
  • Запуск процесу асинхронно в коді, який відповідає за виконання збереженої процедури, як запропонував Mr.Brownstone .

    Не погана ідея, проте в моєму випадку збережена процедура викликається з декількох місць, тому пошук усіх цих місць та забезпечення того, що вони називають другу процедуру, теж не здається практичним. Крім того, друга збережена процедура є досить критичною, і забуття її запустити може спричинити деякі основні проблеми для нашої компанії.

  • Зробіть 1-ю процедуру встановити прапор та встановіть повторюване завдання, щоб перевірити цей прапор і запустити, чи є його набір, як запропонував Джимбо . Я не великий фанат робіт, які постійно працюють і перевіряють зміни кожні кілька хвилин, але, безумовно, це варіант, який варто розглянути, залежно від вашої ситуації.

3
Перегляньте Асинхронне виконання процедур для прикладу, готового до використання, використовуючи Service Broker. Переваги sp_job в тому, що він працює в Express Edition і повністю міститься в БД (немає залежності від таблиць завдань MSDB). Пізніше дуже важливо для відмови в DBM та відновлення HA / DR.
Рем Русану

Стріляйте, я бачу, як Мартін пов’язав ту саму статтю. Я залишу коментар для аргументів відмови / ДР.
Рем Русану

@RemusRusanu: ну, це одне з найкращих джерел інформації про Service Broker, але, мабуть, ви вже знали ;-).
Маріан

Мені сподобалось посилання від @Rusanu, але я хотів щось без відповіді (на мою думку, відповідає цій проблемі). Я написав свою спрощену версію на abamacus.blogspot.com/2016/05/…
Abacus

Крім того, якщо ви спробуєте запустити завдання агента SQL, це не вдасться EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'., якщо в Azure не існує ні сервісного брокера, ні агента Sql. Я не знаю, чому Microsoft через півтора десятиліття людей, які запитують, відмовляються додавати EXECUTE ASYNC RematerializeExpensiveCacheTable.
Ян Бойд

8

Ви можете використовувати сервісного брокера разом із активацією на черзі. З цим ви можете розмістити параметри для виклику процедури у черзі. Це займає приблизно стільки ж часу, як вставка. Після здійснення транзакції і, можливо, ще декількох секунд, активація автоматично викликає процедуру приймача асинхронно. Він, ніж просто вул, повинен взяти параметри черги і виконати потрібну роботу.


7

Це старе питання заслуговує на більш вичерпну відповідь. Деякі з них згадуються в інших відповідях / коментарях тут, інші можуть або не можуть працювати в конкретній ситуації ОП, але можуть працювати для інших, які шукають асинхронно викликати збережені програми з SQL.

Щоб бути абсолютно явним: TSQL не має (сам по собі) можливість запускати інші операції TSQL асинхронно .

Це не означає, що у вас ще багато варіантів:

  • Завдання агента SQL : Створіть декілька завдань SQL і або плануйте їх запускати на потрібний час, або запускайте їх асинхронно з "головного управління", що зберігається з використанням програми sp_start_job. Якщо вам потрібно відстежувати їхній прогрес програмно, просто переконайтеся, що завдання оновлюють користувальницьку таблицю JOB_PROGRESS (або ви можете перевірити, чи не закінчили вони ще використання функції без документації, xp_sqlagent_enum_jobsяк описано у цій чудовій статті Грегорі А. Ларсена). Вам потрібно створити стільки окремих завдань, скільки потрібно паралельних процесів, навіть якщо вони виконують одну і ту ж збережену процедуру з різними параметрами.
  • Пакет SSIS : для складніших асинхронних сценаріїв створіть пакет SSIS з простим потоком завдань розгалуження. SSIS запустить ті завдання в окремих павуках, які SQL виконуватиме паралельно. Викличте пакет SSIS з завдання агента SQL.
  • Спеціальна програма : Напишіть просту спеціальну програму на обраній вами мові (C #, Powershell тощо), використовуючи асинхронні методи, що надаються цією мовою. Викликайте збережений протокол SQL у кожному потоці програми.
  • OLE Automation : У SQL використовуйте sp_oacreateта sp_oamethodзапускайте новий процес, який викликає один одного, зберігається протокол, як описано в цій статті , також Грегорі А. Ларсен.
  • Сервіс-брокер : Подивіться на використання Service Broker - хороший приклад асинхронного виконання в цій статті .
  • Паралельне виконання CLR : Використовуйте команди CLR Parallel_AddSqlта Parallel_Executeяк описано в цій статті Аланом Капланом (лише для SQL2005 +).
  • Заплановані завдання Windows : перераховано для повноти, але я не прихильник цієї опції.

Якби це я, я, певно, використовував би декілька завдань агента SQL у більш простих сценаріях, а пакет SSIS - у складніших сценаріях.

У вашому випадку виклик завдань SQL Agent звучить як простий і керований вибір.

Останній коментар : SQL вже намагається паралелізувати окремі операції, коли це може *. Це означає, що виконання 2 завдань одночасно замість одного за одним не є гарантією того, що воно закінчиться швидше. Тестуйте уважно, щоб побачити, чи насправді щось покращує чи ні.

У нас був розробник, який створив пакет DTS для одночасного виконання 8 завдань. На жаль, це був лише сервер 4-х процесорів :)

* Якщо припустити налаштування за замовчуванням. Це можна змінити, змінивши максимальну ступінь паралелізму або маску афінності сервера або використовуючи підказку MAXDOP запиту.


6

Так, один метод:

  1. Коли перша збережена процедура завершена, вона вставляє запис з усією інформацією, необхідною для запуску другої збереженої процедури
  2. Друга збережена процедура працює як робота, щохвилини або в який час ви вирішите
  3. Він перевіряє наявність вставлених записів, виконує процес і відмічає запис як закінчений

Це обмежує виконання збереженої процедури кількістю запущених завдань, які, якщо ви хочете, щоб це одночасно викликався одним клієнтом, добре - тоді як у вас може бути кілька клієнтів, що викликають одну і ту ж процедуру одночасно . Крім того, як клієнт знає, що робота завершена, не повторно оглядаючи базу даних, щоб з’ясувати, чи встановлено прапор?
Mr.Brownstone

1
@ Mr.Brownstone - потенційно завдання може обробити більше однієї невирішеної задачі, встановленої в чергу, за допомогою різних збережених викликів процедур, коли вона виконується. Збережена процедура також може закликати sp_start_jobїї запустити або створити завдання, якщо це потрібно, динамічно, щоб уникнути опитування щохвилини, але складність для цього випадку, ймовірно, означає, що це буде не простіше, ніж сервіс-брокер.
Мартін Сміт

@MartinSmith Насправді у мене вже встановлена ​​робота для цієї 2-ої збереженої процедури, оскільки вона використовувалася щоночі, поки ми не виявили, що деякі проблеми не синхронізуються правильно з номерами першої процедури. Якщо я розпочну роботу з 1-ї збереженої процедури, чи буде вона запускатися асинхронно і негайно повертатися з SP?
Рейчел

@Rachel - Так. sp_start_jobповертається негайно. Не можу згадати, які дозволи йому потрібні.
Мартін Сміт

1
Початок роботи з іншої процедури / бази даних є досить складною проблемою, якщо ви не хочете відкривати великі отвори в безпеці. У Ерланда Соммарського є стаття про різні методики, які потрібно поєднувати: sommarskog.se/grantperm.html Однак тут немає повного рішення.
Себастьян Майне

1

Іншою можливістю буде отримання 1-ї збереженої процедури для запису до таблиці аудиту, коли вона завершується, та розміщення тригера на таблиці аудиту, яка запускає другу збережену процедуру, коли записується таблиця аудиту. Немає необхідності в постійному опитуванні та немає необхідності в додатковій роботі агента SQL Server.


3
Перша збережена процедура не повернеться до тих пір, поки вкладка до таблиці аудиту не завершиться, і це не відбудеться до тих пір, поки тригер не завершить виконання (включаючи виклик до другої збереженої процедури)
Мартін Сміт

1
Я вже розглядав використання тригера, але тригери запускаються синхронно з оператором INSERTабо UPDATE, а не асинхронно, тому Мартін правильний, що 1-а процедура все-таки закінчиться очікуванням, поки 2-а процедура не повернеться.
Рейчел
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.