当我使用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
答案 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?
有人分享一些观点吗?
感谢