2011-04-05 87 views
0

我正在使用一個python服務器,它同時處理多個數據庫上的事務,每個數據庫存儲有關不同應用程序的性能數據。併發是通過多處理模塊完成的,因此每個事務線程都在一個新進程中啓動,並且共享內存數據保護機制不可行。 我使用sqlite作爲我的數據庫管理系統,並已選擇在其自己的文件中設置每個應用程序的數據庫。不幸的是,這引發了數據庫創建的競爭條件;如果兩個進程嘗試同時爲同一個新應用程序創建一個數據庫,則兩者都將創建要存儲數據庫的文件。我的研究讓我相信,在創建文件之前無法鎖定文件;有沒有其他一些機制可以用來確保文件沒有被創建,然後同時寫入?防止在python中創建文件

由於提前,以這樣的方式,他們保證不會碰撞 大衛

+0

也許我誤解了,但不能只是重命名每個數據庫的文件位置? – dfb 2011-04-05 23:16:33

回答

1

通常的Unix風格的處理常規文件的方法是試圖創建文件並查看它是否失敗。在Python的情況下,這將是:

try: 
    os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_EXCL) 
except IOError: # or OSError? 
    # Someone else created it already. 

最起碼,你可以用這個方法來嘗試創建一個「鎖定文件」具有類似名稱的數據庫。如果創建了鎖定文件,則繼續製作數據庫。如果沒有,你可以爲「數據庫存在」情況做任何你需要的事情。

0

試圖在代碼中創建,並在您的異常處理程序中的文件,檢查文件是否存在,而不是使用它創建現有的文件時,您可以捕獲錯誤。

0

你沒有提到這個平臺,但是在linux上的open()os.open()在python中,需要一個你可以使用的flags參數。 O_CREAT標誌創建一個文件,如果該文件不存在,並且O_EXCL標誌給出錯誤(如果該文件已存在)。您還需要指定訪問模式O_RDONLY,O_WRONLYO_RDWR。您可以在os模塊中找到這些常量。

例如:fd = os.open(filename, os.O_RDWR | os.O_CREAT | os.O_EXCL)

0

您可以使用POSIX O_EXCL and O_CREAT flags to open(2)以保證只有一個單一的過程中獲取文件,因此數據庫; O_EXCL將無法​​通過NFSv2或更早的版本,並且將其用於其他網絡文件系統依然不穩定。

liblockfile庫實現了open(2)聯機幫助頁中描述的網絡文件系統安全鎖定機制,這很方便;但我只看到預先製作的Ruby和Perl綁定。根據您的需要,也許提供Python綁定將是有用的,或者可能只是重新實現算法:

O_EXCL Ensure that this call creates the file: if this flag is 
      specified in conjunction with O_CREAT, and pathname 
      already exists, then open() will fail. The behavior of 
      O_EXCL is undefined if O_CREAT is not specified. 

      When these two flags are specified, symbolic links are not 
      followed: if pathname is a symbolic link, then open() 
      fails regardless of where the symbolic link points to. 

      O_EXCL is only supported on NFS when using NFSv3 or later 
      on kernel 2.6 or later. In environments where NFS O_EXCL 
      support is not provided, programs that rely on it for 
      performing locking tasks will contain a race condition. 
      Portable programs that want to perform atomic file locking 
      using a lockfile, and need to avoid reliance on NFS 
      support for O_EXCL, can create a unique file on the same 
      file system (e.g., incorporating hostname and PID), and 
      use link(2) to make a link to the lockfile. If link(2) 
      returns 0, the lock is successful. Otherwise, use stat(2) 
      on the unique file to check if its link count has 
      increased to 2, in which case the lock is also successful.