2012-01-26 2 views
8

아파치 서버에 저장된 JSON 파일을 읽는 모바일 앱이 있습니다. GUI를 통해 무언가가 변경되면 해당 JSON 파일의 내용이 다시 생성됩니다 (PHP 스크립트 사용).아파치는 파일을 제공하기 전에 파일을 읽기 잠금합니까?

아파치에서 JSON 파일을 처리하는 도중에 JSON 파일을 덮어 쓰려고하면 문제가 발생할 수 있습니다.

아파치는 파일을 제공하기 전에 읽기 잠금을 얻습니까? 그렇지 않다면 서빙되는 동시에 쓰려고하면 어떻게됩니까?

+0

실제로 '실제'파일이 필요한가요? 아니면 그냥 내용을 출력하여 파일을 가짜로 만들 수 있습니까? – PeeHaa

답변

9

아니요. POSIX 호환 시스템에서 모든 잠금은 어쨌든 권고이므로 Apache가 읽기 잠금을 얻더라도 다른 프로세스는 파일을 쓸 수 있습니다. 따라서

[pid 7246] open("/var/www/file.json", O_RDONLY|O_CLOEXEC) = 11 
[pid 7246] fcntl(11, F_GETFD)   = 0x1 (flags FD_CLOEXEC) 
[pid 7246] mmap(NULL, 20, PROT_READ, MAP_SHARED, 11, 0) = 0x7f53f93da000 
[pid 7246] munmap(0x7f53f93da000, 20) = 0 
[pid 7246] writev(10, [{"HTTP/1.1 200 OK\r\nDate: Thu, 26 J"}, ...) = 365 
[pid 7246] close(11)     = 0 

, 당신의 JSON 파일이 부분적으로 만 기록되는 일이 발생할 수 있습니다

당신은 strace에 있음을 확인할 수 있습니다. 이 문제를 피하려면 JSON 파일을 동일한 파일 시스템의 임시 파일에 작성하고 rename이라는 원자를 사용하여 파일을 덮어 씁니다.

그런 식으로 open이 성공하면 apache는 이전 파일을 계속 제공합니다. open 전에 rename가 완료되면 apache는 완료된 새 파일을 가져옵니다.

일관성 문제 (정전 등)가있는 경우 JSON 파일을 닫기 전에 응용 프로그램에서 fsync으로 전화하여이 파일을 닫는 것이 좋습니다.

+0

PHP의 http://php.net/manual/en/function.flock.php를 사용하고 쓰기 락이있는 경우에는 괜찮습니까? – cdmckay

+0

@cdmckay 아니요. 쓰기 잠금은 아무 효과가 없습니다. 아파치가 읽기 잠금을 얻지 못하기 때문입니다. 나는 대답을 연장했다. 요컨대 : ['rename'] (http://php.net/rename)을 사용하십시오. – phihag

+0

호기심에서 벗어난 이유는 무엇입니까? 공연? – cdmckay

1

당신은 * nix 플랫폼에 대한 잘못된 패러다임을 생각하고 있습니다. 원하는 것은 스크립트에서 JSON 파일에 원자 파일을 쓰는 것입니다. 대상 디렉토리의 고유 한 임시 파일 이름에 파일을 작성한 다음 rename()을 사용하여이 파일을 이전 디렉토리로 옮깁니다. 파일 이동 작업은 원자 적입니다. 비동기 프로세스는 이전 JSON 파일 또는 새 파일을 열지 만 하이브리드는 열지 않습니다.

임시 파일 이름을 구성하는 방법은 다양합니다. tempnam()에 대한 PHP 설명서 사용자 의견을 참조하십시오. 내 시스템에서 요청 고유 ID를 생성하므로 기본으로 $_SERVER["UNIQUE_ID"]을 사용합니다.

관련 문제