当我使用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 访问数据库的此类问题?
有人分享一些要点吗?
谢谢
关于python - 使用multiprocessing访问mysql时,总是报如下错误,如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24406092/