在python中获取更新的MySQL表条目,而不关闭连接

2024-10-04 01:24:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个python程序在运行。Script1定期向表中写入条目,Script2从同一个MySQL表中读取数据。两者同时运行。Script2必须获取表的最后一个(最新添加的)条目。在

现在,问题是Script1完美地向表中添加条目,但是Script2无法每次读取最新的条目。它只在我阅读后关闭连接时读取最新的条目,当我想再次阅读时重新打开它。在

这是唯一可以采取的方法吗?有没有一种方法可以在不需要每次关闭和打开连接的情况下获取更新值?在访问不断更新的数据库时,程序员遵循的最佳实践是什么?

更详细地说:

下面的代码工作正常,但无法显示更新的值。它第一次成功地显示了最后一个条目,但是在接下来的几次readComm()被调用时,相同的条目会再次显示,尽管表已经被更新。在

import MySQLdb
import time

db = MySQLdb.connect("localhost", "root", "abc", "abc")
cursor=db.cursor()

def readComm():
    sql = "SELECT * FROM my_table ORDER BY id DESC LIMIT 1;"
    try:
        cursor.execute(sql)
        # Fetch all the rows in a list of lists.
        results = cursor.fetchall()
        print '~~~~', results
    except:
        print "Error! Unable to fetch data" 
    return
for i in range(5):
    readComm()
    time.sleep(10)

如果我修改代码,使它在每次输入和退出readComm()时打开和关闭DB,那么代码将显示更新的值。在


Tags: 方法代码inimportdbsqltime条目
2条回答

这只是因为事务中的读隔离。每次循环后执行db.commit()。在

正如@DanielRoseman所指出的,您正在事务中编写数据,这是为了让您在更改集之前发生错误时回滚一组更改。因此,在事务期间所做的更改在发生它们的会话之外是不可见的,直到事务被the ^{} statement永久化和最终化。即使您只是在一个SELECT语句中读取数据,也会开始一个事务—因此您的“reading”脚本每次都会查看第一个SELECT时数据库的状态。在

最明显的解决方案是使用与Connection对象相关联的显式commit()方法。但是,一个更优雅的解决方案利用了MySQLdb Connection对象的implementation of the context manager protocol,它是从PEP 343采用的:

def __enter__(self):
   if self.get_autocommit():
       self.query("BEGIN")
   return self.cursor()

def __exit__(self, exc, value, tb):
   if exc:
       self.rollback()
   else:
       self.commit()

它告诉您Connection对象如何与with语句一起工作。因此,如果要以这种方式使用连接对象db

^{pr2}$

然后发生以下情况:

  • x(或您选择的名称)绑定到Cursor对象*返回的db.__enter__()
  • 如果在缩进块期间引发异常,db将调用它自己的rollback()方法
  • 否则,db将在离开缩进块时调用自己的commit()方法

换句话说,该模块的设计使得您可以通过将每个应该是单个事务事务事务的语句集放入with块中来轻松实现事务。因为您在这里显示的代码只是从表中读取数据,所以无论您决定使用with还是显式调用commit(),最重要的是修改另一个脚本。在

最简单的事

…因为“reading”脚本将在打开连接后通过调用db.autocommit(True)来启用自动提交模式。The Python database API指定“如果数据库支持自动提交功能,则必须首先关闭该功能”,但是如果不担心并发问题,那么就没有理由不打开它,“读取”脚本应该就是这样。在

事实上,如果服务器上只有这两个脚本在运行,而您不需要在另一个脚本中执行事务,那么最简单的方法就是在两个脚本中打开autocommit并忘掉它。但是,如果您忘记了在这里所做的,而去编写其他需要执行并发事务的脚本,那么这有可能会在以后给您带来麻烦。在

*请注意,db.__enter__()为您创建的光标是由^{关闭的而不是。在本例中,MySQLdb.Cursor实际上只是a Python object that emulates a cursor;它不占用任何额外的服务器资源,而且通常不必担心关闭它。实际上,只要它的父对象Connection保持打开状态,就可以在with块退出后的with语句中继续引用Cursor对象。(当然,除非您显式地close()光标或将其名称绑定到另一个对象。)

相关问题 更多 >