2009-07-30 91 views
19

我有兩個不同的PHP文件,都寫入同一個文件。每個PHP腳本都由兩個不同HTML頁面的用戶操作調用。我知道可以調用兩個PHP文件,但是兩個PHP文件會同時嘗試寫入文件嗎?如果是的話,會發生什麼?另外,可以讓一個PHP正常失敗(文件寫入失敗,另一個PHP可以寫入文件),因爲一個PHP函數不如其他PHP函數重要。PHP同時文件寫入

回答

28

解決這個問題的通常方法是有兩個腳本使用flock()鎖定:

$f = fopen('some_file', 'a'); 
flock($f, LOCK_EX); 
fwrite($f, "some_line\n"); 
flock($f, LOCK_UN); 
fclose($f); 

這將導致腳本等待對方得到寫入之前對文件進行。如果你喜歡,在「不太重要」的腳本可以這樣做:

$f = fopen('some_file', 'a'); 
if(flock($f, LOCK_EX | LOCK_NB)) { 
    fwrite($f, "some_line\n"); 
    flock($f, LOCK_UN); 
} 
fclose($f); 

,這樣,如果它發現的東西是忙於文件就只是沒有做任何事情。

+0

正是我在找的東西!這很簡單,我應該更多地檢查PHP文檔。 – 2009-07-30 22:30:46

+0

小心使用flock(),因爲函數不是原子的。 – arul 2009-07-30 22:42:41

+0

另一個提示可以防止文件內容在兩次完全同時寫入時變空。一個帶有flatfile訪客計數器的熱門頁面發生在我身上。解決方案:我在fwrite()之前添加了一個20-80毫秒的隨機延遲,並且解決了問題,甚至到目前爲止訪問者數量還是很高。 – 2013-01-30 20:18:48

-4

FYI:涌向僅適用於* nix中,而不是在Windows上使用

+2

來自PHP文檔:「flock()允許你執行一個簡單的讀寫器模型,它幾乎可以在任何平臺上使用(包括大多數Unix衍生工具,甚至Windows)。」 – cdmckay 2009-07-31 00:45:25

+1

雖然'flock'作爲一個系統調用並沒有在Windows上實現,但它在'flock' PHP函數中被抽象出來。 – Piskvor 2010-12-15 17:25:37

+1

是的,我說錯了。這是當我說Windows在不可用時我正在考慮的錯誤:http://bugs.php.net/bug.php?id = 39138(我需要它在Windows本地開發服務器上的時間,我遇到過這種情況,並從此避免在Windows機器上使用它)。保持冷靜並進行。 – xentek 2011-01-09 05:08:10

9

請注意:

由於PHP 5.3.2,自動解鎖當文件的資源句柄被關閉移除。 解鎖現在總是需要手動完成。

更新的向後兼容的代碼是:

if (($fp = fopen('locked_file', 'ab')) !== FALSE) { 
    if (flock($fp, LOCK_EX) === TRUE) { 
     fwrite($fp, "Write something here\n"); 
     flock($fp, LOCK_UN); 
    } 

    fclose($fp); 
} 

即你要調用的羊羣(..,LOCK_UN)明確,因爲FCLOSE()不這樣做了。

11

請注意如果文件打開爲附加,posix聲明原子訪問。這意味着你可以用多個線程追加到文件中,它們的行不會被破壞。

我用十幾個線程和幾十萬行測試了這個。沒有一條線被破壞。

這可能不適用於大於1kB的字符串,因爲緩衝區大小可能會超過。

這可能也不適用於不符合posix的窗口。