首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在python中获取更新的MySQL表条目而不关闭连接

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

Stack Overflow用户
提问于 2014-06-25 18:14:38
回答 2查看 2.2K关注 0票数 2

我有2个python程序在运行。Script1定期将条目写入表,Script2从同一个MySQL表读取条目。两人同时奔跑。Script2必须获得表的最后(最新添加的)条目。

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

,这是唯一可以采取的方法吗?是否有一种方法可以获得更新的值,而不需要每次关闭和打开连接?当访问不断更新的DB时,最佳实践程序员遵循什么?

更详细的是:

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

代码语言:javascript
运行
复制
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。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-25 18:18:41

这仅仅是因为事务内部的读取隔离。在每个循环之后执行db.commit()

票数 5
EN

Stack Overflow用户

发布于 2014-06-25 19:00:49

正如@DanielRoseman所指出的,您正在事务中写入数据,这是为了在更改集发生之前出错时,允许您回滚一组更改。因此,在事务期间所做的更改在会话之外是不可见的,直到语句将事务变为永久的和最终的。即使您只是在SELECT语句中读取数据,也可以开始一个事务--因此您的“读取”脚本每次都在查看数据库在第一个SELECT时所处的状态。

最明显的解决方案是使用与commit()对象关联的显式Connection方法。然而,更优雅的解决方案利用了MySQLdb Connection对象的上下文管理器协议的实现,该上下文管理器协议的实现是从佩普343中采用的

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
with db as x:
    # indented code block here

然后发生以下情况:

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

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

最容易做的事。

...for“读”脚本是在打开连接后调用db.autocommit(True)来启用自动提交模式。Python数据库API指定“如果数据库支持自动提交功能,这必须在一开始就关闭”,但是如果您不担心并发性问题,就没有理由不能打开它,这应该是您的“读取”脚本的情况。

事实上,如果这两个脚本是服务器上唯一的事情,并且您不需要在其他脚本中进行事务处理,那么最简单的方法就是在这两个脚本中打开自动提交,然后忘记它。但是,如果您忘记了这里所做的事情,然后编写需要执行并发事务的其他脚本,这可能会让您在以后的日子里陷入麻烦。

*注意,db.__enter__()为您创建的游标不是由db.__exit__()关闭的。在这种情况下,MySQLdb.Cursor实际上只是模拟游标的Python对象;它不会占用任何额外的服务器资源,您通常不必担心关闭它。实际上,在Cursor块退出后,您可以继续使用with语句中绑定它的任何名称来引用with对象,只要其父Connection仍然处于打开状态。(当然,除非显式地close()游标或将其名称绑定到另一个对象。)

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

https://stackoverflow.com/questions/24415699

复制
相关文章

相似问题

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