<p>正如@DanielRoseman所指出的,您正在事务中编写数据,这是为了让您在更改集之前发生错误时回滚一组更改。因此,在事务期间所做的更改在发生它们的会话之外是不可见的,直到事务被<a href="http://dev.mysql.com/doc/refman/5.0/en/commit.html" rel="nofollow">the ^{<cd1>} statement</a>永久化和最终化。即使您只是在一个<code>SELECT</code>语句中读取数据,也会开始一个事务—因此您的“reading”脚本每次都会查看第一个<code>SELECT</code>时数据库的状态。在</p>
<p>最明显的解决方案是使用与<code>Connection</code>对象相关联的显式<code>commit()</code>方法。但是,一个更优雅的解决方案利用了MySQLdb <code>Connection</code>对象的<a href="https://github.com/farcepest/MySQLdb1/blob/master/MySQLdb/connections.py#L256" rel="nofollow">implementation of the context manager protocol</a>,它是从<a href="http://legacy.python.org/dev/peps/pep-0343/" rel="nofollow">PEP 343</a>采用的:</p>
<pre><code>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()
</code></pre>
<p>它告诉您<code>Connection</code>对象如何与<code>with</code>语句一起工作。因此,如果要以这种方式使用连接对象<code>db</code>:</p>
^{pr2}$
<p>然后发生以下情况:</p>
<ul>
<li><code>x</code>(或您选择的名称)绑定到<code>Cursor</code>对象*返回的<code>db.__enter__()</code></li>
<li>如果在缩进块期间引发异常,<code>db</code>将调用它自己的<code>rollback()</code>方法</li>
<li>否则,<code>db</code>将在离开缩进块时调用自己的<code>commit()</code>方法</li>
</ul>
<p>换句话说,该模块的设计使得您可以通过将每个应该是单个事务事务事务的语句集放入<code>with</code>块中来轻松实现事务。因为您在这里显示的代码只是从表中读取数据,所以无论您决定使用<code>with</code>还是显式调用<code>commit()</code>,最重要的是修改<strong>另一个</strong>脚本。在</p>
<h2>最简单的事</h2>
<p>…因为“reading”脚本将在打开连接后通过调用<code>db.autocommit(True)</code>来启用自动提交模式。<a href="http://legacy.python.org/dev/peps/pep-0249/#commit" rel="nofollow">The Python database API</a>指定“如果数据库支持自动提交功能,则必须首先关闭该功能”,但是如果不担心并发问题,那么就没有理由不打开它,“读取”脚本应该就是这样。在</p>
<p>事实上,如果服务器上只有这两个脚本在运行,而您不需要在另一个脚本中执行事务,那么最简单的方法就是在两个脚本中打开autocommit并忘掉它。但是,如果您忘记了在这里所做的,而去编写其他需要执行并发事务的脚本,那么这有可能会在以后给您带来麻烦。在</p>
<p>*请注意,<code>db.__enter__()</code>为您创建的光标是由^{<cd22>关闭的<em>而不是</em>。在本例中,<code>MySQLdb.Cursor</code>实际上只是<a href="http://mysql-python.sourceforge.net/MySQLdb.html#connection-objects" rel="nofollow">a Python object that emulates a cursor</a>;它不占用任何额外的服务器资源,而且通常不必担心关闭它。实际上,只要它的父对象<code>Connection</code>保持打开状态,就可以在<code>with</code>块退出后的<code>with</code>语句中继续引用<code>Cursor</code>对象。(当然,除非您显式地<code>close()</code>光标或将其名称绑定到另一个对象。)</p>