php當資料庫update遇到並發,一個小坑

來源:互聯網
上載者:User

標籤:blog   http   io   os   使用   ar   java   strong   檔案   

有一個答題的小項目,表的欄位如下:

id 使用者id
times 答題次數
questions 回答的問題id,這是一個php serialize()的字串

當使用者答完題像後端提交結果時,構建的post包如下:

{    ‘id‘:1,    ‘questionid‘:38}

後台邏輯如下:

$user = User::findFirst("id = ?1",array(‘id‘=>$_POST[‘id‘]));//取得使用者模型$questions = unserialize($user->questions);//還原序列化$questionid = (int)$_POST[‘questionid‘];//題目idif ( ! in_array($questionid,$questions)) {//判斷使用者是否答過,沒有答過則將題目id添加到questions欄位裡    $questions[] = $questionid;    $user->times += 1;//統計答題次數    $user->questions = serialize($questions);//序列化questions    $user->save();//update} else {    exit(‘對不起,這個題目你已經答過‘);}

看上去流程沒有問題啊,使用者每次提交的時候會先讀取自己的資料,檢測是否答過這個題目,答過則直接退出。

但是出問題了:
當活動推出的第二天,後台資料發現有個使用者的times答題次數和questions記錄數不匹配,表現為 times=120 count(unserialize(questions))=17。
當時很奇怪,代碼正常流程是沒問題的,卡了半天,一直沒想出來使用者如何造成這種資料的,直到剛才,終於開竅,正如題目中所說,問題出在並發上,這個使用者可能自己寫指令碼或者藉助第三方工具,類比post請求,並使用多線程等技術造成並發請求,我們來類比一下並發過程:

使用者同時發起兩個請求,php也就分配了兩個進程來處理,當著兩個進程幾乎同時執行了這行代碼:

$user = User::findFirst("id = ?1",array(‘id‘=>$_POST[‘id‘]));//取得使用者模型

此時在兩個進程中的$user資料是一樣的,我們假設一下,此時$user->questions 的值為 {1,2}。

假設兩個請求構建的post資料包分別為:

{    ‘id‘:1,    ‘questionid‘:3}

{    ‘id‘:1,    ‘questionid‘:4}

那麼當代碼執行到:

in_array($questionid,$questions)

的時候實際上返回的都是 false
他們相繼發起了 $user->save() ,分別希望將 3 和 4 加進questions,注意,這時候questions在資料庫中的值還是{1,2},而sql語句是一條條執行的,也就是說資料庫按順序執行了兩次update操作,先是將questions的值更改為 {1,2,3},隨即第二個save()執行又將其改為了{1,2,4},兩次times都增加1,所以最終的結果時:
times questions
4 {1,2,4}

這時候如果使用者繼續提交 ‘questionid‘:3 ,則又變更為:
times questions
5 {1,2,3,4}

這是兩個並發的情況,會造成times比questions的數量多 1
如果類比10個並發呢?不想算了。

問題既然已經出現了,還是得解決啊,首先想到用innodb的行級鎖,很遺憾,表是myisam…

最終的解決方案是通過作業系統檔案獨佔鎖定實現的,螢幕前的朋友如果有興趣可以看:
http://my.oschina.net/cxz001/blog/281130

php當資料庫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.