2010-11-04 37 views
6

Tôi có ứng dụng đa luồng sử dụng sqlite (3.7.3)Tránh cơ sở dữ liệu sqlite3 bị khóa

Tôi đang gặp lỗi khóa cơ sở dữ liệu có vẻ khá phổ biến. Tôi tự hỏi làm thế nào để tránh nó trong trường hợp của tôi.

Hãy để tôi mô tả những gì tôi đang xây dựng. Xin lỗi, không có mã nào quá lớn và phức tạp.

Tôi có khoảng 8 chủ đề đồng thời truy cập cơ sở dữ liệu. Bất kỳ một trong những chủ đề có thể đọc hoặc viết cùng một lúc.

Mỗi hàng trong một bảng trong cơ sở dữ liệu có đường dẫn tệp trỏ đến một tài nguyên + thuộc tính khác có liên quan đến tài nguyên đó.

3 trường ghi chú là người đọc, trạng thái và del.

Độc giả được tăng lên mỗi lần một sợi đọc từ tài nguyên, nhưng chỉ khi tình trạng> 0 và del = 0.

Vì vậy, tôi có một số SQL mà không

UPDATE resource set readers=readers+1 where id=? AND del=0 AND status>0 

Sau đó, tôi kiểm tra số lượng hàng được cập nhật. Nó chỉ nên là 1. Sau đó tôi cố gắng đọc hàng trở lại với một lựa chọn. Tôi làm điều đó ngay cả khi nó không thành công để cập nhật vì tôi cần biết lý do không thành công.

Tôi đã thử gói cả bản cập nhật và chọn trong giao dịch nhưng điều đó không có tác dụng. Tôi đã kiểm tra rằng tôi cũng đang gọi hoàn tất các tuyên bố của mình.

Bây giờ, tôi nghĩ rằng sqlite sẽ tuần tự hóa theo mặc định. Tôi đã thử một vài chế độ mở nhưng tôi vẫn gặp lỗi tương tự.

Và trước khi bạn hỏi, tôi không có ý định truy cập mysql. Tôi hoàn toàn không cần cấu hình.

Ai đó có thể cung cấp một số gợi ý về cách tránh loại vấn đề này không? Tôi có nên di chuyển khóa của người đọc ra khỏi DB không? Nếu tôi làm điều đó, tôi nên thay thế nó bằng cơ chế nào? Tôi đang sử dụng Linux theo C++ và với thư viện tăng sẵn.

EDIT: Điều thú vị là thêm COMMIT sau khi cuộc gọi cập nhật của tôi được cải thiện đáng kể.

+1

Cam kết thường xuyên hơn cho phép khóa chi tiết hơn trên tệp cơ sở dữ liệu, điều này sẽ làm giảm thời gian người đọc dành để chờ mở khóa bảng. Điều này xuất phát từ việc tăng chi phí tập tin nhật ký. Xem http://sqlite.org/lockingv3.html#writing để biết thêm thông tin. – checker

Trả lời

1

Khi bạn mở db, bạn nên cấu hình 'thời gian chờ bận rộn'

int sqlite3_busy_timeout(sqlite3*, int ms); 

http://www.sqlite.org/c3ref/busy_timeout.html

+2

Xin chào, vâng tôi đã thử điều đó. Nó giúp một chút. Nhưng ngay cả khi đặt nó cao tới 1 giây, nó vẫn chạy vào vấn đề khóa. Tôi đã bật chế độ shared_cache và điều đó dường như giúp ích nhiều hơn thời gian chờ bận. Tôi sẽ thử cả hai. – Matt

+0

Hóa ra rằng sqlite đã bị búa quá khó cho ứng dụng của tôi. Vì vậy, tôi đã di chuyển trường độc giả vào bộ nhớ thay thế. Điều này đã cải thiện hiệu suất khoảng 10000% và tôi nhấn ổ cứng waay ít hơn. – Matt

1

Câu hỏi đầu tiên: bạn đang cố gắng sử dụng một kết nối với tất cả tám đề? Nếu vậy, hãy đảm bảo mỗi luồng có kết nối riêng. Tôi không biết bất kỳ cơ sở dữ liệu nào thích điều đó.

Ngoài ra kiểm tra FAQ: http://www.sqlite.org/faq.html

Rõ ràng SQLite phải được biên soạn với một lựa chọn SQLITE_THREADSAFE Preprocessor thiết lập để 1. Họ làm có một phương pháp để xác định xem đó là vấn đề của bạn.

Một vấn đề khác là việc viết chỉ có thể xảy ra từ một quy trình một cách an toàn.

+0

Có, một kết nối cho mỗi chuỗi. Tôi sẽ kiểm tra các tùy chọn preprocessor threadsafe. Tôi đã được ấn tượng mặc dù đó là mặc định. – Matt

+0

Tôi đặt tùy chọn này như thế nào? – ademar111190

Các vấn đề liên quan