mysql 隊列 完成並發讀。本站提示廣大學習愛好者:(mysql 隊列 完成並發讀)文章只能為提供參考,不一定能成為您想要的結果。以下是mysql 隊列 完成並發讀正文
一個 MySQL 表可以看做是一個隊列,每行動一個元素。每次查詢獲得知足某個前提的最後面的一行,並將它從表中刪除或許轉變它的狀況,使得下次查詢不會獲得它。在沒有並發拜訪的情形下,簡略地用 SELECT 獲得一行,再用UPDATE(或許DELETE)語句修正之,便可以完成。
SELECT * FROM targets WHERE status='C' LIMIT 1;
UPDATE targets SET status='D' WHERE id='id';
假如有並發拜訪,在SELECT和UPDATE語句之間能夠會存在其他地SELECT查詢,招致統一行被掏出屢次。為了包管在並發情形下依然能正常任務,一種思緒是應用數據庫地鎖來避免,就像在多線程情況下所做地一樣。總之,如果的查詢和修正為一個原子操作,不被其它的拜訪攪擾。MySQL 5 支撐存儲進程,可以用它來完成。
單條 UPDATE 語句應當原子操作的,可以應用這個特征來包管並發拜訪情形下隊列的正常任務。每次取元素時,先用 UPDATE 修正相符前提的第一行,然後再獲得該行。惋惜 UPDATE 語句沒有前往值,從新用通俗的SELECT的話又很難找到剛被悛改的那筆記錄。
這裡用到一個小技能:在 UPDATE 時加上 id=LAST_INSERT_ID(id),再用 SELECT LAST_INSERT_ID() 便可獲得剛修正的那筆記錄的id。還有一個成績,當表中不存在相符前提的記載,招致 UPDATE 掉敗時,LAST_INSERT_ID() 會保存本來地值不變,因此不克不及辨別隊列中能否還有元素。
ROW_COUNT() 前往上一個語句影響的行數,把它作為 SELECT 的一個前提,可以贊助處理這個成績。
最初,支撐並發拜訪的完全處理計劃為:
UPDATE targets SET status='D', id=LAST_INSERT_ID(id) WHERE status='C' LIMIT 1;
SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();
更新:在完成帶優先級的隊列時這類辦法有成績,帶有 ORDER BY ... 前提的 UPDATE 語句異常慢,例如:
UPDATE targets SET status='D' WHERE status='C' ORDER BY schedule ASC LIMIT 1;
而零丁查詢和更新則是很快的:
SELECT id FROM targets WHERE status='C' ORDER BY schedule ASC LIMIT 1;
UPDATE targets SET status='D' WHERE id='id';
本來這是MySQL的Bug-12915,一年多之前提出來的,固然封閉了,卻只處理了部門成績,尚不支撐WHERE,見MySQL 5.0.15 的 Changlog。無法,下面這類奇妙的辦法也沒有適用價值了。
最初采取了一種調和計劃,以下:
UPDATE targets, (SELECT id FROM targets WHERE status='C' AND schedule<CURRENT_TIMESTAMP ORDER BY schedule ASC LIMIT 1) tmp SET status='D' WHERE targets.id=LAST_INSERT_ID(tmp.id);
SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();