使用Python 3.6开始交易mysql-connector-python不返回任何结果

时间:2018-07-06 09:20:37

标签: mysql python-3.x transactions mysql-connector-python

我正在使用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 *不是要走的路,而只是想暂时获得一些回应。

我正在尝试允许多个工作脚本执行一项任务,而这些工作人员不会执行同一任务:

  1. 执行选择和行锁定任务,以便其他工作人员的“ SELECT”查询不显示它们,
  2. 将任务状态设置为“正在处理”并解锁记录。

这是我第一次尝试锁定,因此这是新的领域。我能够进行常规查询并填充表等,因此有一定的经验,但没有锁定的经验。

创建表格:

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

问题:

  1. 这是正确的心态吗?即还有更多的pythonic / mysql方法可以做到这一点吗?

  2. 我是否需要启动mysql连接的特定方法?为什么使用MySQL工作台而不是通过脚本工作?我已经尝试过使用直接mysql,它也可以工作-因此,我认为可能是需要正确设置的python连接器,因为它是唯一无法正常工作的组件。

  3. 当前,我在连接器上使用“ 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))

非常感谢,

坦率

1 个答案:

答案 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和事务对我没有任何帮助。

祝你好运

坦率