Получение различных результатов при использовании mysql при использовании многопроцессорности python

Я не могу понять, что я делаю неправильно (или как его исправить). Возможно, было бы проще показать какой-то код (его немного упростить от того, что я делаю, но это доказывает мою мысль):

from multiprocessing import Pool
import MySQLdb
import sys

#sql connection
try:
 conn = MySQLdb.connect (host = "127.0.0.1",user = "user",passwd = "password", db = "mydb")
except MySQLdb.Error, e:
 print "Error %d: %s" % (e.args[0], e.args[1])
 sys.exit (1)

#with database
cursor = conn.cursor ()
cursor.execute ("DROP TABLE IF EXISTS data_table")
cursor.execute ("""
 CREATE TABLE data_table(
 value CHAR(80)
 ) ENGINE=MyISAM 
""")

cursor.execute (""" INSERT INTO data_table (value) VALUES ('%s')""" % [0, 0]) #need to insert basecase
conn.commit()


def build_table(i,x): # i is index, x is data[i]
 conn = MySQLdb.connect (host = "127.0.0.1",user = "user",passwd = "password", db = "mydb")
 cursor = conn.cursor ()
 #print i,x
 target_sum = 100
 for s in range(target_sum + 1): 
 for c in range(target_sum + 1): 
 #print c, i
 cursor.execute ("""
INSERT INTO data_table (value) 
 SELECT '%s'
 FROM dual
 WHERE ( SELECT COUNT(*) FROM data_table WHERE value='%s' )
 = 1
 AND NOT EXISTS
 ( SELECT * FROM data_table WHERE value='%s' )
 """ % ([s, i+1], [s - c * x, i], [s, i+1]))
 conn.commit()

 conn.close()

data = [2,5,8]
pool = Pool(processes=4)
for i, x in enumerate(data): 
 build_table(i,x) #creates 250 records
 #pool.apply_async(build_table, (i, x))
pool.close()
pool.join()

print 'completed'

Он в основном создает таблицу в mysql. В приведенном выше коде создается 250 записей (это правильно), но если вы закомментируете build_table(i,x) в цикле for и pool.apply_async(build_table, (i, x)) он создает только 52 записи. Почему существует разница при многопроцессорности одной и той же функции и есть ли что-нибудь, что я могу сделать, чтобы исправить это, чтобы результаты были одинаковыми (я думал, что быстро фиксация обновлений исправит его, но не повезет)?

Если я играю вокруг pool = Pool(processes=4) и меняю его на 1, он работает, но я предполагаю, что это ожидалось, потому что его не многопроцессорность действительно в этот момент. Кроме того, если это помогает, я использую InnoDB.

ОБНОВЛЕНИЕ: когда я перехожу на MyISAM, я получаю 240 обновляемых результатов (не совсем 250, мне нужно, но намного лучше, чем 52).

UPDATE2: команда mysql была объединена в одну команду, и результаты, похоже, различаются. Иногда я получаю 248 результатов в базе данных, иногда 240 или меньше. Может быть, многопроцессорность приводит к расхождению между ожидаемыми и фактическими результатами?

1 ответ

Я попытался бы объединить 2 Selects и Insert в один оператор Insert:

#print c, i
cursor.execute(""" SELECT value FROM data_table WHERE value='%s' """ % ([s - c * x, i]))
if cursor.rowcount == 1:
 cursor.execute(""" SELECT value FROM data_table WHERE value='%s' """ % [s, i+1])
 if cursor.rowcount == 0:
 cursor.execute (""" INSERT INTO data_table (value) VALUES ('%s')""" % [s, i+1])

В чем-то вроде:

#print c, i
cursor.execute ("""
 INSERT INTO data_table (value) 
 SELECT '%s'
 FROM dual
 WHERE ( SELECT COUNT(*) FROM data_table WHERE value='%s' )
 = 1
 AND NOT EXISTS
 ( SELECT * FROM data_table WHERE value='%s' )
 """ % ([s, i+1], [s - c * x, i], [s, i+1]))

Не уверен в синтаксисе в последней строке. Вам нужно будет передать 3 параметра.

licensed under cc by-sa 3.0 with attribution.