Получение различных результатов при использовании 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.