【问题标题】:Python MySQL not refreshingPython MySQL不刷新
【发布时间】:2019-02-22 03:11:41
【问题描述】:

我有两个程序:一个填充和更新数据库,另一个每 10 秒从数据库中选择一次信息。

我使用 Pymysql。

当我更新数据库我提交数据时,我可以用命令行在数据库中看到结果,但是另一个程序有相同的输出并且没有得到新的数据!

除了SELECT之外,我还需要进行特殊查询吗? 我需要在所有查询之前关闭连接并重新打开它吗?

我在启动程序时创建了GetData 类,并且每10 秒调用一次get_data

class GetData:
    def __init__(self):
        self.conn = pymysql.connect(host='localhost', user='root', password='', db='mydb', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)

    def get_data(self, data):
        with self.conn.cursor() as cursor:
            self.sql = "SELECT id_data, somedata FROM mytable WHERE (%s = 'example');"
            cursor.execute(self.sql, (data,))
        return cursor.fetchall()

    def close_conn(self):
        self.conn.close()

填充数据库的程序:

class FillDb:
    def __init__(self):
        self.conn = pymysql.connect(host='localhost', user='root', password='', db='mydb', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)
        #added this line but doesen't help!
        self.conn.autocommit(True)

    def add_in_db(self, data):
        with self.conn.cursor() as cursor:
            self.sql = "INSERT INTO mytable (somedata) VALUES (%s);"
            cursor.execute(self.sql, (data,))
            self.conn.commit()

【问题讨论】:

  • 如果没有看到一些有代表性的代码,我们无法回答这个问题。
  • 您不能参数化列名。我不确定self.sql = "SELECT id_data, somedata FROM mytable WHERE (%s = "example");" 会起作用
  • 还请向我们展示实例化您的类并调用其方法的代码。我和@roganjosh 在一起,您的 SELECT 查询看起来不对。如果example 应该是字符串文字,则它应该用单引号引起来,而不是在这种情况下用双引号引起来。此外,您似乎在调用fetchall 后通过退出上下文管理器已关闭的游标上调用execute;至少基于此处显示的缩进。我希望get_data 中的cursor.fetchall 会引发异常。
  • 有趣,看起来他们真的允许在关闭的游标上调用fetchall。不过我有一个疑问,如果你使用with self.conn as cursor: 而不是with self.conn.cursor() as cursor: 会发生什么?
  • 对如何以及为什么感兴趣?那我会写一个答案;评论太长了。他们的文档没有错,只是……不完整。

标签: python mysql python-3.x mariadb pymysql


【解决方案1】:

为什么您没有看到更新:

该行为的原因是 InnoDB 的默认隔离级别 REPEATABLE READ。使用 REPEATABLE READ,第一个非锁定 SELECT 会建立一个快照,表示该时间点的数据。所有连续的非锁定 SELECT 都从同一个快照中读取。其他事务对数据库的更新不会反映在该快照中,因此保持透明。

提交事务(或关闭事务并创建一个新事务)将导致在下一个查询中创建一个新快照,代表数据库中那个时间点的数据。这就是 MySQL 如何将 Consistent Nonlocking Reads 作为其 ACID 合规策略的一部分来实现的。

为什么with self.conn 有效以及它的作用:

在 PyMySQL 中,有两个(相关的)上下文管理器实现,一个在 Cursor(或多或少“记录”)上,一个在 Connection(可以在代码中找到:D)。

当您使用with self.conn.cursor() as cursor: 时,光标的实现生效。进入上下文返回selfself.conn上的cursor()方法返回的游标对象);离开上下文最终关闭了该游标。对交易没有影响。

当使用with self.conn as cursor 时,有效的是连接的实现。进入上下文从调用self.cursor()返回光标;离开上下文对事务执行commitrollback。游标也隐式关闭。

因此,在离开连接实现的上下文时对 self.commit 的隐式调用会使事务中的现有快照“过期”,并强制在循环的下一次迭代中创建一个新快照,其中可能包含您的插入,只要他们的提交在创建所述新快照之前完成。

【讨论】:

    【解决方案2】:

    我已经通过添加self.conn.commit() 解决了同样的问题

    cursor.fetchall()

    【讨论】:

    • 这个解决方案已经由this existing answer提供。在回答老问题时,请确保您的回答对问答提供了独特而有价值的贡献。
    猜你喜欢
    • 1970-01-01
    • 2011-12-29
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 2021-08-24
    • 2013-12-03
    相关资源
    最近更新 更多