PHP檔案讀寫鎖的問題詳解

pythontab發表於2014-06-20

讀寫相關的問題是永遠存在的,檔案鎖就是為了解決這個問題而做的,其實它就是個簡單的訊號量。讀寫相關性指由於同時讀寫檔案造成檔案資料的隨機性衝突。為了明確知道在何時透過何種操作對更改或是讀取了檔案中的那些資料,有必要對操作進行序列化,原子化,同步化,使使用者能確知在何時檔案中有什麼資料。檔案鎖就是其中一個工具。

檔案系統一般有兩種鎖,共享鎖及排它鎖,也可被稱為讀鎖和寫鎖。

檔案系統鎖的特點:

一個檔案開啟的時候只能擁有一把鎖,就是說在同時,不能給一個檔案同時分配兩把以上的鎖。

讀寫已被上鎖的檔案的使用者可以持有這把鎖,即持有這把鎖的使用者可以對該檔案進行相應的操作,如讀或寫。使用者可以申請持有某個檔案鎖,如果檔案開始無鎖,申請持有鎖之前先由系統為該檔案建立了一把鎖,然後該申請者持有它。

持有鎖的規則:如果這個檔案已擁有一個讀(共享)鎖,其它使用者不能為該檔案分配排它鎖或只讀鎖,但可以持有這把鎖,也就是說其它使用者可以讀檔案,但只要該檔案被鎖住,就沒有使用者可以對其進行寫入。如果該檔案已有一把排它鎖且已為某使用者持有,則沒有任何使用者可以再持有這把鎖,除非持有者解鎖。

有一個重要的概念要記住:對檔案的操作本身與鎖其實沒有什麼關係,無論檔案是否被上鎖,使用者都可以隨意對檔案進行正常情況下的任何操作,但作業系統會檢查鎖,針對不同的情況給予不同的處理。比如說在無鎖的情況下,任何人可以同時對某檔案進行任意的讀寫,當然這樣很有可能讀寫的內容會出現錯誤——注意只是內容出錯,操作並不會出錯。加鎖後,某些操作在某些情況下會被拒絕。檔案鎖的作用並不是保護檔案及資料本身,而是保證資料的同步性,因此檔案鎖只對持有鎖的使用者才是真正有效的,也只有所有使用者都使用同一種完全相同的方式利用檔案鎖的限制對檔案進行操作,檔案鎖才能對所有使用者有效,否則,只要有一個例外,整個檔案鎖的功能就會被破壞。比如,所有人都遵循的開檔案,加鎖,操作讀寫,解鎖,關閉檔案的步驟的話,所有的人操作都不會出現問題,因為基於檔案鎖的分配及持有原則,檔案中的資料的更新是作為原子操作存在的,是不可分的,因此也是同步的,安全的。但假如某個人不是採取此步驟,那麼他在讀寫時就會出現問題,不是讀不準就是寫不進等等。

基於以上原理,對讀資料是否鎖定這點就值得說說。一般來說,寫資料的時候排它鎖定是唯一的操作,它這時保證寫到檔案中的資料是正確的,檔案被鎖時,其它使用者無法得到該鎖,因此無權做任何操作。在讀的時候,要視具體情況而定,大多數情況下,如果不需要特別精確或是敏感的資料,無需鎖定,因為鎖定要花時間和資源,一個人申請持有鎖花不了時間,人一多就有問題了,最主要的是,如果該檔案需要被更新的話,假如被上了只讀鎖,則寫入無法進行,因為那些想寫入的使用者將得不到排它鎖,如果同時申請持有隻讀鎖的人過多的話,排它鎖就有可能一直申請不到,這樣表現就是檔案可能很長時間內無法被寫入,顯得很慢。一般來說,寫檔案的機會相對較少,也更重要,因此主要做好排它鎖定,只讀鎖在多數情況下並無必要。那麼只讀鎖用在何處呢?只讀鎖其實只對使用者本身有用,只讀鎖保證使用者讀到的資料是確實從檔案中讀到的真實資料,而不是被稱為“dirty”的髒資料。其實,這個還是針對那些不用鎖的其它使用者對檔案的誤操作,假如檔案上鎖,其它使用者不一定非要透過鎖對檔案進行讀寫,如果他是直接讀寫的話,對上了鎖的檔案操作不一定有效,持有讀鎖的使用者可以肯定在他讀資料的時候讀出來的是從真實的檔案中得到的,而不是同時已被覆蓋掉的資料。

因此,在寫入的時候上排它鎖應該是天經地義的,可以保證這時資料的不會出錯。如果你不申請共享鎖,可能讀出的資料有錯誤,但對檔案本身沒有任何影響,影響只是對使用者的,申請共享鎖後讀出的資料肯定是當時讀的時候檔案中的真實資料,如果不是為了保證資料的精確性,共享鎖可以不加,充其量就是重新讀一次,如果你讀它是為了寫入,不如直接加排它鎖,沒有必要用共享鎖。

還有一點要強調的是:檔案鎖只對使用它的使用者,而且是按規則使用它的使用者才有效,否則,你用你的,我用我的,有的用,有的不用,還是會亂套的,錯誤還是會出現的,對同一個檔案,只有大家用同一個規則用檔案鎖,才能保證每個使用者在對該檔案進行共享操作的時候不會出現讀寫錯誤。


相關文章