当使用多处理来访问MySQL时,它总是抛出以下错误,如何解决?

时间:2014-06-25 10:23:00

标签: python mysql multiprocessing

当我使用Python多处理来访问MySQL数据库时,总是得到错误:

  

操作错误:(2006年,“MySQL服务器已经消失”)

     

查询期间与MySQL服务器的连接丢失

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

这是我的代码:

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配置问题,但我认为这不是问题。 这是my.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

1 个答案:

答案 0 :(得分:2)

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

问题是由'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()

并为子进程添加sleep:

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

它有效。因为在此更改下,将在构建连接之前构造subProcesses,然后subProcesses将使用它们与db的单独连接。

所以我有一个问题:

是否有任何优雅的解决方案可以解决/防止多处理中的这类问题,以便通过orm访问db?

有人分享一些观点吗?

感谢

找到了一篇好文章:Django multiprocessing and database connections