首页 > 解决方案 > 与其余代码并行监控数据库和 ssh 连接

问题描述

我正在运行一个 python 脚本,即从 sql 服务器获取数据。查询运行很长时间,有时脚本会中断,因为 db 或 ssh 连接丢失。在这种情况下,脚本将冻结,因为它正在等待一个永远不会出现的结果。

如果数据库连接仍然可用,是否有持续监控的策略,而脚本的其余部分正在做其他事情(比如等待查询结果)?

我什至如何解决这个问题,因为监控过程必须与脚本的其余部分分离。

我知道,这是一个非常广泛的问题,可能没有绝对的答案,但我希望对我能读懂的一般方法提出一些建议。

标签: pythonpython-3.x

解决方案


您可以通过将长时间运行的代码放在一个单独的线程中来做到这一点,然后不要使用thread.join()它来检测线程何时完成,而是定期轮询以查看线程是否已完成并查看连接是否仍然良好。thread.exit()如果您发现连接不良并且需要提前退出,则可以使用该功能。

对于 MySQL 函数,我不打算这样做,但您可能必须为您使用的任何数据库更改它。我的计算机没有设置为能够轻松连接到 Python 中的数据库,所以我没有测试任何代码,所以其中可能存在一些错误,但这应该让您大致了解如何做在执行查询时监视数据库连接。

import threading
import MySQLdb

conn = MySQLdb.connect("localhost","testuser","test123","testdb" )

class DB_Query(threading.Thread):
    ''' Used by the run_query function to run a query in a separate thread '''
     def __init__(self, conn, query, dictionary_to_store_results):
         super(DB_Query, self).__init__()
         dictionary_to_store_results['finished'] = false
         self.conn = conn
         self.query = query
         self.result = dictionary_to_store_results

     def run(self):
         cursor = self.conn.cursor()
         try:
             cursor.execute(self.query)
         except SystemExit:
             cleanup_after_unexpected_broken_connection()
             raise
         self.result['data'] = cursor.fetchall()
         self.result['finished'] = true

    def cleanup_after_unexpected_broken_connection():
        # add cleanup code here
        pass

def check_connection_good(conn):
    # check if the connection is good here
    return True

def run_query(query):
    ''' Runs a query, while periodically checking to make sure the connection stays active throughout the process '''
    global conn
    query_result = {} # the thread will populate this dictionary with the results of executing the query
    thread = DB_Query(conn, query, query_result)
    thread.start()
    while(true):
        # check once every half second for the next 5 seconds if the thread is still running
        for i in range(5):
            time.sleep(.5)
            if not thread.is_alive():
                break
        # throw a systemExit error in the thread if the connection is broken
        if not check_connection_good(conn):
            thread.exit()
    return query_result['data']

if __name__ == "__main__":
    run_query('select * from some_table')

推荐阅读