SQLite3 có xử lý an toàn truy cập đồng thời bằng nhiều quá trình đọc / ghi từ cùng một DB không? Có bất kỳ ngoại lệ nền tảng cho điều đó?
SQLite3 có xử lý an toàn truy cập đồng thời bằng nhiều quá trình đọc / ghi từ cùng một DB không? Có bất kỳ ngoại lệ nền tảng cho điều đó?
Câu trả lời:
Nếu hầu hết các truy cập đồng thời đó là đọc (ví dụ CHỌN), SQLite có thể xử lý chúng rất tốt. Nhưng nếu bạn bắt đầu viết đồng thời, sự tranh chấp khóa có thể trở thành một vấn đề. Rất nhiều thứ sẽ phụ thuộc vào hệ thống tập tin của bạn nhanh như thế nào, vì bản thân công cụ SQLite cực kỳ nhanh và có nhiều tối ưu hóa thông minh để giảm thiểu sự tranh chấp. Đặc biệt là SQLite 3.
Đối với hầu hết các ứng dụng máy tính để bàn / máy tính xách tay / máy tính bảng / điện thoại, SQLite đủ nhanh vì không đủ đồng thời. (Firefox sử dụng SQLite rộng rãi cho dấu trang, lịch sử, v.v.)
Đối với các ứng dụng máy chủ, một số người trước đây đã nói rằng bất cứ điều gì ít hơn 100 nghìn lượt xem trang mỗi ngày đều có thể được xử lý hoàn hảo bởi cơ sở dữ liệu SQLite trong các tình huống điển hình (ví dụ: blog, diễn đàn) và tôi chưa thấy bằng chứng nào ngược lại. Trong thực tế, với các đĩa và bộ xử lý hiện đại, 95% các trang web và dịch vụ web sẽ hoạt động tốt với SQLite.
Nếu bạn muốn truy cập đọc / ghi thực sự nhanh, hãy sử dụng cơ sở dữ liệu SQLite trong bộ nhớ . RAM là một số đơn đặt hàng có cường độ nhanh hơn đĩa.
Đúng, SQLite xử lý đồng thời tốt, nhưng nó không phải là tốt nhất từ góc độ hiệu suất. Từ những gì tôi có thể nói, không có ngoại lệ cho điều đó. Các chi tiết có trên trang web của SQLite: https://www.sqlite.org/lockingv3.html
Tuyên bố này được quan tâm: "Mô-đun máy nhắn tin đảm bảo tất cả các thay đổi xảy ra cùng một lúc, rằng tất cả các thay đổi xảy ra hoặc không có thay đổi nào xảy ra, rằng hai hoặc nhiều quá trình không cố gắng truy cập cơ sở dữ liệu theo cách không tương thích cùng một lúc"
Có nó làm. Hãy tìm hiểu tại sao
Tất cả các thay đổi trong một giao dịch trong SQLite đều xảy ra hoàn toàn hoặc không xảy ra
Hỗ trợ ACID như cũng như đồng thời đọc / ghi được cung cấp theo 2 cách - bằng cách sử dụng cái gọi là nhật ký (cho phép gọi nó là “ cách cũ ”) hoặc ghi-trước khai thác gỗ (cho phép gọi nó là “ phương pháp mới ”)
Trong chế độ này, SQLite sử dụng khóa DATABASE-LEVEL . Đây là điểm quan trọng để hiểu.
Điều đó có nghĩa là bất cứ khi nào nó cần đọc / ghi một cái gì đó, lần đầu tiên nó sẽ có được một khóa trên tệp cơ sở dữ liệu ENTIRE . Nhiều người đọc có thể cùng tồn tại và đọc một cái gì đó song song
Trong quá trình viết, nó đảm bảo có được một khóa độc quyền và không có quá trình nào khác là đọc / ghi đồng thời và do đó việc ghi là an toàn.
Đây là lý do tại sao ở đây họ nói cụ SQLite serializable giao dịch
Vì nó cần phải khóa toàn bộ cơ sở dữ liệu mỗi lần và mọi người chờ đợi một quá trình xử lý việc viết đồng thời bị ảnh hưởng và việc ghi / đọc đồng thời như vậy có hiệu suất khá thấp
Trước khi viết một cái gì đó vào tệp cơ sở dữ liệu, trước tiên SQLite sẽ lưu đoạn dữ liệu được thay đổi trong một tệp tạm thời. Nếu một cái gì đó gặp sự cố khi viết vào tệp cơ sở dữ liệu, nó sẽ chọn tệp tạm thời này và hoàn nguyên các thay đổi từ nó
Trong trường hợp này, tất cả các ghi được thêm vào một tệp tạm thời ( nhật ký ghi trước ) và tệp này được định kỳ hợp nhất với cơ sở dữ liệu gốc. Khi SQLite đang tìm kiếm thứ gì đó, trước tiên, nó sẽ kiểm tra tệp tạm thời này và nếu không tìm thấy gì, hãy tiếp tục với tệp cơ sở dữ liệu chính.
Do đó, độc giả không cạnh tranh với các nhà văn và hiệu suất tốt hơn nhiều so với Cách cũ.
SQlite phụ thuộc rất nhiều vào chức năng khóa hệ thống tập tin cơ bản vì vậy nó nên được sử dụng một cách thận trọng, chi tiết hơn ở đây
Bạn cũng có khả năng chạy vào cơ sở dữ liệu bị khóa , đặc biệt là ở chế độ ghi nhật ký, vì vậy ứng dụng của bạn cần được thiết kế với lỗi này.
Dường như không ai đề cập đến chế độ WAL (Write Ahead Log). Đảm bảo các giao dịch được tổ chức hợp lý và với chế độ WAL được bật, không cần phải khóa cơ sở dữ liệu trong khi mọi người đang đọc mọi thứ trong khi cập nhật đang diễn ra.
Vấn đề duy nhất là tại một số điểm, WAL cần được kết hợp lại vào cơ sở dữ liệu chính và nó thực hiện điều này khi kết nối cuối cùng với cơ sở dữ liệu đóng lại. Với một trang web rất bận rộn, bạn có thể thấy mất vài giây để tất cả các kết nối được đóng lại, nhưng 100 nghìn lượt truy cập mỗi ngày không phải là vấn đề.
database is locked
lỗi đó sẽ được đưa ra bởi nhà văn
Năm 2019, có hai tùy chọn ghi đồng thời mới chưa được phát hành nhưng có sẵn trong các nhánh riêng biệt.
Ưu điểm của chế độ nhật ký này so với chế độ "wal" thông thường là người viết có thể tiếp tục viết vào một tệp wal trong khi tệp kia được kiểm tra.
BEGIN CONCURRENT - liên kết đến tài liệu chi tiết
Cải tiến BEGIN CONCURRENT cho phép nhiều người viết xử lý các giao dịch ghi đồng thời nếu cơ sở dữ liệu ở chế độ "wal" hoặc "wal2", mặc dù hệ thống vẫn tuần tự hóa các lệnh CAMIT.
Khi một giao dịch ghi được mở bằng "BEGIN CONCURRENT", thực tế việc khóa cơ sở dữ liệu sẽ được hoãn lại cho đến khi một CAMIT được thực thi. Điều này có nghĩa là bất kỳ số lượng giao dịch nào được bắt đầu với BEGIN CONCURRENT đều có thể tiến hành đồng thời. Hệ thống sử dụng khóa cấp độ trang lạc quan để ngăn chặn các giao dịch đồng thời xung đột được thực hiện.
Cùng nhau, chúng có mặt trong start-concallel-wal2 hoặc mỗi cái trong một nhánh riêng .
begin concurrent
thứ đó.
SQLite có khóa trình đọc- ghi ở cấp cơ sở dữ liệu. Nhiều kết nối (có thể thuộc sở hữu của các quy trình khác nhau) có thể đọc dữ liệu từ cùng một cơ sở dữ liệu cùng một lúc, nhưng chỉ một kết nối có thể ghi vào cơ sở dữ liệu.
SQLite hỗ trợ số lượng người đọc đồng thời không giới hạn, nhưng nó sẽ chỉ cho phép một người viết bất cứ lúc nào. Đối với nhiều tình huống, đây không phải là một vấn đề. Nhà văn xếp hàng. Mỗi ứng dụng làm cơ sở dữ liệu của nó hoạt động nhanh chóng và di chuyển, và không có khóa nào tồn tại trong hơn vài chục mili giây. Nhưng có một số ứng dụng đòi hỏi đồng thời nhiều hơn và những ứng dụng đó có thể cần tìm kiếm một giải pháp khác. - Sử dụng phù hợp cho SQLite @ SQLite.org
Khóa độc giả-nhà văn cho phép xử lý giao dịch độc lập và nó được thực hiện bằng cách sử dụng các khóa độc quyền và chia sẻ ở cấp cơ sở dữ liệu.
Phải có khóa độc quyền trước khi kết nối thực hiện thao tác ghi trên cơ sở dữ liệu. Sau khi có được khóa độc quyền, cả thao tác đọc và ghi từ các kết nối khác đều bị chặn cho đến khi khóa được giải phóng lại.
SQLite có một bảng khóa giúp khóa cơ sở dữ liệu càng muộn càng tốt trong quá trình ghi để đảm bảo đồng thời tối đa.
Trạng thái ban đầu là UNLOCKED và ở trạng thái này, kết nối chưa được truy cập cơ sở dữ liệu. Khi một quá trình được kết nối với cơ sở dữ liệu và thậm chí một giao dịch đã được bắt đầu với BEGIN, kết nối vẫn ở trạng thái UNLOCKED.
Sau trạng thái UNLOCKED, trạng thái tiếp theo là trạng thái CHIA SẺ. Để có thể đọc (không ghi) dữ liệu từ cơ sở dữ liệu, trước tiên, kết nối phải vào trạng thái CHIA SẺ, bằng cách lấy khóa CHIA SẺ. Nhiều kết nối có thể có được và duy trì các khóa CHIA SẺ cùng một lúc, vì vậy nhiều kết nối có thể đọc dữ liệu từ cùng một cơ sở dữ liệu cùng một lúc. Nhưng miễn là chỉ có một khóa CHIA SẺ vẫn chưa được phát hành, không có kết nối nào có thể hoàn thành ghi vào cơ sở dữ liệu.
Nếu một kết nối muốn ghi vào cơ sở dữ liệu, trước tiên, nó phải nhận được khóa RESERVED.
Chỉ một khóa RESERVED có thể hoạt động cùng một lúc, mặc dù nhiều khóa CHIA SẺ có thể cùng tồn tại với một khóa RESERVED duy nhất. RESERVED khác với PENDING ở chỗ khóa SHARED mới có thể có được trong khi có khóa RESERVED. - Khóa tệp và đồng thời trong SQLite Phiên bản 3 @ SQLite.org
Khi một kết nối có được khóa RESERVED, nó có thể bắt đầu xử lý các hoạt động sửa đổi cơ sở dữ liệu, mặc dù những sửa đổi này chỉ có thể được thực hiện trong bộ đệm, thay vì thực sự được ghi vào đĩa. Các sửa đổi được thực hiện cho nội dung đọc được lưu trong bộ nhớ đệm. Khi một kết nối muốn gửi một sửa đổi (hoặc giao dịch), cần phải nâng cấp khóa RESERVED thành khóa ĐỘC QUYỀN. Để có được khóa, trước tiên bạn phải nâng khóa lên khóa PENDING.
Khóa PENDING có nghĩa là quá trình giữ khóa muốn ghi vào cơ sở dữ liệu càng sớm càng tốt và chỉ chờ trên tất cả các khóa CHIA SẺ hiện tại để xóa để có thể nhận được khóa ĐỘC QUYỀN. Không có khóa SHARED mới nào được phép đối với cơ sở dữ liệu nếu khóa PENDING đang hoạt động, mặc dù các khóa SHARED hiện tại được phép tiếp tục.
Một khóa ĐỘC QUYỀN là cần thiết để ghi vào tệp cơ sở dữ liệu. Chỉ có một khóa ĐỘC QUYỀN được cho phép trên tệp và không có khóa nào khác được phép cùng tồn tại với khóa ĐỘC QUYỀN. Để tối đa hóa đồng thời, SQLite hoạt động để giảm thiểu lượng thời gian mà các khóa EXCLUSIVE được giữ. - Khóa tệp và đồng thời trong SQLite Phiên bản 3 @ SQLite.org
Vì vậy, bạn có thể nói SQLite xử lý truy cập đồng thời một cách an toàn bằng nhiều quy trình ghi vào cùng một DB đơn giản vì nó không hỗ trợ nó! Bạn sẽ nhận được SQLITE_BUSY
hoặc SQLITE_LOCKED
cho nhà văn thứ hai khi nó đạt đến giới hạn thử lại.
Chủ đề này đã cũ nhưng tôi nghĩ sẽ rất tốt khi chia sẻ kết quả các thử nghiệm của mình được thực hiện trên sqlite: tôi đã chạy 2 phiên bản của chương trình python (các quy trình khác nhau cùng một chương trình) thực thi các lệnh CHỌN và CẬP NHẬT các lệnh sql trong giao dịch với khóa EXCLUSIVE và thời gian chờ được đặt thành 10 giây để có được một khóa, và kết quả là bực bội. Mỗi trường hợp đã thực hiện trong vòng 10000 bước:
Ngay cả khi sqlite được cấp khóa độc quyền trong giao dịch, tổng số chu kỳ thực hiện không bằng 20 000 nhưng ít hơn (tổng số lần lặp qua bộ đếm đơn được tính cho cả hai quy trình). Chương trình Python gần như không ném bất kỳ ngoại lệ nào (chỉ một lần trong khi chọn trong 20 lần thực thi). sửa đổi sqlite tại thời điểm thử nghiệm là 3.6.20 và python v3.3 CentOS 6.5. Theo ý kiến của tôi, tốt hơn là tìm sản phẩm đáng tin cậy hơn cho loại công việc này hoặc hạn chế ghi vào sqlite cho quy trình / chủ đề duy nhất.
with con
là đủ.