我有一个名为“unprocessed”的表,我想读取2000行,通过HTTP将它们发送到另一台服务器,然后将这些行插入“已处理”表并从“未处理”表中删除它们。
我的python代码大致如下:
db = MySQLdb.connect("localhost","username","password","database" )
# prepare a cursor object using cursor() method
cursor = db.cursor()
# Select all the records not yet sent
sql = "SELECT * from unprocessed where SupplierIDToUse = 'supplier1' limit 0, 2000"
cursor.execute(sql)
results = cursor.fetchall()
for row in results:
id = row[0]
<code is here here for sending to other server - it takes about 1/2 a second>
if sentcorrectly="1":
sql = "INSERT into processed (id, dateprocessed) VALUES ('%s', NOW()')" % (id)
try:
inserted = cursor.execute(sql)
except:
print "Failed to insert"
if inserted:
print "Inserted"
sql = "DELETE from unprocessed where id = '%s'" % (id)
try:
deleted = cursor.execute(sql)
except:
print "Failed to delete id from the unprocessed table, even though it was saved in the processed table."
db.close()
sys.exit(0)
我希望能够同时运行此代码,以便我可以提高通过HTTP将这些记录发送到其他服务器的速度。 目前,如果我尝试同时运行代码,我会获得在其他服务器上发送的相同数据的多个副本,并保存到“已处理”表中,因为select查询在代码的多个实例中获得相同的id。 / p>
如何在选择记录时锁定记录,然后在将每个记录移动到“已处理”表之前将其作为一行处理? 该表是MyISAM,但我今天已经转换为innoDB,因为我意识到有可能通过innoDB更好地锁定记录。
答案 0 :(得分:1)
根据您的评论回复。
两个解决方案中的一个是客户端python主进程,用于收集所有2000条记录的记录ID,然后将其拆分成块以供子工作者处理。
简短版本,您的选择是委托工作或依赖可能棘手的资产锁定机制。我建议使用前一种方法,因为它可以借助消息队列进行扩展。
委托逻辑将使用multiprocessing
import multiprocessing
records = get_all_unprocessed_ids()
pool = multiprocessing.Pool(5) #create 5 workers
pool.map(process_records, records)
这将创建2000个任务并一次运行5个任务,或者您可以使用此处概述的解决方案将记录拆分为块 How do you split a list into evenly sized chunks?
pool.map(process_records, chunks(records, 100))
将创建20个100个记录的列表,这些记录将分批处理5个
编辑: 语法错误 - 签名是map(func,iterable [,chunksize]),我省略了func的参数。