【问题标题】:Getting broken pipe when passing mysql connection to a python thread将mysql连接传递给python线程时管道损坏
【发布时间】:2016-01-18 15:29:57
【问题描述】:

我正在尝试将 mysql 连接传递给 python 中的线程。 如果我在worker类中初始化mysql,就没有错误。

但是,连接的成本可能很高,所以我尝试只从调用函数传递 mysql 连接(参见下面的代码)。但这一直抛出这个错误:

(2006, "MySQL 服务器已消失 (BrokenPipeError(32, 'Broken 管道'))

知道为什么吗?我认为是因为我们通过mysql连接的方式

def worker(db):
""" Distributes the workload for a thread
"""
while True:
    item = queue_handler.get()
    perform_insert(item, db)
    queue_handler.task_done()

def insert_bulk(params):
""" Handles the insert
"""
    cntr = 0
    res = []
    cannot_read = []
    (data, cms, report_id) = params

    db = nmi_mysql.DB(CONFIG['earnings_db'], True)

    for i in range(10):
        thrd = threading.Thread(target=worker, args=(db,))
        thrd.deamon = True
        thrd.start()

    for row in data:
        split_files = row.split(',')

        if len(split_files) != 34:
            cannot_read.append(split_files)
            continue

        now = datetime.datetime.now()

        res.append(<some data to insert>)

        if len(res) == 750 or cntr == len(data):
            queue_handler.put([res, cms, report_id])
            res = []

        cntr += 1

    queue_handler.join()

    db.close()

    return [len(res), cms]

更新

我们没有传递 mysql 连接,而是创建了一个连接池并在线程中使用该池。这样,我们只需在线程级别从池中获取连接。

【问题讨论】:

  • 通常情况下,不同客户端线程之间不能使用数据库连接:它们不是线程安全的。如果没有人为您提供更好的答案,我建议您将每个连接处理到同一个线程中:打开、使用和关闭。
  • @LittleSanti 我们使用了连接池。效果很好。
  • 在同一个线程中完全处理每个连接时,可以使用池:获取连接、使用连接、释放连接。原因还是一样:连接通常不是线程安全的。

标签: python mysql multithreading pymysql broken-pipe


【解决方案1】:

数据库连接不是线程安全的,因此您不应将它们从一个线程传递到另一个线程。连接池保留请求之间的打开连接,因此从池中获取连接、将其用于查询然后释放它会更快。

这个related answer 有一些关于数据库连接线程安全的有用链接。

【讨论】:

  • 我的回答主要是对cmets的总结。我刚刚发布了它,所以这个问题将从未回答的问题列表中删除。
猜你喜欢
  • 2011-05-16
  • 2016-07-04
  • 1970-01-01
  • 1970-01-01
  • 2018-06-05
  • 2012-08-13
  • 2013-10-10
  • 2020-12-14
  • 1970-01-01
相关资源
最近更新 更多