PHP出現檔案鎖與mysql表鎖有大概想的用法,就是同一時間只能讓一個人操作,這樣就避免了同時有多個人操作同一檔案,這樣導致資料丟失的情況了,下面我來給大家介紹PHP檔案鎖用法。
PHP內建了檔案鎖函數:
bool flock ( int $handle , int $operation [, int &$wouldblock ] )
$handle 是開啟的檔案指標;
$operation 可以是
“LOCK_SH”,共用鎖定定;“LOCK_EX”,獨佔鎖定;“LOCK_UN”,釋放鎖定;“LOCK_NB”,防止flock鎖定時堵塞。
這裡主要說說“LOCK_EX”和“LOCK_NB”。
比如我們有兩個檔案,如下。
flocka.php
| 代碼如下 |
複製代碼 |
$file = 'temp.txt'; $fp = fopen($file,'a'); for($i = 0;$i < 5;$i++) { fwrite($fp, "11111111n"); sleep(1); } fclose($fp); |
flockb.php
| 代碼如下 |
複製代碼 |
$file = 'temp.txt'; $fp = fopen($file,'a'); for($i = 0;$i < 5;$i++) { fwrite($fp, "22222222n"); } fclose($fp);
|
先運行flocka.php,然後馬上運行flockb.php。
結果:
11111111
22222222
22222222
22222222
22222222
22222222
11111111
11111111
11111111
11111111
說明不加檔案鎖時,兩個檔案會同時對txt檔案進行寫入操作。
下面修改一下兩個php檔案的代碼。
flocka.php
| 代碼如下 |
複製代碼 |
$file = 'temp.txt'; $fp = fopen($file,'a'); if(flock($fp,LOCK_EX)) { for($i = 0;$i < 5;$i++) { fwrite($fp, "11111111n"); sleep(1); } flock($fp,LOCK_UN); } fclose($fp);
|
flockb.php
| 代碼如下 |
複製代碼 |
$file = 'temp.txt'; $fp = fopen($file,'a'); if(flock($fp,LOCK_EX)) { for($i = 0;$i < 5;$i++) { fwrite($fp, "22222222n"); } flock($fp,LOCK_UN); } fclose($fp);
|
同樣先運行flocka.php,然後馬上運行flockb.php。
會發現在flocka.php運行結束前,flockb.php一直處於等待狀態,只有當flocka.php運行結束後,flockb.php才會繼續執行。
輸出結果:
11111111
11111111
11111111
11111111
11111111
22222222
22222222
22222222
22222222
22222222
另外,在執行flock時,檔案鎖會自動釋放。
還有一種辦法
如下代碼簡單類比了這種事務並髮狀態: process1.php
| 代碼如下 |
複製代碼 |
$num = 100; $filename = "processdata.txt"; $fp = fopen($filename, "a"); for ($i = 0; $i < $num; $i++) { fwrite($fp, "process1: " . $i . "rn"); usleep(100000); } fclose($fp); ?> |
我們需要先執行第一個事務,在processdata.txt檔案中寫入這100行。
process2.php
| 代碼如下 |
複製代碼 |
$num = 100; $filename = "processdata.txt"; $fp = fopen($filename, "a"); for ($i = 0; $i < $num; $i++) { fwrite($fp, "process2: " . $i . "rn"); usleep(100000); } fclose($fp); ?> |
第二個事務,繼續向processdata.txt檔案中寫入100行。
第二個事務,繼續向processdata.txt檔案中寫入100行。
多次同時執行,雖然都寫了100行,但是事務1和事務2的資料交錯寫入,這並不是我們想要的結果。我們要的是事務完整的執行,此時我們需要有個機制去保證在第一個事務執行完後再執行第二個。在PHP中,flock函數完成了這一使命。在事物1和事務2的迴圈前面都加上: flock($fp, LOCK_EX); 就能滿足我們的需求,將兩個事務串列。
當某一個事務執行完flock時,因為我們在這裡添加的是LOCK_EX(獨佔鎖定),所以所有對資源的操作都會被阻塞,只有當事務執行完成後,後面的事務才會執行。我們可以通過輸出當前的時間的方法來確認這一點。
關於在尾部追加寫入,在unix系統的早期版本中存在一個並發寫入的問題,如果要在尾部追加,需要先lseek位置,再write。當多個進程同時操作時,會因為並發導致的覆蓋寫入的問題,即兩個進程同時擷取尾部的位移後,先後執行write操作,後面的操作會將前面的操作覆蓋。這個問題在後面以添加開啟時的O_APPEND操作而得到解決,它將尋找和寫入操作變成了一個原子操作。
在PHP的fopen函數的實現中,如果我們使用a參數在檔案的尾部追加內容,其調用open函數中oflag參數為 O_CREAT|O_APPEND,即我們使用追加操作不用擔心並發追加寫入的問題。
在PHP的session預設儲存實現中也用到了flock檔案鎖,當session開始時就調用PS_READ_FUNC,且以O_CREAT | O_RDWR | O_BINARY 開啟session資料檔案,此時會調用flock加上寫鎖,如果此時有其它進程訪問此檔案(即同一使用者再次發起對當前檔案的請求),就會顯示頁面載入中,進程被阻塞了。加寫鎖其出發點是為了保證此次會話中對session的操作事務能完整的執行,防止其它進程的幹擾,保證資料的一致性。如果一個頁面沒有session修改操作,可以儘早的調用session_write_close()釋放鎖。
檔案鎖是針對檔案的鎖,除了這種釋義,還可以理解為用檔案作為鎖。在實際工作中,有時為確保單個進程的執行,我們會在程式執行前判斷檔案是否存在,如果不存在則建立一個空檔案,在進程結束後刪除這個空檔案,如果存在,則不執行。
http://www.bkjia.com/PHPjc/628753.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/628753.htmlTechArticlePHP出現檔案鎖與mysql表鎖有大概想的用法,就是同一時間只能讓一個人操作,這樣就避免了同時有多個人操作同一檔案,這樣導致資料丟失的...