挿入トリガーからPythonスクリプトを起動する


10

いくつかの電子メールを送信し、クラウドシステムとやり取りするPythonの素晴らしい部分があります。正常に動作します。しかし、dbをポーリングするには、数分ごとに実行する必要があります。ビジネス目的では、Pythonスクリプトをリアルタイムで実行する必要があるため、ポーリングの遅延はありません。(これは、顧客と電話で連絡している営業担当者に提供されます。)

実際には1分のポーリングループは必要ありません。または30秒。レコードをdbに表示して、すぐに何かが起こるようにしたいと思っています。

このフライをすばやく作成するには、特定のレコードタイプがテーブルに挿入されたときにこれを起動します。

トリガーからPythonスクリプトを起動できますか?

以下のAaronのメモによれば、これはVery Bad Thing™であることがわかりますが、このテーブルはほとんど使用されません(1日に0〜12挿入)。テーブルをポーリングしても、ビジネスニーズを満たすことができません(.pyをすぐに実行する必要があります-電子メールを送信するだけではありません)。

私たちのビジネスニーズを満たす方法は、SQL Serverに.netバージョンのpythonをセットアップし、T-SQLがC#のものを呼び出す方法でpythonスクリプトを呼び出すようにすることです... しかし、私たちは方法がわかりません実際にこれを行う!(この質問に答えてください)。

ドキュメント/詳細?


Stack Overflowでフォローアップの質問をしました:SQL ServerでPython CLRプロシージャを作成するにはどうすればよいですか?


質問の下の質問:あなたはPythonの断片を持っています。SQLトリガーから起動したいのですが、それは非常に悪いことです。では、SQL操作の途中でPythonコードを使用せずに同じ効果を実際に達成するにはどうすればよいでしょうか。

このニーズを解決するための非トリガー、非ポーリングのアプローチは何ですか?

(同じ効果=「テーブルで挿入/更新/削除が行われ、テーブルをポーリングせずに、dbイベントの2秒以内にPythonスクリプトがトリガーされます」)


あなたは5年後に問題を変えていますか?紛争がいっぱい。pyはすぐに実行する必要があるため、テーブルをポーリングしてもビジネスニーズを満たしませんが、更新では2秒の遅延は許容できると言いますか?混乱しています。2秒の遅延が許容範囲内であれば、テーブルをポーリングしていると思います。
アーロンバートランド

1
@AaronBertrand私はこの質問が現実のすべての人の見解に適合しないことに同意します。しかし、少し時間を取って、質問者がインテリジェントではなく、実際のトリガーではないが実際のトリガーのようなクエストを必要としていると仮定すると、(SEコミュニティとして)私たちは方法を見つけるのを助けることができますfwd(または、質問を却下します。実際には、必要性/問題はなくなりません)。fwiw。
Jonesome Reinstate Monica、2018

それは問題ありませんが、どの問題を解決するかを選択し、質問を修正する必要があります(または、5年前に得られた回答が当時は受け入れられたが、今日は受け入れられなくなった場合、要件が変更されたためかどうかにかかわらず、新しい問題を開始する可能性があります) )。現在、あなたはポーリングトリガーをしたくないと言っています。また、それは即時ある必要があり、2秒の遅延で問題ないと述べています。
アーロンバートランド

DBMSは、トリガを管理し、アプリケーション層(データ記憶装置よりも)として寄与することができるので、今、これは、NoSQLのは便利とは異なり、DBMSを来ていないシナリオ、である
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';

余談ですが、これは非常に悪いTMであることを認識していることを質問に記載する必要がありますが、何らかの理由でそれを気にする必要はありません。トリガーから発射したとしても、期待どおりのリアルタイムが得られるとはまだ思いません。Pythonではなくデータベースメールを検討しましたか?


アーロン、あなたのポイントはすべて有効ですが、それが私の問題です。トリガーからPythonを起動したいのですが、問題はありません。(実際のテーブルのトリガーで「ジョブ」テーブルに値をプッシュし、「ジョブ」テーブルのトリガーでPythonを実行することができます...)
Jonesome Reinstate Monica

4
また、あなたのトリガー->他のテーブル->他のトリガーのアイデアは同じ問題に苦しんでいますが、今はもっと悪いです。元のトランザクションは、そのすべてのカスケードアクティビティが完了するまで待機する必要があります。
アーロンバートランド

問題を重ねたREを呼び出します。そこに行かない!
Jonesome Reinstate Monica

OPが強化され、質問を再構成する
Jonesome Reinstate Monica

2

「挿入/更新/削除はテーブルで行われ、Pythonスクリプトがdbイベントの2秒以内にトリガーされます。

まず、トリガーを使用してこの目的専用のテーブルにメッセージを書き込む場合、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を、xp_cmdshellを介してPythonを呼び出す内部アクティブ化プロシージャ、またはターゲットService BrokerキューのブロッキングRECEIVEでループする外部プロセスと一緒に使用することです。これは、データベースメールが内部で機能する方法です。



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()

次に、このSO Q&Aに示すように、トリガーから上記のデーモンにHTTPリクエストを送信できます。リクエストハンドラは、Pythonロジックを非同期で実行するために別のスレッドを生成することもできます。


いい答えだ!!!90年代中頃のmgrアプリケーションのほとんど(私が作業していた)は、ポーリング間隔でデータベースをポーリングしていました。
オーバーエクスチェンジ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.