SELECT FOR UPDATE用于锁定查询

时间:2008-12-25 07:53:24

标签: sql mysql transactions

我正在使用MySql 5.x,在我的环境中,我有一个名为CALLS的表。

表CALLS的列状态采用枚举{inprogress,completed}。

我希望表的读取/更新是行锁定的,所以:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET AUTOCOMMIT = 0;
SELECT amount from CALLS where callId=1213 FOR UPDATE;
COMMIT

基本上我正在进行FOR UPDATE,即使在我只需要阅读金额并返回的情况下。我发现这可以让我确保防止读取/更新相互干扰。但是我被告知这会降低应用程序的并发性。

无论如何都能实现相同的事务一致性而不会产生锁定开销吗?感谢。

2 个答案:

答案 0 :(得分:1)

免责声明:MySQL通常充满惊喜,因此以下内容可能不真实。

你在做什么对我没有任何意义:你在SELECT之后提交,这应该打破锁定。所以在我看来,你的代码不应该真正产生任何重大的开销;但它也没有给你任何一致性改进。

通常,SELECT FOR UPDATE可以是一种非常合理的方式来确保一致性而不需要比实际需要更多的锁。但是,当然,它只应在需要时使用。也许你应该有不同的代码路径:在后续的更改操作中使用检索的值时使用的一个(使用FOR UPDATE)。另外一个(不使用FOR UPDATE)在不必保护值不受变化时使用。

答案 1 :(得分:0)

你在那里实施的内容 - 如果你不熟悉它 - 被称为pessimistic locking。你为牺牲一致性而牺牲性能,这有时是一个有效的选择。根据我的专业经验,我发现悲观锁定远比帮助更具障碍。

首先,它可以导致deadlock

(更好的imho)替代方案是optimistic locking,你可以假设碰撞很少发生,你只需要在碰撞时处理它们。你在交易中做你的事,所以碰撞不应该让你的数据处于不一致的状态。

这里有关于Java optimistic locking的更多信息,但这些想法适用于任何事情。