最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mysql 隊(duì)列 實(shí)現(xiàn)并發(fā)讀

 更新時(shí)間:2012年04月24日 20:39:01   作者:  
隊(duì)列是常用的數(shù)據(jù)結(jié)構(gòu),基本特點(diǎn)就是先入先出,在事務(wù)處理等方面都要用到它,有的時(shí)候是帶有優(yōu)先級(jí)的隊(duì)列。當(dāng)隊(duì)列存在并發(fā)訪問的時(shí)候,比如多線程情況下,就需要鎖機(jī)制來保證隊(duì)列中的同一個(gè)元素不被多次獲取
一個(gè) MySQL 表可以看作是一個(gè)隊(duì)列,每一行為一個(gè)元素。每次查詢得到滿足某個(gè)條件的最前面的一行,并將它從表中刪除或者改變它的狀態(tài),使得下次查詢不會(huì)得到它。在沒有并發(fā)訪問的情況下,簡(jiǎn)單地用 SELECT 得到一行,再用UPDATE(或者DELETE)語句修改之,就可以實(shí)現(xiàn)。
復(fù)制代碼 代碼如下:

SELECT * FROM targets WHERE status='C' LIMIT 1;
UPDATE targets SET status='D' WHERE id='id';

如果有并發(fā)訪問,在SELECT和UPDATE語句之間可能會(huì)存在其他地SELECT查詢,導(dǎo)致同一行被取出多次。為了保證在并發(fā)情況下仍然能正常工作,一種思路是使用數(shù)據(jù)庫地鎖來防止,就像在多線程環(huán)境下所做地一樣??傊?,要是的查詢和修改為一個(gè)原子操作,不被其它的訪問干擾。MySQL 5 支持存儲(chǔ)過程,可以用它來實(shí)現(xiàn)。
單條 UPDATE 語句應(yīng)該原子操作的,可以利用這個(gè)特性來保證并發(fā)訪問情況下隊(duì)列的正常工作。每次取元素時(shí),先用 UPDATE 修改符合條件的第一行,然后再得到該行??上?UPDATE 語句沒有返回值,重新用普通的SELECT的話又很難找到剛被改過的那條記錄。
這里用到一個(gè)小技巧:在 UPDATE 時(shí)加上 id=LAST_INSERT_ID(id),再用 SELECT LAST_INSERT_ID() 即可得到剛修改的那條記錄的id。還有一個(gè)問題,當(dāng)表中不存在符合條件的記錄,導(dǎo)致 UPDATE 失敗時(shí),LAST_INSERT_ID() 會(huì)保留原來地值不變,因而不能區(qū)分隊(duì)列中是否還有元素。
ROW_COUNT() 返回上一個(gè)語句影響的行數(shù),把它作為 SELECT 的一個(gè)條件,可以幫助解決這個(gè)問題。
最后,支持并發(fā)訪問的完整解決方案為:

復(fù)制代碼 代碼如下:

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();

更新:在實(shí)現(xiàn)帶優(yōu)先級(jí)的隊(duì)列時(shí)這種方法有問題,帶有 ORDER BY ... 條件的 UPDATE 語句非常慢,例如:

復(fù)制代碼 代碼如下:
UPDATE targets SET status='D' WHERE status='C' ORDER BY schedule ASC LIMIT 1;


而單獨(dú)查詢和更新則是很快的:
復(fù)制代碼 代碼如下:

SELECT id FROM targets WHERE status='C' ORDER BY schedule ASC LIMIT 1;
UPDATE targets SET status='D' WHERE id='id';


原來這是MySQL的Bug-12915,一年多以前提出來的,雖然關(guān)閉了,卻只解決了部分問題,尚不支持WHERE,見MySQL 5.0.15 的 Changlog。無奈,上面這種巧妙的方法也沒有實(shí)用價(jià)值了。
最后采用了一種折衷方案,如下:

復(fù)制代碼 代碼如下:

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();

相關(guān)文章

最新評(píng)論

凌源市| 德令哈市| 麦盖提县| 喀喇| 广安市| 北票市| 临西县| 泽库县| 吉隆县| 奇台县| 达孜县| 玛沁县| 怀宁县| 阿鲁科尔沁旗| 乐昌市| 彭山县| 鄱阳县| 澳门| 星座| 绥德县| 丹江口市| 女性| 隆昌县| 洮南市| 濮阳县| 青州市| 凤翔县| 沧源| 永登县| 越西县| 巴塘县| 革吉县| 邻水| 濮阳县| 苏州市| 拜泉县| 金昌市| 白河县| 利辛县| 新巴尔虎右旗| 江津市|