Tôi đã sử dụng SQLite trong một thời gian và đã có "tài sản" đối phó với một số vấn đề về khóa. Tôi khá chắc chắn rằng SQLite sử dụng ổ khóa phạm vi byte trên hệ thống tập tin Unix theo mặc định.
Để chính xác hơn, nó chứa mã cho một vài phương pháp khóa thay thế (ví dụ: sử dụng flock()
và dotlock-style khóa toàn bộ tệp). Khi biên dịch với SQLITE_ENABLE_LOCKING_STYLE
option nó cố gắng tự động phát hiện các phương pháp khóa thích hợp cho hệ thống tập tin cơ bản.
Mã phát hiện tự động chứa một số trường hợp được mã hóa cứng (ví dụ: "ufs", "nfs" và "smbfs"), không có mã nào trong số đó là AFS. Nếu không có trường hợp được mã hóa cứng nào, SQLite cố gắng lấy khóa bằng byte trên một tệp bằng cách sử dụng fcntl()
. Sau đó nó giả định rằng nếu cuộc gọi fcntl()
thành công, thì các khóa phạm vi byte có sẵn.
Đây là nơi OpenAFS đến để làm mọi thứ thú vị. Rõ ràng ([1], [2], [3]) OpenAFS có lịch sử dài nằm trong các ứng dụng không gian người dùng về khóa phạm vi byte. Từ mã số openafs-1.4.14
:
/* next line makes byte range locks always succeed,
* even when they should block */
if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
DoLockWarning();
afs_PutFakeStat(&fakestate);
return 0;
}
Trong một từ: Ouch!
Điều này cho phép khóa ổ byte thành công cho dù thành công. Trên Linux, nó thậm chí còn tệ hơn nữa: nó sử dụng cơ sở hạ tầng hạt nhân để cung cấp các khóa phạm vi byte trong số các quá trình của cùng một hệ thống. Điều đó có nghĩa là một ứng dụng không thể chỉ nĩa một quy trình mới và kiểm tra cơ chế khóa - các khóa byte-byte sẽ xuất hiện để làm việc tốt, trong khi không khủng khiếp để bảo vệ một tập tin từ các quá trình từ xa.
Tóm lại: bạn không thể sử dụng SQLite chưa sửa đổi một cách đáng tin cậy với OpenAFS. Hầu hết các hệ thống tập tin mạng khác cũng có vấn đề, do đó khuyến nghị tránh hoàn toàn hệ thống tập tin mạng.
Một vài quyết có thể có không theo thứ tự đặc biệt:
Sử dụng một DBMS thích hợp, chẳng hạn như PostgreSQL. Nếu có thể làm điều này, bạn sẽ tốt hơn trong thời gian dài.
Triển khai máy chủ của riêng bạn cho ứng dụng của bạn, nếu DBMS đầy đủ là quá mức cần thiết.
Sửa đổi mã nguồn SQLite thành mặc định thành flock()
trên OpenAFS. Tôi không chắc chắn nếu điều này sẽ làm việc đúng, kể từ khi OpenAFS có một lịch sử lâu dài ([1], [2]) của các vấn đề khóa ngay cả với đồng bằng cũ flock()
, nhưng bạn sẽ không biết cho đến khi bạn kiểm tra nó.
Triển khai OpenAFS VFS của riêng bạn cho SQLite, sử dụng vùng người dùng OpenAFS, thay vì trải qua nhân.
Hãy thử vận may của bạn với một hệ thống tệp mạng khác.
Dù bạn làm gì, bạn sẽ phải thực hiện thử nghiệm rộng rãi nếu có liên quan đến SQLite3 và tệp cơ sở dữ liệu được chia sẻ.
CHỈNH SỬA:
Người nhận xét đề xuất sử dụng cơ chế tệp dotlock. Tôi đã không đi sâu vào mã nguồn OpenAFS quá nhiều, nhưng thoạt nhìn nó xuất hiện để hỗ trợ phương thức tạo các tệp dotlock mà SQLite sử dụng phương thức open(O_CREAT|O_EXCL)
. Nếu nó hoạt động như nó được cho là, thì SQLite thực sự có thể sử dụng được với OpenAFS nếu bạn buộc nó sử dụng phương thức dotlock.
Điều đó nói rằng, dấu chấm phẩy là đủ của một vấn đề trên hệ thống tập tin cục bộ thông thường, mà không giới thiệu sự phức tạp của hệ thống tập tin mạng vào hỗn hợp - đó là lý do tại sao tôi không đề xuất nó ở nơi đầu tiên.
+1 Rất tiếc. Tuy nhiên, sẽ không dotlocks làm việc, giả định rằng AFS cung cấp tạo file nguyên tử? – janneb
@janneb: Tôi đã kiểm tra nguồn OpenAFS w.r.t. dotlocks. Các kết quả đã được khuyến khích - hoặc khuyến khích như bất cứ điều gì liên quan đến dotlocks có thể được. – thkala