我正在使用Python 3.6,mysql-connector-python 8.0.11和8.0.11 MySQL Community Server-GPL。有问题的表正在使用innoDB引擎。
在使用MySQL Workbench时,我可以输入:
USE测试;开始交易; SELECT * FROM task where 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 *不是要走的路,而只是想暂时获得一些回应。
我正在尝试允许多个工作脚本执行一项任务,而这些工作人员不会执行同一任务:
这是我第一次尝试锁定,因此这是新的领域。我能够进行常规查询并填充表等,因此有一定的经验,但没有锁定的经验。
创建表格:
create table test
(
id int auto_increment
primary key,
task_status int not null,
task_ref varchar(16) not null
);
问题:
这是正确的心态吗?即还有更多的pythonic / mysql方法可以做到这一点吗?
我是否需要启动mysql连接的特定方法?为什么使用MySQL工作台而不是通过脚本工作?我已经尝试过使用直接mysql,它也可以工作-因此,我认为可能是需要正确设置的python连接器,因为它是唯一无法正常工作的组件。
当前,我在连接器上使用“ autocommit = 1”,并在光标上使用“ buffered = True”。我知道您可以在“ START TRANSACTION”之前在SQL中设置“ autocommit = 0”,因此了解锁定可能需要这样做,但是对于所有其他事务,我希望保持自动提交。这样可以解决吗?
代码:
#!/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))
非常感谢,
坦率
答案 0 :(得分:0)
因此,经过反复试验,我(通过反复试验)得出结论,执行此操作的正确方法是将“ 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-connector和事务对我没有任何帮助。
祝你好运
坦率