作者roga (任性)
看板PHP
標題Re: [請益] 同時寫入資料庫的問題
時間Fri Mar 25 12:33:01 2011
※ 引述《sunz5010 (FoFo)》之銘言:
: : 以上是先拿出庫存再來算數量,但是您要考慮 innodb_lock_wait_timeout ,
: : 這個預設是 50 秒,等起來有點久。或是考慮另一種作法,不要 select 直接計算
: : $sth = $dbh->prepare("UPDATE scart SET qty = qty - :qty
: : WHERE id = :id and qty - :qty > 0");
: : $sth->execute(array(':qty'=>$qty, ':id'=>$id));
補充一下,如果是一次購買多件商品,這邊可以
$dbh->beginTransaction();
每執一行 update 敘述之後,拿 rowCount() 來看
$sth = $dbh->prepare("UPDATE scart SET qty = qty - :qty
WHERE id = :id and qty - :qty >= 0");
$sth->rowCount();
foreach($productIdList as $pid)
{
$sth->execute(array(':qty' => $qty, ':id' => $pid));
if($sth->rowCount() == 0)
{
// 簡化一點,在途中有遇到 rowCount 回傳是 0 就直接 rollback
throw new Exception('update error.');
}
}
$dbh->commit();
然後 PDO 自己 commit failed 也會 throw exception
所以只要在外層 catch exception 然後 $dbh->rollback() 即可。
流程控制大概是這樣。
: : 然後 update 失敗就代表庫存不夠,叫使用者重新回頁面購買。
: 謝謝你的分享、我也順便分享一下我的作法
: 我原本的問題是
: 「倉庫」:1顆蘋果
: 「甲」=>想買蘋果
: 「乙」=>想買蘋果
: 而買蘋果的機制如為(1)先檢查有沒有蘋果 (2)有的話就買
: 但要讓整個機制都在Critical Secion底下、就需要一個lock
: 觀念是
: 「Lock資源」=>籃子
: 機制是=>誰先搶到「籃子」、就能購買
: if(籃子)
: {
: (1)檢查有沒有蘋果
: (2)有的話就買
: }
: else //拿不到籃子的情況
: {
: 等待拿籃子、並且嘗試拿取
: }
: 讓我困擾的是、要製作這個Lock資源、必須要有一個具有實現lock功能的工具
: 於是我想到了MySQL的Primary Key
: 我的作法是、創造一個「MyLock」的Table
: 裡面可以有很多資訊、但主要的就是要有一個LockName這個PrimaryKey
: (我這個Table其實也只放了這一個欄位)
: 所以作法如下:
: /*****Start*****/
: //買東西之前
: reslut = MySQL(insert into MyLock (LockName) value ("籃子"))
: while(result=>ErrorCode == 1062) //1062:重複的PK
: {
: //有人拿了籃子、等待一秒、之後嘗試拿籃子
: sleep(1); //先等待一個時間
: result = MySQL(insert into MyLock (LockName) vlaue ("籃子");
: }
: //Critical Secion [Start]
: (1)檢查倉庫有沒有蘋果
: (2)有的話就買
: //Critical Secion [End]
: MySQL(delete from MyLock where LockName = '籃子') //釋放籃子資源
: /*******End*******/
: 這個方式挺容易的
: 而且沒有複雜的MySQL判斷跟指令
: 另外跟原本的lock 觀念也一致
: 分享給大家@@、如果我的方法有什麼問題也歡迎討論
一個購物車,要考慮同時購買蘋果香蕉橘子柳丁,以及所有水果的庫存。
然後大家應該要都可以同時買東西,看來照你的作法,看來一次只能有一個人買。
如果同時三個人買,就算庫存足夠,也得等 (是嗎?)
--
The Internet: where men are men, women are men, and children are FBI agents.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 202.89.121.16
推 sunz5010:疑、你說的對ㄝ~我是沒有考慮到你這個問題 03/25 12:48
→ sunz5010:不過我想、這也是可以在Critical Section那邊去抉擇 03/25 12:48
→ sunz5010:決定一次處理多少的量、不過這個問題或許也牽扯到服務 03/25 12:49
→ sunz5010:等待的問題、我在想這個或許是另外一個議題 03/25 12:50
→ sunz5010:因為LOCK是一個觀念、至於你要怎麼運用這個LOCK 03/25 12:50
→ sunz5010:也要看你演算法怎麼設計、不過你點醒了我沒注意到的地方 03/25 12:51
→ sunz5010:還謝謝你的提醒@@ 03/25 12:51
※ 編輯: roga 來自: 202.89.121.16 (03/25 16:00)