NOW() 如何与交易交互?

How does NOW() interact with transactions?

我是 运行 事务,它对一个 table 执行多次更新(可能需要几秒钟),然后对第二个 table 执行另一个更新。最终更新的时间戳为 NOW():UPDATE KeyTimestamps SET timestamp=NOW() WHERE key=$key.

我担心更新按一个顺序发生,但时间戳看起来像按另一个顺序发生。所以我们有以下 table 状态序列:

key | timestamp
----+--------------------
 A  | 1970-01-01 00:00:00
 B  | 1970-01-01 00:00:00

key | timestamp
----+--------------------
 A  | 2015-12-02 12:00:00
 B  | 1970-01-01 00:00:00

key | timestamp
----+--------------------
 A  | 2015-12-02 12:00:00
 B  | 2015-12-02 11:59:59

这会发生吗?手册 says

NOW() returns a constant time that indicates the time at which the statement began to execute.

但是一个查询可以先于另一个查询开始执行,然后再执行完吗?交易可以保护我免受这种情况的影响吗?

正如手册所说,MySQL 在每个语句的开头绑定 NOW() 的值。因此,如果在一个语句中多次使用该值,它将是相同的。

如果您需要在多语句序列(事务)开头绑定的值,请执行以下操作:

SET @start := NOW();
SELECT something;
UPDATE something else;
...
UPDATE KeyTimestamps SET timestamp=@start WHERE key=$key

每个不同的客户端连接都将保留自己的变量值,例如 @start,因此当您有多个客户端同时进行交易时,这将起作用。

注意:您几乎同时从不同客户端启动的操作将运行 以正式不可预测的顺序进行。他们不会总是按照您的直觉告诉您的顺序 运行。所以在你的系统设计中尽量避免依赖于精确的操作顺序。自动递增 id 也是如此。如果你确实让你的系统依赖于这些东西,你就创造了 race conditions 的可能性。那些是血腥的谋杀调试。

评论有点长

如果您想知道插入 table 的顺序,请使用自动递增列。这保证永远不会有重复,应该按插入顺序分配。然后您可以将此排序与使用时间戳列的排序进行比较。

请注意,同时插入的两行的时间戳列可能相同。