Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么我需要重新连接到数据库以查看表数据中的更改?_Python_Mysql_Sql_Cursor_Mysql Python - Fatal编程技术网

Python 为什么我需要重新连接到数据库以查看表数据中的更改?

Python 为什么我需要重新连接到数据库以查看表数据中的更改?,python,mysql,sql,cursor,mysql-python,Python,Mysql,Sql,Cursor,Mysql Python,我定期查询MySQL表并检查同一行中的数据 我使用MySQLdb来完成这项工作,每15秒查询一次相同的表和行 实际上,行数据每3秒更改一次,但光标始终返回相同的值 奇怪的是:在我关闭MySQL连接并重新连接之后,使用新的游标执行相同的select命令,返回新的值 我怀疑是错误的代码在注释后开始: config = SafeConfigParser() config.read("../test/settings_test.conf") settings = {} settings["mysql_

我定期查询MySQL表并检查同一行中的数据

我使用MySQLdb来完成这项工作,每15秒查询一次相同的表和行

实际上,行数据每3秒更改一次,但光标始终返回相同的值

奇怪的是:在我关闭MySQL连接并重新连接之后,使用新的游标执行相同的select命令,返回新的值

我怀疑是错误的代码在注释后开始:

config = SafeConfigParser()
config.read("../test/settings_test.conf")

settings = {}
settings["mysql_host"] = config.get("mysql","mysql_host")
settings["mysql_port"] = int(config.get("mysql","mysql_port"))
settings["mysql_user"] = config.get("mysql","mysql_user")
settings["mysql_password"] = config.get("mysql","mysql_password")
settings["mysql_charset"] = config.get("mysql","mysql_charset")

#suspected wrong code
conn = mysql_from_settings(settings)
cur = conn.cursor()
cur.execute('use database_a;')
cur.execute('select pages from database_a_monitor where id=1;')
result = cur.fetchone()[0]
print result
#during 15 second, I manually update the row and commit from mysql workbench
time.sleep(15)    

cur.execute('select pages from database_a_monitor where id=1;')
result = cur.fetchone()
print result
conn.close()
输出为:

94
94
94
104
如果我更改代码,使其关闭连接并重新连接,它将返回最新的值,而不是重复相同的值:

conn = mysql_from_settings(settings)
cur = conn.cursor()
cur.execute('use database_a;')
cur.execute('select pages from database_a_monitor where id=1;')
result = cur.fetchone()[0]
print result
conn.close()

time.sleep(15)
#during that period, I manually update the row and commit from mysql workbench

conn = mysql_from_settings(settings)
cur = conn.cursor()
cur.execute('use database_a;')
cur.execute('select pages from database_a_monitor where id=1;')
result = cur.fetchone()[0]
print result
conn.close() 
输出为:

94
94
94
104
为什么会有这种行为上的差异

以下是设置中mysql的定义:

def mysql_from_settings(settings):
    try:
        host = settings.get('mysql_host')
        port = settings.get('mysql_port')
        user = settings.get('mysql_user')
        password = settings.get('mysql_password')
        charset = settings.get('mysql_charset')
        conn=MySQLdb.connect(host=host,user=user,passwd=password,port=port,\
               charset=charset)

        return conn
    except MySQLdb.Error,e:
        print "Mysql Error %d: %s" % (e.args[0], e.args[1])

这几乎可以肯定是事务隔离的结果。既然您没有另外声明,我将假设您正在使用默认的存储引擎()和隔离级别():

可重复读取 InnoDB的默认隔离级别。它防止查询的任何行被其他行更改 事务,从而阻止不可重复的读取 幻影读取。它使用一种适度严格的锁定策略,以便事务中的所有查询都可以看到来自 相同的快照,即事务发生时的数据 开始

有关更多详细信息,请参阅MySQL文档中的

简单地说,这意味着当您在事务中从表中选择时,从表中读取的值在事务期间不会改变;您将继续看到事务打开时表的状态,以及在同一事务中所做的任何更改

在您的情况下,每3秒钟的更改将在其他会话和事务中进行。为了“查看”这些更改,您需要保留在发出第一个
选择
时开始的事务,并启动一个新事务,然后该事务将“查看”表的新快照

您可以在SQL中使用或通过调用显式管理事务。一个更好的方法可能是利用;例如:

conn = mysql_from_settings(settings)
with conn as cur:
    cur.execute('use database_a;')
    cur.execute('select pages from database_a_monitor where id=1;')
    result = cur.fetchone()[0]
print result
#during 15 second, I manually update the row and commit from mysql workbench
time.sleep(15)    

cur.execute('select pages from database_a_monitor where id=1;')
result = cur.fetchone()
print result
conn.close()
with
语句与MySQLdb的
Connection
对象一起使用时,会返回一个游标。当您使用
块离开
时,
连接。\uuu退出\uuu
被调用:

def __exit__(self, exc, value, tb):
    if exc:
        self.rollback()
    else:
        self.commit()
因为您所做的只是读取数据,所以没有什么要回滚或提交的;写入数据时,请记住,通过异常离开块将导致回滚更改,而正常离开将导致提交更改

注意,这并没有关闭游标,它只管理事务上下文。在我对的回答中,我对这个问题进行了更详细的讨论,但简短的故事是,在使用MySQLdb时,通常不必担心关闭游标

您还可以通过不发出
USE
语句来让您的生活变得更轻松


提供了两种其他方法,您可以将隔离级别更改为或启用。

相关,可能重复:谢谢。它工作正常。引擎是InnoDB。你救了我一天。