Запуск скрипта Python из триггера вставки

10

У нас есть хороший кусок Python, который отправляет некоторые электронные письма и взаимодействует с облачной системой. Работает отлично. Но мы должны стрелять каждые несколько минут, чтобы опросить БД. Для бизнес-целей нам действительно нужно, чтобы скрипт Python запускался в реальном времени, чтобы не было задержки при опросе. (Это обслуживает продавцов, которые разговаривают по телефону с покупателями.)

Мы действительно не хотим 1-минутного цикла опроса. Или 30 секунд. Мы хотим, чтобы запись была показана в БД и чтобы все происходило сразу.

Самый быстрый способ заставить эту муху запустить ее, когда в таблицу вставлен определенный тип записи.

Можем ли мы запустить скрипт Python из триггера?

Согласно примечанию Аарона ниже, мы знаем, что это Very Bad Thing ™ , но эта таблица очень и очень мало используется (0-12 вставок в день). Опрос таблицы не отвечает нашим бизнес-потребностям (нам нужен .py для немедленного запуска - он делает гораздо больше, чем просто отправляет электронное письмо).

Мы считаем, что способ удовлетворения потребностей нашего бизнеса состоит в том, чтобы установить .net версию python на SQL Server, а затем заставить T-SQL вызывать скрипт python так же, как он вызывает C #, но мы не знаем, как это сделать. на самом деле сделать это! (поэтому этот вопрос).

Docs / подробности?


Я задал дополнительный вопрос о переполнении стека: как создать процедуру Python CLR в SQL Server?


Вопрос под вопросом : у вас есть кусок питона. Вы хотите, чтобы он запускался из триггера SQL, но вы знаете, что это очень плохо. Итак, что вы делаете для достижения того же эффекта, не имея кода Python в середине операции SQL?

Что такое не запускающий, не опрашивающий подход к решению этой проблемы?

(Тот же самый эффект = «вставка / обновление / удаление происходит в таблице, и сценарий python запускается в течение 2 секунд после события db без опроса таблицы»)

Jonesome Восстановить Монику
источник
Вы меняете вопрос пять лет спустя? Полный конфликтов. Опрос таблицы не соответствует вашим бизнес-потребностям, потому что py должен запускаться немедленно, но в обновлении вы говорите, что 2-секундная задержка приемлема? Смешение. Если допустима 2-секундная задержка, я думаю, что это опрос таблицы.
Аарон Бертран
1
@AaronBertrand Я согласен, что этот вопрос не соответствует общепринятому взгляду на реальность. Но если мы возьмем момент и предположим, что спрашивающий умен и искренен в своем стремлении к квесту «не фактический триггер, но действует как подобный триггеру», мы (как сообщество SE) можем помочь найти способ fwd (или отклонить вопрос, который фактически не устраняет необходимость / проблему). FWIW.
Jonesome Восстановить Монику
Это нормально, но вы должны выбрать, какую проблему решить, а затем исправить вопрос (или, возможно, начать новый, если ответ, который вы получили 5 лет назад, был приемлемым тогда, но больше не приемлем сегодня, будь то потому, что ваши требования с тех пор изменились ). В настоящее время вы говорите, что не хотите опроса или триггера, а также говорите, что он должен быть немедленным, и задержка в 2 секунды вполне подойдет.
Аарон Бертран
Теперь это сценарий, в котором NoSQL не пригодится в отличие от СУБД, поскольку СУБД может управлять триггерами и вносить вклад в качестве прикладного уровня (больше, чем хранилище данных)
overexchange
@samsmith Вы прошли этот ответ?
сверхобмена

Ответы:

12

Не заставляйте пользовательскую транзакцию ждать (надеюсь!) Успешного завершения скрипта Python. Вся ваша транзакция находится там и ожидает запуска этого внешнего процесса, попытки отправки почты и т. Д. Я сомневаюсь, что электронная почта действительно должна выходить в этот момент - особенно если учесть, что вы не можете контролировать любые задержки, которые возникают при маршрутизации. в любом случае в почтовый ящик получателя. Почему бы просто не запускать процесс чаще, если время так важно?

