Python 如何查看另一个客户端对 MariaDB 所做的更改?
how can Python see changes made to MariaDB by another client?
在我的 Windows 机器上,我在 MariaDB (10.3.7) 上有一个非常简单的数据库,我使用 mysql-connector-python-rf (2.2 .2).
我还使用 2 个 HeidiSQL 实例连接到数据库 workbench。
当我使用其中一个工作台在数据 table 中添加或删除一行时,我可以立即在另一个工作台中使用 SELECT 语句访问更改的数据。我的结论:第一个工作台已经将更改提交到数据库。
不过,看到Python的变化似乎更复杂了。我必须在查询之前添加一个 commit()
才能看到更改:
config = {'user' : 'some_user',
'password': 'some_password',
'host' : '127.0.0.1',
'database': 'some_database',
'raise_on_warnings': True,
}
db = mysql.connector.connect(**config)
# wait some to make changes to the database using the HeidiSQL workbenches
db.commit() # even though Python has not changed anything which needs to be
# committed, this seems necessary to re-read the db to catch
# the changes that were committed by the other clients
cursor = db.cursor()
cursor.execute('some_SQL_query')
for result in cursor:
do_something_with(result)
cursor.close()
到目前为止,我认为 commit()
用于提交 Python 想要对数据库进行的更改。
commit()
还读取自上次 connect()
以来其他客户端对 Python 所做的更改是否正确?这是 bug/inconvenience 还是功能?
或者这里发生了什么我想念的事情?
正如@brunodesthuilliers 所指出的,答案似乎在于隔离级别。 Python 的默认值似乎是 REPEATABLE READ
。要始终读取最新的提交,有必要更改事务的隔离级别,例如至 READ COMMITTED
.
config = {'user' : 'some_user',
'password': 'some_password',
'host' : '127.0.0.1',
'database': 'some_database',
'raise_on_warnings': True,
}
db = mysql.connector.connect(**config)
cursor = db.cursor()
cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;')
cursor.close()
# wait some to make changes to the database using the HeidiSQL workbenches
cursor = db.cursor()
cursor.execute('some_SQL_query') # will now read the last committed data
for result in cursor:
do_something_with(result)
cursor.close()
线程正在写 COMMIT
在写之后发出。在阅读线程中执行 COMMIT
没有任何效果。
我不会更改 "isolation level" 除非您需要 reader 在未完成的更改发生时看到它们。 这通常不是必需的。
因此,writer 应该在完成某个工作单元后立即发出 COMMIT
。那可能是一个 INSERT
;它可能是一个漫长、复杂的操作组合。一个简单的例子就是经典的“资金转移:
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE id = 123; -- my account
UPDATE accounts SET balance = balance - 100 WHERE id = 432; -- your account
COMMIT;
为了 accounts
的完整性,您希望 UPDATEs
要么发生要么不发生,即使系统在中间崩溃。如果 读取 中间的数据,您不希望任何其他线程在 balance
中看到不一致。
另一种表述方式:作者负责说"I'm done"(通过调用commit
)。
在我的 Windows 机器上,我在 MariaDB (10.3.7) 上有一个非常简单的数据库,我使用 mysql-connector-python-rf (2.2 .2).
我还使用 2 个 HeidiSQL 实例连接到数据库 workbench。
当我使用其中一个工作台在数据 table 中添加或删除一行时,我可以立即在另一个工作台中使用 SELECT 语句访问更改的数据。我的结论:第一个工作台已经将更改提交到数据库。
不过,看到Python的变化似乎更复杂了。我必须在查询之前添加一个 commit()
才能看到更改:
config = {'user' : 'some_user',
'password': 'some_password',
'host' : '127.0.0.1',
'database': 'some_database',
'raise_on_warnings': True,
}
db = mysql.connector.connect(**config)
# wait some to make changes to the database using the HeidiSQL workbenches
db.commit() # even though Python has not changed anything which needs to be
# committed, this seems necessary to re-read the db to catch
# the changes that were committed by the other clients
cursor = db.cursor()
cursor.execute('some_SQL_query')
for result in cursor:
do_something_with(result)
cursor.close()
到目前为止,我认为 commit()
用于提交 Python 想要对数据库进行的更改。
commit()
还读取自上次 connect()
以来其他客户端对 Python 所做的更改是否正确?这是 bug/inconvenience 还是功能?
或者这里发生了什么我想念的事情?
正如@brunodesthuilliers 所指出的,答案似乎在于隔离级别。 Python 的默认值似乎是 REPEATABLE READ
。要始终读取最新的提交,有必要更改事务的隔离级别,例如至 READ COMMITTED
.
config = {'user' : 'some_user',
'password': 'some_password',
'host' : '127.0.0.1',
'database': 'some_database',
'raise_on_warnings': True,
}
db = mysql.connector.connect(**config)
cursor = db.cursor()
cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;')
cursor.close()
# wait some to make changes to the database using the HeidiSQL workbenches
cursor = db.cursor()
cursor.execute('some_SQL_query') # will now read the last committed data
for result in cursor:
do_something_with(result)
cursor.close()
线程正在写 COMMIT
在写之后发出。在阅读线程中执行 COMMIT
没有任何效果。
我不会更改 "isolation level" 除非您需要 reader 在未完成的更改发生时看到它们。 这通常不是必需的。
因此,writer 应该在完成某个工作单元后立即发出 COMMIT
。那可能是一个 INSERT
;它可能是一个漫长、复杂的操作组合。一个简单的例子就是经典的“资金转移:
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE id = 123; -- my account
UPDATE accounts SET balance = balance - 100 WHERE id = 432; -- your account
COMMIT;
为了 accounts
的完整性,您希望 UPDATEs
要么发生要么不发生,即使系统在中间崩溃。如果 读取 中间的数据,您不希望任何其他线程在 balance
中看到不一致。
另一种表述方式:作者负责说"I'm done"(通过调用commit
)。