python - 使用multiprocessing访问mysql时,总是报如下错误,如何解决?

标签 python mysql multiprocessing

当我使用Python multiprocessing访问MySQL数据库时,总是报错:

OperationalError: (2006, 'MySQL server has gone away')

Lost connection to MySQL server during query

如果有人能向我解释一下,我将不胜感激。

这是我的代码:

class MetricSource:
  def __init__(self, task):
    self.task = task

  def get_next_task_time(self):
    try:
      task_id = self.task.id
      next_task = Task.objects.get(id=task_id)
      next_time = next_task.last_success_time
    except Task.DoesNotExist as e:
      print 'Find Exception: %d' % self.task.id

def access_queue(input_queue, output_queue):
  while True:
    try:
      metric_source = input_queue.get(timeout=0.5)
      metric_source.get_next_task_time()
      output_queue.put(metric_source)
    except Queue.Empty:
      print "Queue Empty Error"
      continue

class Command(BaseCommand):

  def handle(self, *args, **options):
    self.manager = multiprocessing.Manager()
    self.input_queue = self.manager.Queue()
    self.output_queue = self.manager.Queue()

    self.init_data()

    for i in range(PROCESS_NUM):
      Process(target=access_queue, args=(self.input_queue, self.output_queue)).start()

  def init_data(self):
    for i in range(200):
      try:
        task = Task.objects.get(id=i+1)
        self.input_queue.put(MetricSource(task))
      except Exception as e:
        print 'find task_id %d' % i
        continue
      except IOError as e:
        print "find IOError: %r" % e
        continue

而且我怀疑这是我的 MySQL 配置的问题,但我认为这不是问题所在。 这是我的.cnf:

[mysqld]
default-character-set=utf8
collation_server = utf8_general_ci
character_set_server = utf8
max_allowed_packet = 100M

datadir=/home/work/data1/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
slow_query_log
slow_query_log_file=/home/work/data1/mysql/mysql-slow.log
max_allowed_packet=100M

log-error=/home/work/data1/mysql/error.log
general_log
general_log_file=/home/work/data1/mysql/mysql.log

tmp_table_size=2G
max_heap_table_size=2G

wait_timeout=2880000
interactive_timeout=2880000
innodb_data_home_dir=/home/work/data1/mysql/ibdata/

[mysqld_safe]
default-character-set=utf8
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

最佳答案

我已经找到数据库连接崩溃的原因,在这里分享一些要点。

问题是由'init_data'和'fork subProcess'的顺序引起的:

self.init_data()

for i in range(PROCESS_NUM):
  Process(target=access_queue, args=(self.input_queue, self.output_queue)).start()

按照这个顺序,在执行init_data()时,已经建立了db连接,然后fork子进程,然后将连接复制到子进程中。所以所有的子进程实际上都在使用同一个连接,这肯定会导致一些不确定的问题。

当我将订单更改为:

for i in range(PROCESS_NUM):
  Process(target=access_queue, args=(self.input_queue, self.output_queue)).start()

self.init_data()

并为子进程添加休眠:

def access_queue(id, input_queue, output_queue):
  time.sleep(5)
  while True:
    ...

它有效。因为在此更改下,子进程将在连接建立之前构造,然后子进程将使用它们单独的连接到数据库。

所以我有一个问题:

是否有任何优雅的解决方案来解决/防止多处理中通过 orm 访问数据库的此类问题?

有人分享一些要点吗?

谢谢

已找到好帖子:Django multiprocessing and database connections

关于python - 使用multiprocessing访问mysql时,总是报如下错误,如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24406092/

相关文章:

Python 多处理池 OSError : Too many files open

python - 在 Python 2.7 中,在 5 个不同的线程中调用函数并并行执行

python_pygame - 文件未找到错误 : No such file or directory

python - 将元素汇总到某个索引并覆盖该值

python - 如何在 google Bigquery 中使用加载作业时创建日期分区表?

mysql - 在mysql中更改时间戳

mysql - 计算mysql中两个时间戳的时间差

linux - 如何增加子进程数量

python - 使用python调整两个字符串之间的1个空格

php - 从 Magento 销售 > 订单中删除已删除的订单