使用Python 3.6启动事务mysql-connector-python不返回任何结果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python 3.6启动事务mysql-connector-python不返回任何结果相关的知识,希望对你有一定的参考价值。

我正在使用Python 3.6,mysql-connector-python 8.0.11和8.0.11 MySQL社区服务器 - GPL。有问题的表使用了innoDB引擎。

使用MySQL Workbench时我可以输入:

使用测试;开始交易; 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.

这是我脚本的调试输出。如果我将Query更改为普通SELECT,我会得到输出。

  * SQL QRY: SELECT * FROM test WHERE task_status != 1 LIMIT 1;
  * SQL RES: [(1, 0, 'TASK0001')]

我知道SELECT *不是要走的路,而是试着现在就做一些回应。

我正在尝试允许多个工作者脚本在没有工作人员执行相同任务的情况下接收任务:

  1. 执行select和row锁定任务,以便其他工作人员的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))

非常感谢,

坦率

答案

所以在玩了一下后,我(通过反复试验)得出正确的方法是在正常查询结束时加上'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和交易没有得到任何东西。

祝好运,

坦率

以上是关于使用Python 3.6启动事务mysql-connector-python不返回任何结果的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 virtualenv 在 Amazon 的 Elastic Beanstalk 上使用最新版本的 python (3.6)

Mule 3.3 spring 3.1 hibernate 3.6 事务管理

将 mod_wsgi 从 python3.5 更改为 3.6

在 slim python 3.6 docker 映像上运行 python mysql 客户端

python2.6 2.7 升级成3.6之后yum

Python3 - '超过锁定等待超时;尝试重新启动事务'并且只在数据库上处理