玛丽亚数据库。在不锁定表的情况下使用事务回滚
MariaDB. Use Transaction Rollback without locking tables
在网站上,当用户发表评论时,我会进行多次查询、插入和更新。 (在 MariaDB 10.1.29 上)
我使用 START TRANSACTION
因此,如果任何查询在任何给定点失败,我可以轻松地回滚并删除所有更改。
现在我注意到当我从另一个 INSERT
执行 INSERT
时,这个 锁定了 table,而且我在查询时没有说话是运行,这是显而易见的,但是直到事务没有关闭。
然后 DELETE
只有在它们共享一个公共索引键(同一页面的评论)时才会被锁定,但幸运的是 UPDATE
没有被锁定。
我可以做任何不从新插入锁定 table 的交易吗(交易正在进行时,而不是实际查询),或者任何其他让我方便 "undo" 的方法某个点后查询完成了吗?
PD:
我使用 PHPs 函数 mysqli_begin_transaction()
开始交易,没有任何 flags
,然后 mysqli_commit()
。
我不认为简单的 INSERT 会阻止其他插入的时间超过插入时间。 AUTO_INC locks 没有持有完整的交易时间。
但是如果两个事务尝试更新同一行,如以下语句(对同一评论的两个回复)
UPDATE comment SET replies=replies+1 WHERE com_id = ?
第二个必须等到第一个提交。您需要那个锁来保持计数(回复)一致。
我想你能做的就是尽量缩短交易时间。例如,您可以在开始交易之前准备好所有报表。但那是几毫秒的事情。如果您传输文件并且可能需要 40 秒,那么您不应该在数据库事务打开时执行此操作。在开始事务之前传输文件并使用指示操作未完成的名称保存它们。您也可以将它们保存在不同的文件夹中,但在同一分区中。然后当你 运行 交易时,你只需要重命名文件,这应该不会花费太多时间。有时您可以 clean-up 并删除未重命名的文件。
所有写操作都以类似的方式工作——它们锁定它们接触(或可能接触)的行,从语句执行到事务通过以下任一方式关闭COMMIT
或 ROLLBACK
。 SELECT...FOR UPDATE
和 SELECT...WITH SHARED LOCK
也参与其中。
发生写操作时,进行死锁检查。
在某些情况下,有 "gap" 锁定。 com_id
是否恰好是 table 中的最后一个 ID?
您是否遗漏了任何需要 FOR UPDATE
的 SELECTs
?
在网站上,当用户发表评论时,我会进行多次查询、插入和更新。 (在 MariaDB 10.1.29 上)
我使用 START TRANSACTION
因此,如果任何查询在任何给定点失败,我可以轻松地回滚并删除所有更改。
现在我注意到当我从另一个 INSERT
执行 INSERT
时,这个 锁定了 table,而且我在查询时没有说话是运行,这是显而易见的,但是直到事务没有关闭。
然后 DELETE
只有在它们共享一个公共索引键(同一页面的评论)时才会被锁定,但幸运的是 UPDATE
没有被锁定。
我可以做任何不从新插入锁定 table 的交易吗(交易正在进行时,而不是实际查询),或者任何其他让我方便 "undo" 的方法某个点后查询完成了吗?
PD:
我使用 PHPs 函数 mysqli_begin_transaction()
开始交易,没有任何 flags
,然后 mysqli_commit()
。
我不认为简单的 INSERT 会阻止其他插入的时间超过插入时间。 AUTO_INC locks 没有持有完整的交易时间。
但是如果两个事务尝试更新同一行,如以下语句(对同一评论的两个回复)
UPDATE comment SET replies=replies+1 WHERE com_id = ?
第二个必须等到第一个提交。您需要那个锁来保持计数(回复)一致。
我想你能做的就是尽量缩短交易时间。例如,您可以在开始交易之前准备好所有报表。但那是几毫秒的事情。如果您传输文件并且可能需要 40 秒,那么您不应该在数据库事务打开时执行此操作。在开始事务之前传输文件并使用指示操作未完成的名称保存它们。您也可以将它们保存在不同的文件夹中,但在同一分区中。然后当你 运行 交易时,你只需要重命名文件,这应该不会花费太多时间。有时您可以 clean-up 并删除未重命名的文件。
所有写操作都以类似的方式工作——它们锁定它们接触(或可能接触)的行,从语句执行到事务通过以下任一方式关闭COMMIT
或 ROLLBACK
。 SELECT...FOR UPDATE
和 SELECT...WITH SHARED LOCK
也参与其中。
发生写操作时,进行死锁检查。
在某些情况下,有 "gap" 锁定。 com_id
是否恰好是 table 中的最后一个 ID?
您是否遗漏了任何需要 FOR UPDATE
的 SELECTs
?