【问题标题】:Getting different results with mysql when using python multiprocessing使用 python 多处理时使用 mysql 获得不同的结果
【发布时间】:2012-02-20 05:51:05
【问题描述】:

我无法弄清楚我做错了什么(或如何纠正它)。显示一些代码可能更容易(它比我正在做的有点简化,但它证明了我的观点):

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 个条目(这是正确的),但是如果您在 for 循环中注释掉 build_table(i,x) 并取消注释 pool.apply_async(build_table, (i, x)) 它只会创建 52 条记录。为什么在多处理相同的功能时会有区别,我能做些什么来修复它,所以结果是一样的(我认为快速提交更新会修复它,但没有运气)?

如果我玩 pool = Pool(processes=4) 并将其更改为 1,它可以工作,但我想那是预期的,因为那时它并不是真正的多处理。另外,如果有帮助,我正在使用 InnoDB。

更新:当我更改为 MyISAM 时,我会更新 240 个结果(不是我需要的 250 个,但比 52 个要好得多)。

UPDATE2:mysql 命令被合并为一个命令,结果似乎有所不同。有时我在数据库中得到 248 个结果,有时是 240 个或更少。也许是多处理导致了预期结果和实际结果之间的差异?

【问题讨论】:

  • 我无法解开所有复杂的逻辑以及您实际尝试插入的值,但我猜交叉线程/进程会导致某些值被插入两次或根本不插入,从而影响其他流程的第 2 步和第 3 步。在一个进程的 1st Select 和 2nd Select 之间,另一个进程可以插入该值(第一个进程认为丢失)。在第二次选择和插入之间可能会发生类似的事情。
  • @ypercube 对复杂的逻辑感到抱歉。我花了 10 多个小时来解决这个问题,然后最后一个小时试图创建一个简化的示例,并且双嵌套 for 语句是我可以重新创建它的唯一方法。我以为您所说的正在发生,但我认为快速提交更改会解决它。
  • 表是 InnoDB 还是 MyISAM?您在哪个序列化级别运行?
  • 另一件事。我猜你真正的问题(不是简化的问题)是在表中插入更多的值(并且可能不止一列)。您能否提供有关该问题的详细信息?也许只需要几个插入就可以解决,不需要复杂。
  • pool计算的结果存储在一个临时数组中,然后写入数据库是不是不可行?

标签: python mysql multiprocessing


【解决方案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 个参数。

【讨论】:

  • 如果您在列value 上添加UNIQUE 约束,则可以删除NOT EXISTS ... 部分。
  • 谢谢。该代码不起作用,但我确实理解您的逻辑,而不是多个小命令,只需使用一个结合所有条件的超级 sql 语句。让我弄清楚如何做到这一点,我还将研究您在 cmets 中关于禁用自动提交的建议。
  • update..当我将其设置回 InnoDB 并运行您的代码时,我得到 167 个匹配项。我需要弄清楚如何禁用自动提交,也许这会让它变得更好。我会更新你,但def。取得了不错的进展。太奇怪了,我重新运行了代码,现在得到了 248 个匹配项。当我运行它然后浏览网络时,它会创建 240..hmm 结果似乎因 cpu 使用情况而异。
  • WHERE (COUNT(*)) = 1 很奇怪。你真的需要那个吗?检查背后的逻辑是什么(代码中的第一个 SELECT)?
  • 这只是一个例子,但基本上逻辑只是检查数据库中是否存在计算值。如果确实如此,则添加未来值(如果值尚不存在)。我的原始代码有一个字典,可以在字典中搜索值,如果该值不存在,则将其创建为 false,如果再次找到,则将其变为 true。所以如果 [s - c * x, i] 存在,则将 [s, i+1] 变为 True。如果它不存在,则将其变为 False(但如果再次找到,则使用该逻辑将其变为 true)。在 python 中,这是来自“defaultdict”命令。我试图重新创建它
猜你喜欢
  • 2016-07-10
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 2021-08-02
  • 2014-10-09
  • 1970-01-01
相关资源
最近更新 更多