首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用Python 3.6启动事务mysql-connector-python不返回任何结果

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

Stack Overflow用户
提问于 2018-07-06 17:20:37
回答 1查看 960关注 0票数 0

我使用的是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的脚本时(从同一台机器,相同的访问,等等):

代码语言:javascript
复制
  * SQL QRY: START TRANSACTION; SELECT * FROM test WHERE task_status != 1 LIMIT 1 FOR UPDATE;
  * SQL RES: No result set to fetch from.

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

代码语言:javascript
复制
  * SQL QRY: SELECT * FROM test WHERE task_status != 1 LIMIT 1;
  * SQL RES: [(1, 0, 'TASK0001')]

我知道SELECT *不是一个好办法,但现在只是想得到一些回应。

我正在尝试允许多个worker脚本执行一个任务,而不让worker执行相同的任务:

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

这是我第一次尝试锁定,所以这是一个新的领域。我能够做普通的查询和填充表等,所以我有一些经验,但不是锁定。

表创建:

代码语言:javascript
复制
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连接器可能需要正确设置,因为它是我在连接器上使用'autocommit=1‘,在游标上使用'buffered=True’的唯一非working.
  3. Currently组件。我知道您可以在“START TRANSACTION”之前在SQL中设置“autocommit=0”,因此对于锁定,我可能需要这样做,但对于所有其他事务,我更喜欢保持自动提交。这可以和/或可行吗?

代码:

代码语言:javascript
复制
#!/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))

非常感谢,

弗兰克

EN

回答 1

Stack Overflow用户

发布于 2018-07-07 04:05:28

因此,在尝试了一段时间后,我(通过反复试验)发现,正确的方法是将'FOR UPDATE‘放在正常查询的末尾:

完整代码如下(包括添加用于测试的虚拟记录的选项):

代码语言:javascript
复制
#!/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连接器和事务没有给我任何东西。

祝好运,

弗兰克

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51207066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档