2010-10-15 17 views
6

Có một vấn đề đã biết với SQLite đưa ra lỗi "cơ sở dữ liệu bị khóa" cho truy vấn thứ hai trong một giao dịch đơn lẻ khi sử dụng Perl DBD :: SQLite không? Kịch bản: Linux, Perl DBI, AutoCommit => 0, một chương trình con với hai khối mã (sử dụng các khối để bản địa hóa các tên biến). Trong khối mã đầu tiên, một xử lý truy vấn được tạo ra bằng cách chuẩn bị() trên một câu lệnh chọn, nó được thực hiện() và khối đã đóng. Khối thứ hai khối xử lý truy vấn khác được tạo ra bằng cách chuẩn bị cho một câu lệnh cập nhật và thường xuyên (30% thời gian) SQLite/DBI cung cấp cho một lỗi cơ sở dữ liệu bị khóa ở giai đoạn này. Tôi nghĩ rằng lỗi xảy ra trong quá trình chuẩn bị() và không xảy ra trong khi thực thi().Tại sao SQLite đưa ra một "cơ sở dữ liệu bị khóa" cho truy vấn thứ hai trong một giao dịch khi sử dụng DBD :: SQLite của Perl?

Công việc của tôi xung quanh là cam kết sau truy vấn đầu tiên. (Gọi kết thúc trên truy vấn đầu tiên không giúp được). Tôi không muốn cam kết vì nhiều lý do liên quan đến sự sang trọng và hiệu suất. Mã gốc đã hoạt động tốt trong nhiều năm với Postgres làm cơ sở dữ liệu. Tôi đã thử sqlite_use_immediate_transaction không có hiệu lực.

Trong tất cả các tình huống khác, tôi đã tìm thấy SQLite để thực hiện rất tốt, vì vậy tôi nghi ngờ đây là một sự giám sát trong trình điều khiển DBD, chứ không phải là một vấn đề với SQLite. Đáng buồn thay, mã hiện tại của tôi là một đống kịch bản và mô-đun lớn, vì vậy tôi không có một trường hợp thử nghiệm tệp đơn lẻ.

+0

Bạn có thể cho chúng tôi thấy trường hợp thử nghiệm nhỏ của bạn thể hiện sự cố không? –

Trả lời

6

Không liên quan đến điều này trong anyway là: Transaction and Database Locking từ DBD::SQLite perldoc?

Giao dịch bằng AutoCommit hoặc begin_work đẹp và tiện dụng, nhưng đôi khi bạn có thể gặp phải lỗi "cơ sở dữ liệu bị khóa" gây phiền nhiễu. Điều này thường xảy ra khi ai đó bắt đầu một giao dịch và cố gắng ghi vào cơ sở dữ liệu trong khi người khác đang đọc từ cơ sở dữ liệu (trong giao dịch khác). Bạn có thể ngạc nhiên nhưng SQLite không khóa cơ sở dữ liệu khi bạn chỉ bắt đầu một giao dịch bình thường (hoãn lại) để tối đa hóa đồng thời. Nó dự trữ một khóa khi bạn phát hành một câu lệnh để viết, nhưng cho đến khi bạn thực sự cố gắng viết với một câu lệnh cam kết, nó cho phép người khác đọc từ cơ sở dữ liệu. Tuy nhiên, đọc từ cơ sở dữ liệu cũng yêu cầu khóa chia sẻ và ngăn chặn cung cấp cho bạn khóa độc quyền mà bạn đã đặt, do đó bạn gặp lỗi "cơ sở dữ liệu bị khóa" và những người khác sẽ gặp lỗi tương tự nếu họ cố gắng viết sau đó, bạn vẫn có khóa đang chờ xử lý. busy_timeout không trợ giúp trong trường hợp này.

Để tránh điều này, hãy đặt loại giao dịch một cách rõ ràng. Bạn có thể phát hành giao dịch ngay lập tức (hoặc bắt đầu giao dịch độc quyền) cho mỗi giao dịch hoặc đặt thuộc tính xử lý cơ sở dữ liệu sqlite_use_immediate_transaction thành true (kể từ 1.30_02) để luôn sử dụng giao dịch ngay lập tức (ngay cả khi bạn chỉ đơn giản là sử dụng start_work hoặc tắt AutoCommit.) .

my $dbh = DBI->connect("dbi:SQLite::memory:", "", "", { 
    sqlite_use_immediate_transaction => 1, 
}); 

Lưu ý rằng điều này chỉ hoạt động khi tất cả các kết nối sử dụng cùng một giao dịch (không trì hoãn). Xem http://sqlite.org/lockingv3.html để biết chi tiết về khóa.

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