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)。