Lanzar un script de Python desde un activador de inserción


10

Tenemos una buena pieza de Python que envía algunos correos electrónicos e interactúa con un sistema en la nube. Funciona bien. Pero tenemos que dispararlo cada pocos minutos para sondear la base de datos. Realmente necesitamos, para fines comerciales, que el script de Python se active en tiempo real, por lo que no hay demora en el sondeo. (Esto sirve a los vendedores que están hablando por teléfono con los clientes).

Realmente no queremos un bucle de sondeo de 1 minuto. O 30 segundos Queremos que el registro se muestre en la base de datos y que las cosas sucedan de inmediato.

La forma más rápida de hacer que esta mosca sea activada cuando se inserta un tipo de registro específico en una tabla.

¿Podemos disparar un script de Python desde un disparador?

Según la nota de Aaron a continuación, sabemos que esta es una cosa muy mala ™ , pero esta tabla tiene muy poco uso (0-12 inserciones al día). El sondeo de la tabla no cumple con nuestras necesidades comerciales (necesitamos que .py se ejecute de inmediato; hace mucho más que enviar un correo electrónico).

Creemos que una forma de satisfacer nuestras necesidades comerciales es configurar la versión .net de python en el SQL Server, y luego hacer que T-SQL llame al script de python de la manera en que llama cosas de C # ... pero no tenemos idea de cómo en realidad haz esto! (Ergo esta pregunta).

Documentos / detalles?


Hice una pregunta de seguimiento sobre Stack Overflow: ¿Cómo creo un procedimiento Python CLR en SQL Server?


La pregunta bajo la pregunta : Tienes una pieza de pitón. Desea que se active desde un disparador SQL, pero sabe que es una cosa muy mala. Entonces, ¿qué haces para lograr el mismo efecto sin tener código python en medio de una operación SQL?

¿Cuál es el enfoque sin disparador y sin sondeo para resolver esta necesidad?

(El mismo efecto = "insertar / actualizar / eliminar ocurre en una tabla y se activa un script de Python dentro de los 2 segundos posteriores al evento db, sin sondear la tabla")


¿Estás cambiando la pregunta cinco años después? Lleno de conflictos. Sondear la tabla no satisface las necesidades de su negocio porque el py necesita ejecutarse de inmediato, pero en la actualización dice que un retraso de 2 segundos es aceptable Confuso. Si un retraso de 2 segundos es aceptable, creo que también lo está haciendo la encuesta.
Aaron Bertrand

1
@AaronBertrand Estoy de acuerdo en que esta pregunta no se ajusta a la visión de la realidad de todos. Pero si nos tomamos un momento y asumimos que el interlocutor es inteligente y sincero en su necesidad de una búsqueda no real de disparador pero que actúa como un disparador, nosotros (como comunidad SE) podemos ayudar a encontrar una manera fwd (o descartar la pregunta, que en realidad no hace que la necesidad / problema desaparezca). fwiw
Jonesome Reinstate Monica el

Está bien, pero debe elegir qué problema resolver y luego solucionar la pregunta (o tal vez comenzar una nueva si la respuesta que recibió hace 5 años era aceptable, pero ya no lo es hoy, ya sea porque sus requisitos han cambiado desde entonces ) Actualmente dice que no desea sondeo o un activador, y también dice que debe ser inmediato y un retraso de 2 segundos está bien.
Aaron Bertrand

Ahora, este es un escenario, donde NoSQL no es útil a diferencia de DBMS, porque DBMS puede administrar los desencadenantes y contribuir como una capa de aplicación (más que un almacenamiento de datos)
intercambiar en exceso el

@samsmith ¿Revisaste esta respuesta?
intercambio excesivo el

Respuestas:


12

No haga que su transacción de usuario espere la finalización exitosa (¡con suerte!) Del script Python. Toda su transacción se queda allí y espera a que se ejecute este proceso externo, intente enviar correo, etc. Dudo que el correo electrónico realmente tenga que salir en ese instante, especialmente dado que no puede controlar los retrasos que tiene a medida que se enruta a la bandeja de entrada del destinatario de todos modos. ¿Por qué no simplemente ejecutar el proceso con más frecuencia, si el tiempo es tan importante?

Por favor, dale un vistazo a este consejo .

Si realmente quieres hacer esto de la manera incorrecta, puedes habilitarlo xp_cmdshelly disparar.

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

Ahora, suponiendo que el usuario tenga acceso xp_cmdshelly / o la cuenta de servicio de SQL Server pueda ver la carpeta donde está almacenado el script de Python, debería poder hacerlo desde su disparador:

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

Como comentario adicional, debe indicar en su pregunta que sabe que esto es algo muy malo TM , pero no le preocupa eso, por cualquier razón. Todavía no creo que vaya a tener el tiempo real que espera, incluso si dispara esto desde el gatillo. ¿Has considerado el correo de la base de datos en lugar de Python?


Aaron, todos tus puntos son válidos, pero ese es mi problema. Quiero disparar python desde un disparador, y no tengo ningún problema con los problemas. (Puedo hacer que el activador en la tabla real introduzca un valor en una tabla de "trabajo", y un activador en la tabla de "trabajo" ejecute python ...)
Jonesome Reinstate Monica el

44
Además, su desencadenante -> otra tabla -> otra idea de desencadenante todavía sufre el mismo problema, solo que ahora es peor. La transacción original todavía tiene que esperar a que se complete toda esa actividad en cascada.
Aaron Bertrand

buena llamada RE en cascada el problema. No iremos allí!
Jonesome Reinstate Monica

OP mejorado, para replantear la pregunta
Jonesome Reinstate Monica el

2

"insertar / actualizar / eliminar ocurre en una tabla y se activa un script de Python dentro de los 2 segundos posteriores al evento db,

En primer lugar, si usa un disparador para escribir un mensaje en una tabla dedicada para este propósito, puede ejecutar continuamente el proceso de agrupación con una espera de 1 segundo, o incluso menos. La clave es hacer que la consulta de sondeo sea lo suficientemente barata (<1 ms) y no interferir con ninguna otra transacción (por lo tanto, la "tabla de cola" dedicada).

Por ejemplo, haga que su proceso de votación ejecute un lote como este:

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.*

Para esperar hasta 25 segundos para que aparezca una fila en la tabla, sondear cada segundo. En el tiempo de espera, simplemente devuelve un conjunto de resultados vacío.

sin sondear la mesa

Lo más simple es utilizar Service Broker, junto con un Procedimiento de activación interna que invoca Python a través de xp_cmdshell, o un proceso externo que se repite en un RECEIVE de bloqueo en la cola del intermediario de servicios de destino. Así es como funciona el Correo electrónico de base de datos .



2

Para minimizar el impacto de ejecutar el script Python sincrónicamente desde su disparador, puede ajustar su código Python en 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()

Luego puede enviar una solicitud HTTP desde su disparador al demonio anterior, como se muestra, por ejemplo, en estas preguntas y respuestas sobre SO . El controlador de solicitudes puede incluso generar un hilo separado para ejecutar su lógica de Python de forma asincrónica.


¡¡¡Buena respuesta!!! La mayoría de las aplicaciones de mgr de mediados de los 90 (en las que trabajé) estaban sondeando la base de datos, con un intervalo de sondeo.
intercambio excesivo el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.