2009-07-30 34 views
19

Tôi có hai tệp PHP khác nhau mà cả hai đều ghi vào cùng một tệp. Mỗi tập lệnh PHP được gọi bởi một hành động người dùng của hai trang HTML khác nhau. Tôi biết nó sẽ có thể cho hai tập tin PHP được gọi, nhưng cả hai tập tin PHP sẽ cố gắng ghi vào tập tin cùng một lúc? Nếu có, điều gì sẽ xảy ra? Ngoài ra, nó có thể làm cho một trong những PHP thất bại một cách duyên dáng (ghi tập tin sẽ chỉ thất bại, và PHP khác có thể ghi vào tệp) vì một hàm PHP ít quan trọng hơn đối với hàm kia.PHP Viết đồng thời

Trả lời

28

Cách thông thường của việc giải quyết này là phải có cả hai kịch bản sử dụng flock() cho khóa:

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

Điều này sẽ gây ra các kịch bản để chờ đợi nhau để có được thực hiện với các tập tin trước khi viết nó. Nếu bạn muốn, tập lệnh "ít quan trọng" hơn có thể thực hiện:

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

để nó sẽ không làm gì nếu thấy có gì đó đang bận.

+0

Chính xác những gì tôi đang tìm kiếm! Điều đó thật dễ dàng, tôi nên kiểm tra tài liệu PHP nhiều hơn. –

+0

Cẩn thận khi sử dụng đàn() vì hàm không phải là nguyên tử. – arul

+0

Một mẹo khác để ngăn nội dung tập tin bị trống trên hai lần ghi chính xác đồng thời. Điều đó đã xảy ra với tôi rất nhiều với một trang phổ biến với một truy cập flatfile truy cập. Giải pháp: Tôi đã thêm một độ trễ ngẫu nhiên 20-80 ms trước fwrite() và điều đó đã khắc phục được sự cố, kể cả cho đến nay với số lượng khách truy cập cao hơn nhiều. –

-4

FYI: đổ xô chỉ hoạt động trên * nix và không có sẵn trên Windows

+2

Từ tài liệu PHP: "flock() cho phép bạn thực hiện một mô hình trình đọc/ghi đơn giản có thể được sử dụng trên hầu hết mọi nền tảng (bao gồm hầu hết các dẫn xuất Unix và thậm chí cả Windows)." – cdmckay

+1

Trong khi 'flock' như một lời gọi hệ thống không được thực hiện trên Windows, điều này được trừu tượng hóa trong hàm' flock' PHP. – Piskvor

+1

vâng, tôi đã nói sai. Đây là lỗi tôi đã nghĩ đến khi tôi nói rằng không có sẵn trên Windows: http://bugs.php.net/bug.php?id = 39138 (thời gian tôi cần nó trên một cửa sổ máy chủ dev địa phương, tôi chạy vào này và đã tránh nó trên Windows máy kể từ đó). Giữ bình tĩnh và tiếp tục. – xentek

9

Xin lưu ý:

Tính đến PHP 5.3.2, việc bẻ khóa tự động khi xử lý tài nguyên của tập tin được đóng đã được gỡ bỏ . Mở khóa ngay bây giờ luôn phải được thực hiện thủ công.

được cập nhật mã tương thích ngược là:

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); 
} 

ví dụ: bạn phải gọi bầy (.., LOCK_UN) một cách rõ ràng bởi vì fclose() không làm điều đó nữa.

11

Xin lưu ý posix cho biết truy cập nguyên tử nếu tệp được mở dưới dạng nối thêm. Điều này có nghĩa là bạn chỉ có thể nối thêm vào tệp với một số luồng và các dòng đó sẽ không bị hỏng.

Tôi đã thử nghiệm điều này với hàng tá chủ đề và vài trăm nghìn dòng. Không có dòng nào bị hỏng.

Điều này có thể không hoạt động với chuỗi trên 1kB khi bộ đệm có thể vượt quá.

Điều này cũng có thể không hoạt động trên các cửa sổ không tuân thủ posix.