python - 从 Python 多处理访问 MySQL 连接池

标签 python connection-pooling mysql-python

我正在尝试设置一个 MySQL 连接池,并让我的工作进程访问已建立的池,而不是每次都设置一个新连接。

我很困惑是否应该将数据库游标传递给每个进程,或者是否有其他方法可以做到这一点? MySql.connector 不应该自动进行池化吗?当我检查我的日志文件时,打开和关闭了很多很多连接……每个进程一个。

我的代码看起来像这样:

PATH = "/tmp"

class DB(object):
  def __init__(self):
    connected = False
    while not connected:
      try:
        cnxpool = mysql.connector.pooling.MySQLConnectionPool(pool_name = "pool1",
                                                          **config.dbconfig)
        self.__cnx = cnxpool.get_connection()
      except mysql.connector.errors.PoolError:
        print("Sleeping.. (Pool Error)")
        sleep(5)
      except mysql.connector.errors.DatabaseError:
        print("Sleeping.. (Database Error)")
        sleep(5)

    self.__cur = self.__cnx.cursor(cursor_class=MySQLCursorDict)

  def execute(self, query):
    return self.__cur.execute(query)

def isValidFile(self, name):
  return True

def readfile(self, fname):
  d = DB()
  d.execute("""INSERT INTO users (first_name) VALUES ('michael')""")

def main():
  queue = multiprocessing.Queue()
  pool = multiprocessing.Pool(None, init, [queue])
  for dirpath, dirnames, filenames in os.walk(PATH):

    full_path_fnames = map(lambda fn: os.path.join(dirpath, fn),
                           filenames)
    full_path_fnames = filter(is_valid_file, full_path_fnames)
    pool.map(readFile, full_path_fnames)

if __name__ == '__main__':
  sys.exit(main())

最佳答案

首先,您要为 DB 类的每个实例创建一个不同的连接池。具有相同名称的池不会使它们成为相同的池

来自documentation :

It is not an error for multiple pools to have the same name. An application that must distinguish pools by their pool_name property should create each pool with a distinct name.

除此之外,在不同进程之间共享数据库连接(或连接池)不是一个好主意(我非常怀疑它是否能正常工作),所以每个进程使用它自己的连接实际上是你应该追求的目标。

您可以在 init 初始化程序中将池初始化为全局变量,然后使用它。
非常简单的例子:

from multiprocessing import Pool
from mysql.connector.pooling import MySQLConnectionPool
from mysql.connector import connect
import os

pool = None

def init():
    global pool
    print("PID %d: initializing pool..." % os.getpid())
    pool = MySQLConnectionPool(...)

def do_work(q):
    con = pool.get_connection()
    print("PID %d: using connection %s" % (os.getpid(), con))
    c = con.cursor()
    c.execute(q)
    res = c.fetchall()
    con.close()
    return res

def main():
    p = Pool(initializer=init)
    for res in p.map(do_work, ['select * from test']*8):
        print(res)
    p.close()
    p.join()

if __name__ == '__main__':
    main()

或者只使用一个简单的连接而不是连接池,因为无论如何在每个进程中一次只有一个连接是事件的。
并发使用的连接数受 multiprocessing.Pool 大小的隐式限制。

关于python - 从 Python 多处理访问 MySQL 连接池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24374058/

相关文章:

java - 在Web应用程序中同时访问数据库

java - 在 java 命令行应用程序中创建连接池

python - pip 安装 MySQLdb 库时出错

centos - 在 CentOS 上安装没有 mysql-server 的 MySQL-python

java - 数据库连接池中的每个连接是否都由一个线程支持?

python - 如何使用python从用户时间线twitter检索/查找tweet上的特定文本

python - 如何向 Django 表单向导提供初始数据?

python - 仅对列表中的列表的字典值进行排序

java - 为什么动态类型语言是解释型语言,而静态类型语言是编译时语言?

python - 如何读取二进制文件并将数据转换为图像?