Пожалуйста, дайте этот совет для просмотра .

Если вы действительно, действительно, действительно хотите сделать это неправильно, вы можете просто включить xp_cmdshellи запустить.

EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE WITH OVERRIDE;
GO
EXEC sp_configure 'xp_cmdshell', 1;
GO
RECONFIGURE WITH OVERRIDE;
GO

Теперь, предполагая, что пользователь имеет доступ xp_cmdshellи / или учетная запись службы SQL Server может видеть папку, в которой хранится скрипт python, вы сможете сделать это из своего триггера:

EXEC master..xp_cmdshell N'C:\Python27\python.exe C:\source\NotifyAgents.py';

Как и в сторону, вы должны указать в своем вопросе , что Вы знаете , что это очень плохо ТМ , но вы не обеспокоены тем , что, по какой - либо причине. Я все еще не думаю, что вы получите такое же реальное время, как ожидаете, даже если вы сделаете это с триггера. Вы рассматривали почту базы данных вместо python?

Аарон Бертран
источник
Аарон, все ваши очки верны, но это моя проблема. Я хочу запустить Python из триггера, и у меня нет проблем с проблемами. (У меня может быть триггер на реальной таблице, помещающий значение в таблицу "заданий", и триггер на таблице "заданий", запускающий python ...)
Jonesome Reinstate Monica
4
Кроме того, ваш триггер -> другая таблица -> другая идея триггера все еще страдает от той же проблемы, только теперь она хуже. Исходная транзакция все еще должна ждать завершения всей этой каскадной операции.
Аарон Бертран
хороший вызов RE каскадный вопрос. Не пойду туда!
Jonesome Восстановить Монику
ОП улучшил, чтобы
перефразировать
2

msgstr "вставка / обновление / удаление происходит в таблице, и скрипт Python запускается в течение 2 секунд после события db,

Прежде всего, если вы используете триггер для записи сообщения в таблицу, предназначенную для этой цели, вы можете непрерывно запускать процесс объединения с ожиданием в 1 секунду или даже меньше. Ключ заключается в том, чтобы сделать запрос опроса достаточно дешевым (<1 мс) и не мешать никаким другим транзакциям (таким образом, выделенной «таблице очередей»).

Например, ваш процесс опроса запускает партию следующим образом:

declare @TriesRemaining int = 25
while not exists (select * from queue_table)
begin
  if @TriesRemaining <= 0
    break;
  set @TriesRemaining -= 1
  waitfor delay '0:0:1'
end
delete top (1)  
from queue_table
output deleted.*

Чтобы подождать до 25 секунд, пока в таблице не появится строка, опрашивающая каждую секунду. По таймауту он просто возвращает пустой набор результатов.

без опроса таблицы

В таком случае проще всего использовать компонент Service Broker вместе с внутренней процедурой активации, которая вызывает Python через xp_cmdshell, или внешним процессом, который зацикливается на блокировке RECEIVE в очереди целевого компонента Service Broker. Так работает Database Mail под капотом.

Дэвид Браун - Microsoft
источник
Есть хорошая подробная статья о настройке сервисного брокера .
Мустаччо
2

Чтобы минимизировать влияние синхронного запуска скрипта Python из вашего триггера, вы можете заключить код Python в BaseHTTPServer:

import BaseHTTPServer

class MyHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_POST(self):
        print "Serving %s" % self.path
        # Your code here
        self.send_response(200, "OK")

def run(server_class=BaseHTTPServer.HTTPServer,
        handler_class=MyHTTPHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever()

if __name__ == "__main__":
    run()

Затем вы можете отправить HTTP-запрос от вашего триггера к демону, описанному выше, как показано, например, в этом разделе вопросов и ответов . Обработчик запросов может даже создать отдельный поток для асинхронного выполнения вашей логики Python.

mustaccio
источник
Хороший ответ!!! Большинство приложений mgr середины 90-х (которые я работал) опрашивали базу данных с интервалом опроса.
переиздание