我正在运行对一个表执行许多更新的事务(可能需要几秒钟),然后再对第二个表执行另一次更新。最终更新的时间戳为NOW():UPDATE KeyTimestamps SET timestamp=NOW() WHERE key=$key
。
我担心一个订单中发生的更新,但时间戳看起来像是以其他顺序发生的。这样我们就有了以下表状态序列:
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()返回一个常量时间,指示语句开始执行的时间。
但是一个查询可以在另一个之前开始执行,并在以后完成执行吗?交易能保护我免受这种影响吗?
答案 0 :(得分:2)
评论时间有点长。
如果您想知道插入到表中的顺序,请使用自动递增列。这保证永远不会有重复,应按插入顺序分配。然后,您可以使用时间戳列将此排序与排序进行比较。
请注意,对于同时插入的两行,时间戳列可能相同。
答案 1 :(得分:1)
正如手册所说,MySQL在每个单独语句的开头绑定NOW()
的值。因此,如果在语句中多次使用该值,则它将是相同的。
如果需要在多语句序列(事务)的开头绑定值,请执行以下操作:
SET @start := NOW();
SELECT something;
UPDATE something else;
...
UPDATE KeyTimestamps SET timestamp=@start WHERE key=$key
每个不同的客户端连接都会保留自己的变量值,例如@start
,这样当多个客户端同时执行事务时,这将起作用。
小心:您在不同客户端几乎同时启动的操作将按照正式无法预测的顺序运行。他们不会总是以你的直觉告诉他们的意愿顺序奔跑。因此,请尽量避免依赖于系统设计中的精确操作顺序。自动增量id也是如此。如果你确实让你的系统依赖于这些东西,你就可以创造race conditions的可能性。这些都是血腥的谋杀案。