【问题标题】:how can Python see changes made to MariaDB by another client?Python 如何查看另一个客户端对 MariaDB 所做的更改?
【发布时间】:2018-12-23 21:38:42
【问题描述】:

在我的 Windows 机器上,我在 MariaDB (10.3.7) 上有一个非常简单的数据库,我使用 mysql-connector-python-rf (2.2.2) 连接到该数据库。

我还使用 2 个 HeidiSQL 工作台实例连接到数据库。

当我使用其中一个工作台在数据表中添加或删除一行时,我可以立即在另一个工作台中使用 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 是否正确?这是错误/不便还是功能?

或者我错过了什么?

【问题讨论】:

  • 您要查找的术语是“事务隔离级别”(起点:en.wikipedia.org/wiki/Isolation_(database_systems)
  • @brunodesthuilliers 很有趣……但这不是与并发事务有关吗?就我而言,交易是顺序的(主要是由于我使用鼠标和键盘的处理速度有限)。工作台 1 更改并提交,暂停,工作台 2 看到更改,暂停,Python 直到我在 Python 中 commit() 才看到更改。这是否意味着 Python 正在缓存数据,直到 commit() 强制它刷新缓存?
  • 您搜索的不够多。 dev.mysql.com/doc/refman/8.0/en/…

标签: python mysql mariadb commit


【解决方案1】:

线程正在写发出COMMIT写后。在阅读线程中做COMMIT没有效果。

我不会更改“隔离级别”,除非您需要读者在更改发生时看到未完成的更改。 这通常不是必需的。

所以,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 中看到不一致。

另一种表达方式:作者负责说“我完成了”(通过调用commit)。

【讨论】:

  • 这就是我的想法:只要我要求 Python 更改数据库中的某些内容,我只需要 commit()。但是一旦 Python 连接到 MariaDB 数据库,Python 似乎会从快照(或类似的东西)中读取数据,该数据不反映 其他 客户端将进行和提交的更改。只有在我commit() 在 Python 中 reading 之前,我才能看到来自其他客户端的那些提交。目前我认为这是REPEATABLE READ 交易的副作用。还是我错过了什么?
  • @Olaf - 你说的似乎是正确的。并且“事务隔离”(例如REPEATABLE READ)会影响它。我几乎从不觉得需要改变隔离模式。另外,检查autocommit 的值。
  • connection_object.autocommit = True 属性确实也可以解决问题,并且在读取其他客户端提交的更改之前不再需要connection_object.commit()
【解决方案2】:

正如@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()

【讨论】:

  • 由于将隔离级别设置为“READ COMMITTED”似乎是高级数据库使用:“专家用户可能会选择 READ COMMITTED 级别,因为他们通过 OLTP 处理突破了可扩展性的界限”(dev.mysql.com/doc/refman/8.0/en/… ) 它可能是通过在查询之前发出commit() 来刷新执行查询的快照的更好选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多