使用python3.6 mysql连接器启动事务python不返回任何结果

anhgbhbe  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(307)

我使用的是python3.6、mysql连接器python8.0.11和8.0.11mysql社区服务器-gpl。有问题的表正在使用innodb引擎。
使用mysql工作台时,我可以输入:
使用试验;启动交易;从任务状态!=1限1更新;
并按预期提供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.

这是我的脚本的调试输出。如果我将查询更改为normal select,我会得到输出。


* SQL QRY: SELECT * FROM test WHERE task_status != 1 LIMIT 1;

  * SQL RES: [(1, 0, 'TASK0001')]

我知道选择不是一个好办法,但现在只是想得到一些回应。
我正在尝试允许多个工作者脚本在工作者不执行相同任务的情况下执行一个任务:
对任务执行select并锁定行,这样其他worker的select查询就不会显示它们,
将任务状态设置为“正在处理”并解锁记录。
这是我第一次尝试锁定,所以这是一个新的领域。我能够做正常的查询和填充表等,所以有一些经验,但不锁定。
表创建:

create table test
(
  id          int auto_increment
   primary key,
  task_status int         not null,
  task_ref    varchar(16) not null
);

问题:
这是正确的心态吗?i、 e.有没有更具python/mysql风格的方法来实现这一点?
有没有一个具体的方法来启动mysql连接?为什么使用mysql工作台而不是通过脚本工作?我试过使用directmysql,这也很管用——所以我认为python连接器可能需要正确设置,因为它是唯一不起作用的组件。
目前我在连接器上使用'autocommit=1',在光标上使用'buffered=true'。我知道您可以在“启动事务”之前在sql中设置“autocommit=0”,因此对于锁定,我可能需要这样做,但对于所有其他事务,我更希望启用autocommit。这是否可行?
代码:


# !/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))

非常感谢,
直率的

kdfy810k

kdfy810k1#

因此,经过一番研究,我发现(通过反复试验)正确的方法是将“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连接器和事务没有得到任何东西。
祝你好运,
直率的

相关问题