假设我对我的数据库中的一个表有大约 1000 个同时请求,该表由这些语句组成(按顺序):
SELECT
INSERT or UPDATE (could be multiple)
DELETE
我想确保没有任何请求相互干扰,并且表处于下一个传入请求的更新状态。例如:
Request #1 comes in.
Request #2 comes in.
Request #1 starts to get processed.
Request #2 should start only when Request #1 is processed so that the data view is consistent and updated for the next request.
我在网上搜索了这种情况,发现了两件事可能会有所帮助:
交易
表锁定
但是当我阅读事务时,我发现当一个事务正在处理一行时,其他事务仍然可以出现并修改该行,这违背了我的目的。
同样在锁定的情况下,只能将列锁定在一种模式下,即读取或写入模式,这再次无法保持数据一致,因为在读取行时它可能会被更新并且刚刚读取的数据将成为旧版本的表实际上是现在。
有没有一种可靠的方法来实现这一点,可以确保没有请求干扰另一个请求,并且表处于下一个传入请求的更新状态?
如果这有帮助,我正在将 MySQL 与 PHP 一起使用。
交易是要走的路。
引用您的来源,因为坦率地说,这是完全错误的。
Transactions的全部意义在于它们为您提供了您正在寻找的那种变化的“原子性”。
表锁定是一个太宽泛的刷子,无法在这里使用。
锁定许多行只是更新一个行效率不高,会产生更多的争用,更多的等待,只会减慢一切。打个比方,这就像试图通过堵住城市中其他房子的每个信箱来向一所房子投递一封信。
除了菲尔的点...
一个常见的模式:
这(大致)执行以下操作之一:
innodb_lock_wait_timeout
) 当前交易看到一个值;被阻止的交易在您的COMMIT
.SERIALIZABLE是多余的。如上所述,这是一种禁止并发访问的蛮力方式。
更多关于您提到的数据视图。
每个事务都会看到数据的“快照”。该快照是事务开始时的所有数据。该实现涉及保留行的副本(参见“历史列表”),以便每个事务都可以找到过去一段时间的数据。
这是很难实现的。而且很难探查。您可以轻松验证“在同一 1 秒内对表的 1000 个请求”。但是,如果您查看详细信息,您可能会发现实际上“同时”运行的“请求”不超过 10 个。但是它们在 10 毫秒内完成,所以整个集合在一秒钟内完成。
所以,让我们把这个问题分成两件事: