MySQL FOR UPDATE 鎖的一點問題

來源:互聯網
上載者:User

問題描述

假設一個情況,這裡只是假設,真實的情況可能不會這樣設計,但是假如真的發生了....
鐵老大有一張這樣的ticket表,用來存放北京到上海的票。

id uid start_addr end_addr book_time
1 1300009860 上海 北京 13866660321
2 0 上海 北京  
3 0 上海 北京  
4 0 上海 北京

uid 不等於0 並且 book_time 不等於0,則表示已售出,不許再更改。
年底了,大家開始搶了,當某一個人開始搶的時候,鐵老大這樣做了,當A開始搶的時候,從表中所有uid=0的記錄中隨機取出一條,然後修改目前記錄的uid為A的uid,book_time為目前時間。

那麼好了,這個時候並發產生了,10000個人同時搶最後剩下的10張票,有2個人A,B同時讀取了uid=0 and id=2的記錄,然後A把uid修改為自己的,book_time修改timeA,系統通知A搶票成功 緊接著,B同樣修改了這條記錄為自己的,那麼這個時候A的票就失效了。

這裡就考慮使用鎖機制了,如果在A讀取了這條記錄後,並把這條記錄加上寫鎖,那麼別人就無法再讀取加鎖,也就不會修改多次了。

實驗結果
實驗了一下for update 加鎖,然後發現了一些問題。
1、當我們使用主鍵查詢去加鎖的時候,可以對這條記錄加行鎖
開啟一個終端:執行一下代碼:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from ticket where id = 2 for update;

那麼 id=2這個記錄就會被加行寫鎖。
令一個終端將無法讀取該記錄,但是卻可以讀取其他記錄
#可以讀取加鎖
mysql> select * from ticket where id = 3 for update;
#不可以讀取
mysql> select * from ticket where id = 2 for update;

2、但是當我們按非主鍵查詢會怎樣呢

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from ticket where uid = 0 limit 1 for update;

那麼這個時候,這個表會被鎖住,任何記錄都不能再讀取加鎖
//不可讀取,等待釋放鎖
mysql> select * from ticket where id = 1 for update;
//不可讀取等待釋放鎖
mysql> select * from ticket where uid = 0 limit 1 for update;

但是表鎖會減少並發。
結論
有沒有一種方法,可以在非主鍵欄位查詢一條記錄時上實現加行寫鎖,期待高手支招。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.