MySQL 之 SELECT FOR UPDATE

介紹

FOR UPDATE 是一種行級(jí)鎖,又叫排它鎖。僅適用于 InnoDB,并且必須開啟事務(wù),在 BEGINCOMMIT 之間才生效。

準(zhǔn)備

  • 創(chuàng)建表
CREATE TABLE `goods_order` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `order_number` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '訂單編號(hào)',
  `user_id` bigint DEFAULT NULL COMMENT '下單用戶id',
  `goods_id` bigint DEFAULT NULL COMMENT '商品id',
  `state` int DEFAULT NULL COMMENT '1:待支付 2:已支付 3:已關(guān)閉',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
  `update_time` datetime DEFAULT NULL COMMENT '更新時(shí)間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_number` (`order_number`)
)

開始

開啟兩個(gè) MySQL 命令窗口

  • 命令窗口1
BEGIN
SELECT id, user_id, goods_id, state FROM goods_order WHERE id = 2 FOR UPDATE
UPDATE goods_order SET state = 2 WHERE id=2
COMMIT
  • 命令窗口2
BEGIN
SELECT id, user_id, goods_id, state FROM goods_order WHERE id = 2 FOR UPDATE
UPDATE goods_order SET state = 3 WHERE id=2
COMMIT

當(dāng) 命令窗口1 執(zhí)行完 SELECT ... FOR UPDATE 后(此時(shí)事務(wù)還未結(jié)束), 命令窗口2 執(zhí)行 SELECT ... FOR UPDATE 語句時(shí)將會(huì)阻塞在那,直到 命令窗口1 中的事務(wù)結(jié)束(執(zhí)行完 COMMIT)。

其中一個(gè)使用場(chǎng)景是用于修改訂單狀態(tài),修改訂單狀態(tài)往往需要兩個(gè)步驟:

  1. 查詢訂單狀態(tài)。
  2. 修改訂單狀態(tài)。

當(dāng)有兩個(gè)任務(wù)同時(shí)請(qǐng)求時(shí),有可能出現(xiàn)如下情況:

  1. 任務(wù)A查詢到訂單狀態(tài)為1。
  2. 任務(wù)B查詢到訂單狀態(tài)為1。
  3. 任務(wù)A修改訂單狀態(tài)為2。
  4. 任務(wù)B修改訂單狀態(tài)為3。

其中,任務(wù)B將訂單狀態(tài)改為3的前提是訂單狀態(tài)為1,但是上述情況下任務(wù)B修改訂單時(shí)訂單狀態(tài)已變成2了,并不符合預(yù)期,通過 SELECT ... FRO UPDATE 就可以解決上述問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容