我使用的是Python3.6、MySQL -connector-python8.0.11和8.0.11 MySQL Community Server - GPL。有问题的表正在使用innoDB引擎。
使用MySQL工作台时,我可以输入:
使用测试;启动事务;SELECT * FROM tasks WHERE task_status != 1 LIMIT 1 FOR UPDATE;
并且它提供了预期的1条记录:
当我使用使用python3的脚本时(从同一台机器,相同的访问,等等):
* SQL QRY: START TRANSACTION; SELECT * FROM test WHERE task_status != 1 LIMIT 1 FOR UPDATE;
* SQL RES: No result set to fetch from.
这是我的脚本的调试输出。如果我将查询更改为普通SELECT,我确实会得到输出。
* SQL QRY: SELECT * FROM test WHERE task_status != 1 LIMIT 1;
* SQL RES: [(1, 0, 'TASK0001')]
我知道SELECT *不是一个好办法,但现在只是想得到一些回应。
我正在尝试允许多个worker脚本执行一个任务,而不让worker执行相同的任务:
这是我第一次尝试锁定,所以这是一个新的领域。我能够做普通的查询和填充表等,所以我有一些经验,但不是锁定。
表创建:
create table test
(
id int auto_increment
primary key,
task_status int not null,
task_ref varchar(16) not null
);
问题:
代码:
#!/usr/bin/env python
import mysql.connector
import pprint
conn = mysql.connector.connect(user='testuser',
password='testpass',
host='127.0.0.1',
database='test_db',
autocommit=True)
dbc = conn.cursor(buffered=True)
qry = "START TRANSACTION; SELECT * FROM 'test' WHERE task_status != 1 LIMIT 1 ON UPDATE;"
sql_select = dbc.execute(qry)
try:
output = dbc.fetchall()
except mysql.connector.Error as e:
print(" * SQL QRY: {0}".format(qry))
print(" * SQL RES: {0}".format(e))
exit()
else:
print(" * SQL QRY: {0}".format(qry))
print(" * SQL RES: {0}".format(output))
非常感谢,
弗兰克
发布于 2018-07-07 04:05:28
因此,在尝试了一段时间后,我(通过反复试验)发现,正确的方法是将'FOR UPDATE‘放在正常查询的末尾:
完整代码如下(包括添加用于测试的虚拟记录的选项):
#!/usr/bin/env python
import mysql.connector
import pprint
import os
conn = mysql.connector.connect(user='testuser',
password='testpass',
host='127.0.0.1',
database='test_db',
autocommit=True)
dbc = conn.cursor(buffered=True)
worker_pid = os.getpid()
all_done = False
create = False
if create:
items = []
for i in range(10000):
items.append([0, 'TASK%04d' % i])
dbc.executemany('INSERT INTO test (task_status, task_ref) VALUES (%s, %s)', tuple(items))
conn.commit()
conn.close
exit()
while all_done is False:
print(all_done)
qry = (
"SELECT id FROM test WHERE task_status != 1 LIMIT 1 FOR UPDATE;"
)
sql_select = dbc.execute(qry)
try:
output = dbc.fetchall()
except mysql.connector.Error as e:
print(" * SQL QRY: {0}".format(qry))
print(" * SQL RES: {0}".format(e))
exit()
else:
print(" * SQL QRY: {0}".format(qry))
print(" * SQL RES: {0}".format(output))
if len(output) == 0:
print("All Done = Yes")
all_done = True
continue
else:
print("Not Done yet!")
if len(output) > 0:
test_id = output[0][0]
print("WORKER {0} FOUND: '{1}'".format(worker_pid, test_id))
qry = "UPDATE test SET task_status = %s, task_ref = %s WHERE id = %s;"
sql_select = dbc.execute(qry, tuple([1, worker_pid, test_id]))
conn.commit()
try:
output = dbc.fetchall()
except mysql.connector.Error as e:
print(" * SQL QRY: {0}".format(qry))
print(" * SQL RES: {0}".format(e))
else:
print(" * SQL QRY: {0}".format(qry))
print(" * SQL RES: {0}".format(output))
print(all_done)
希望这能帮助其他人节省一些时间,因为有很多地方有不同的信息,但搜索python3,mysql连接器和事务没有给我任何东西。
祝好运,
弗兰克
https://stackoverflow.com/questions/51207066
复制相似问题