【问题标题】:Row Level Locking - MySQL - for update行级锁定 - MySQL - 用于更新
【发布时间】:2014-10-30 18:10:58
【问题描述】:

我仍然对表行锁定感到困惑。我正在使用 MySQL/PHP,这是我的场景。

我的应用程序使用一组表来跟踪请求和帖子。用户为项目(表 ITEM (I))创建发布(表 POSTING (P))并且可以向单个用户发送请求(表 REQUEST (R))或者可以发布它并接收发布响应(表 POSTING_RESPONSE (PR )) 将被用户发布项目接受。

示例:我是一名骑自行车的用户。我发布它 - 并向个人用户发送请求。收到我的请求的用户可以接受/拒绝/或什么都不做。如果他们接受 - 它被保留。其他用户可以找到我的帖子并“申请”项目。我有能力“接受”或“忽略”他们的要求。如果我接受,则保留项目。

如果有人接受请求,我想做什么:

  1. 锁定ITEM(I)表中item对应的行

  2. 锁住POSTING(P)表中的行(如果行存在的话)对应item

  3. 锁定 REQUEST (R) 表中为项目发送的任何请求的行

  4. 锁定 POSTING_RESPONSE (PR) 表中与项目对应的行(如果存在行)

  5. 将 ITEM 状态更新为“已保留”

  6. 将 POSTING 状态更新为“不可用”

  7. 将所有/任何 POSTING_RESPONSE 更新为“已拒绝”

  8. 将所有请求更新为“已拒绝”,除了已接受的请求 - 将该请求更新为“已接受”

请忽略此示例的冗余状态。

现在,我假设 #1 - 4 可以通过简单的“选择 ... 更新”将 AUTOCOMMIT 设置为 false 来完成。我可以用这些选择语句确定我是否应该更新——如果是这样,我可以继续更新。然后在完成更新 #5-8 后,我将提交并解锁行。

我在让它工作时遇到问题,我不知道是因为我正在做的事情还是我的想法不正确。

还有一件事...还有其他进程可以将项目的状态更新为 EXPIRED 或 CANCELLED。我希望我的方法的唯一解决方案不是将每个可能的条件都放在 UPDATE 语句中的 WHERE 子句中……这不容易维护。

【问题讨论】:

  • 通常 SELECT 是非锁定的读取。要锁定 SELECT,您必须指定 locking reads
  • @JayBlanchard,你能解释一下吗?也许我只是厚,但我之前看过你的参考,从我收集的内容来看,只有两个选项:锁定共享模式 - 不会阻止读取 - 和 FOR UPDATE - 这是我上面的示例显示的. FOR UPDATE 在我上面的例子中不起作用吗?如果不是,应该是什么??
  • 不,我只是错过了阅读。什么不适合你?

标签: php mysql mysqli innodb rowlocking


【解决方案1】:

迷你交易:在一个查询中完成。

UPDATE item
LEFT JOIN posting
   ON posting.item_id = item.id -- or however
LEFT JOIN request 
   ON request.item_id = item.id -- or however
LEFT JOIN posting_reponse
   ON posting_response.item_id = item.id 
SET 
   item.status = 'Reserved',
   posting.status = 'Unavailable',
   posting_reponse.status = 'Rejected',
   request.status = IF(request.id = some-current-id,'Accepted','Rejected')
WHERE item.id = some-id AND item.status='Available';

...不要再问有关锁定读取的问题了,您真的不希望这样:P

【讨论】:

  • Wrikken - 这可能是要走的路,但我仍然不明白锁定读取有什么问题?
  • 如果你说:'没有其他进程可以读取这个数据',他们不会忽略这个数据,但是进程会挂起直到数据可用。虽然这在非常低流量的项目上工作正常,但它的规模不会超过几个访问者:任何适度活跃的项目都会因各种(子)进程/请求等待其他人而停止。随着流量的增加,请求会花费越来越多的时间,并且您会到达发生锁定超时错误的地步。您可以增加该超时时间,但如果他们必须等待超过一分钟才能发生任何事情,那么没有人会再使用您的项目了。
猜你喜欢
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多