php如何解决并发问题,PHP如何解决并发问题
PHP如何解決并發(fā)問(wèn)題
有個(gè)問(wèn)題:
一個(gè)進(jìn)程開啟事務(wù)對(duì)表的某一行做了修改,但還沒(méi)有提交,另一個(gè)進(jìn)程查詢?cè)撔袛?shù)據(jù),獲取到的是原始的,這時(shí)候上面的事物提交了,我再用這個(gè)原始數(shù)據(jù)的時(shí)候就有問(wèn)題……
那我們?cè)撛趺唇鉀Q這個(gè)問(wèn)題呢?
1、文件鎖
如果對(duì)該表的更新或插入只有一個(gè)文件,這種方式是可以解決的
實(shí)現(xiàn)方式如下:
public static functioncbInventoryReserve() {$LOCK_FILE_PATH = $_SERVER[‘DOCUMENT_ROOT‘]."wmsinventoryapi/inventory/InventoryReserve.php";$fp = fopen( $LOCK_FILE_PATH, "r");if (!$fp) {die("Failed to open the lock file!");
}flock ( $fp,LOCK_EX );//需要進(jìn)行的操作
$params = Flight::request()->getBody();$params = json_decode($params, true);if (! is_array($params) || empty($params)) {
Flight::sendRouteResult(array("error_code" => "40002","error_info" => "params empty"));
}$result = \Inventory\InventoryEngine::getInstance()->inventoryReserve($params);flock ( $fp,LOCK_UN );fclose ( $fp);
Flight::sendRouteResult($result);
}
函數(shù)說(shuō)明??flock()會(huì)依參數(shù)operation所指定的方式對(duì)參數(shù)fd所指的文件做各種鎖定或解除鎖定的動(dòng)作。此函數(shù)只能鎖定整個(gè)文件,無(wú)法鎖定文件的某一區(qū)域。
參數(shù)??operation有下列四種情況:
LOCK_SH 建立共享鎖定。多個(gè)進(jìn)程可同時(shí)對(duì)同一個(gè)文件作共享鎖定。
LOCK_EX 建立互斥鎖定。一個(gè)文件同時(shí)只有一個(gè)互斥鎖定。
LOCK_UN 解除文件鎖定狀態(tài)。
LOCK_NB 無(wú)法建立鎖定時(shí),此操作可不被阻斷,馬上返回進(jìn)程。通常與LOCK_SH或LOCK_EX 做OR(|)組合。
單一文件無(wú)法同時(shí)建立共享鎖定和互斥鎖定,而當(dāng)使用dup()或fork()時(shí)文件描述詞不會(huì)繼承此種鎖定。
返回值??返回0表示成功,若有錯(cuò)誤則返回-1,錯(cuò)誤代碼存于errno。
換言之:
使用共享鎖LOCK_SH,如果是讀取,不需要等待,但如果是寫入,需要等待讀取完成。
使用獨(dú)占鎖LOCK_EX,無(wú)論寫入/讀取都需要等待。
LOCK_UN,無(wú)論使用共享/讀占鎖,使用完后需要解鎖。
LOCK_NB,當(dāng)被鎖定時(shí),不阻塞,而是提示鎖定。
為了更好的移植性,對(duì)于文件的打開與關(guān)閉我選擇了fopen和fclose的組合,但flock的第一個(gè)參數(shù)要求的是int類型的文件描述符。這里對(duì)fopen返回的FILE類型的文件指針進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換為int型的文件描述符 (假設(shè)open函數(shù)返回的文件描述符為fd,而fopen返回的文件指針為*fp,則fd等價(jià)于fp->_fileno).
2、序列化接口(對(duì)象序列化)
所有php里面的值都可以使用函數(shù)serialize()來(lái)返回一個(gè)包含字節(jié)流的字符串來(lái)表示。unserialize()函數(shù)能夠重新把字符串變回php原來(lái)的值。 序列化一個(gè)對(duì)象將會(huì)保存對(duì)象的所有變量,但是不會(huì)保存對(duì)象的方法,只會(huì)保存類的名字。
classA {public $one = 1;public functionshow_one() {echo $this->one;
}
}//page1.php:
include("classa.inc");$a = newA;$s = serialize($a);//把變量$s保存起來(lái)以便文件page2.php能夠讀到
file_put_contents(‘store‘, $s);//page2.php:
// 要正確了解序列化,必須包含下面一個(gè)文件
include("classa.inc");$s = file_get_contents(‘store‘);$a = unserialize($s);//現(xiàn)在可以使用對(duì)象$a里面的函數(shù) show_one()
$a->show_one();?>
3、select *** for update
Select …forupdate語(yǔ)句是我們經(jīng)常使用手工加鎖語(yǔ)句。通常情況下,select語(yǔ)句是不會(huì)對(duì)數(shù)據(jù)加鎖,妨礙影響其他的DML和DDL操作。同時(shí),在多版本一致讀機(jī)制的支持下,select語(yǔ)句也不會(huì)被其他類型語(yǔ)句所阻礙。
借助for update子句,我們可以在應(yīng)用程序的層面手工實(shí)現(xiàn)數(shù)據(jù)加鎖保護(hù)操作。
for update子句的默認(rèn)行為就是自動(dòng)啟動(dòng)一個(gè)事務(wù),借助事務(wù)的鎖機(jī)制將數(shù)據(jù)進(jìn)行鎖定。
開啟一個(gè)事務(wù)使用for update
start transaction;
select sum(quantity) from ws_inventory_item where inventory_item_id=86 for update;
再開啟另一個(gè)事務(wù)時(shí),做update 操作的時(shí),只能等待上面的事務(wù),commit才能執(zhí)行;
start transaction;update ws_inventory_item set quantity = quantity + 1 where inventory_item_id = 86;
原文:http://www.cnblogs.com/sdgf/p/5740998.html
總結(jié)
以上是生活随笔為你收集整理的php如何解决并发问题,PHP如何解决并发问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SpaceX 明早将发射久违的重型猎鹰火
- 下一篇: alchemy php,Flask SQ