MongoDB không tuân thủ ACID trước v4 thực sự có ý nghĩa gì?


226

Tôi không phải là một chuyên gia cơ sở dữ liệu và không có nền tảng khoa học máy tính chính thức, vì vậy hãy đồng ý với tôi. Tôi muốn biết các loại điều tiêu cực trong thế giới thực có thể xảy ra nếu bạn sử dụng phiên bản MongoDBtrước phiên bản 4 , không tuân thủ ACID . Điều này áp dụng cho bất kỳ cơ sở dữ liệu không tuân thủ ACID nào.

Tôi hiểu rằng MongoDB có thể thực hiện các hoạt động nguyên tử , nhưng họ không "hỗ trợ các giao dịch phức tạp và khóa truyền thống", chủ yếu là vì lý do hiệu suất. Tôi cũng hiểu tầm quan trọng của giao dịch cơ sở dữ liệu và ví dụ về thời điểm cơ sở dữ liệu của bạn dành cho ngân hàng và bạn đang cập nhật một số bản ghi cần phải đồng bộ hóa, bạn muốn giao dịch trở lại trạng thái ban đầu nếu có mất điện vì vậy tín dụng tương đương với mua hàng, vv

Nhưng khi tôi bắt đầu trò chuyện về MongoDB, những người trong chúng ta không biết chi tiết kỹ thuật về cách thức cơ sở dữ liệu được triển khai thực sự bắt đầu ném xung quanh các câu như:

MongoDB nhanh hơn MySQL và Postgres, nhưng có một cơ hội nhỏ, như 1 trên một triệu, rằng nó "sẽ không lưu chính xác".

Phần "sẽ không lưu chính xác" đề cập đến cách hiểu này: Nếu có sự cố mất điện ngay khi bạn viết thư cho MongoDB, có thể có một bản ghi cụ thể (giả sử bạn đang theo dõi số lần xem trang trong tài liệu có 10 thuộc tính mỗi), một trong những tài liệu chỉ lưu được 5 trong số các thuộc tính, điều đó có nghĩa là theo thời gian, số lượt xem trang của bạn sẽ bị "tắt" một chút. Bạn sẽ không bao giờ biết bao nhiêu, bạn biết họ sẽ đúng 99,999%, nhưng không phải 100%. Điều này là do, trừ khi bạn đặc biệt biến đây thành một hoạt động nguyên tử mongodb , hoạt động này không được đảm bảo là nguyên tử.

Vì vậy, câu hỏi của tôi là, giải thích chính xác về thời điểm và lý do MongoDB có thể không "lưu chính xác" là gì? Những phần nào của ACID không thỏa mãn và trong những trường hợp nào và làm thế nào để bạn biết khi nào 0,001% dữ liệu của bạn bị tắt? Điều này không thể được sửa chữa bằng cách nào đó? Nếu không, điều này có nghĩa là bạn không nên lưu trữ những thứ như usersbảng của mình trong MongoDB, vì một bản ghi có thể không lưu. Nhưng một lần nữa, người dùng 1 / 1.000.000 đó có thể chỉ cần "thử đăng ký lại", không?

Tôi chỉ tìm kiếm một danh sách khi nào / tại sao những điều tiêu cực xảy ra với cơ sở dữ liệu không tuân thủ ACID như MongoDB, và lý tưởng là nếu có một cách giải quyết tiêu chuẩn (như chạy một công việc nền để dọn dẹp dữ liệu hoặc chỉ sử dụng SQL cho việc này, v.v.) .

Câu trả lời:


133

Một điều bạn mất với MongoDB là các giao dịch đa tập hợp (bảng). Công cụ sửa đổi nguyên tử trong MongoDB chỉ có thể hoạt động đối với một tài liệu duy nhất.

Nếu bạn cần xóa một mặt hàng khỏi kho và thêm nó vào đơn hàng của ai đó cùng một lúc - bạn không thể. Trừ khi hai điều đó - hàng tồn kho và đơn đặt hàng - tồn tại trong cùng một tài liệu (mà có lẽ chúng không có).

Tôi đã gặp vấn đề rất giống nhau trong một ứng dụng tôi đang làm việc và có hai giải pháp khả thi để lựa chọn:

1) Cấu trúc tài liệu của bạn một cách tốt nhất có thể và sử dụng các công cụ sửa đổi nguyên tử một cách tốt nhất có thể và đối với bit còn lại, sử dụng quy trình nền để dọn sạch các bản ghi có thể không đồng bộ. Ví dụ, tôi xóa các mục khỏi kho và thêm chúng vào một mảng dành riêng cho cùng một tài liệu bằng cách sử dụng các sửa đổi nguyên tử.

Điều này cho phép tôi luôn biết rằng các mặt hàng KHÔNG có sẵn trong kho (vì chúng được dành riêng bởi một khách hàng). Khi khách hàng trả phòng, tôi sẽ xóa các mục khỏi reservedInventory. Đây không phải là một giao dịch tiêu chuẩn và vì khách hàng có thể từ bỏ giỏ hàng, tôi cần một số quy trình nền để đi qua và tìm các giỏ hàng bị bỏ rơi và chuyển hàng tồn kho đã đặt lại vào kho tồn kho có sẵn.

Điều này rõ ràng là ít hơn lý tưởng, nhưng nó là phần duy nhất của một ứng dụng lớn mà mongodb không phù hợp hoàn hảo với nhu cầu. Thêm vào đó, nó hoạt động hoàn hảo cho đến nay. Điều này có thể không khả thi đối với nhiều tình huống, nhưng do cấu trúc tài liệu tôi đang sử dụng, nó rất phù hợp.

2) Sử dụng cơ sở dữ liệu giao dịch kết hợp với MongoDB. Người ta thường sử dụng MySQL để cung cấp các giao dịch cho những thứ thực sự cần chúng trong khi để MongoDB (hoặc bất kỳ NoQuery nào khác) làm những gì nó làm tốt nhất.

Nếu giải pháp của tôi từ số 1 không hoạt động trong thời gian dài, tôi sẽ điều tra thêm về việc kết hợp MongoDB với MySQL nhưng hiện tại # 1 phù hợp với nhu cầu của tôi.


27
"Công cụ sửa đổi nguyên tử trong MongoDB chỉ có thể hoạt động đối với một bộ sưu tập duy nhất " => Tôi nghĩ bạn có nghĩa là "chống lại một tài liệu duy nhất ".
assylias

2
Thông tin tuyệt vời, nói chung là một câu trả lời tuyệt vời ngoại trừ đề xuất sử dụng MySQL.
Doug Molineux

Một điều bạn mất với MongoDB là các giao dịch đa tập hợp (bảng). Công cụ sửa đổi nguyên tử trong MongoDB chỉ có thể hoạt động đối với một tài liệu duy nhất ״ từ mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): "Trong MongoDB, một thao tác ghi là nguyên tử ở cấp độ của một tài liệu, ngay cả khi thao tác sửa đổi nhiều tài liệu nhúng trong một tài liệu. "
yoav.str

5
Thiếu giao dịch ACID đa tài liệu không còn là trường hợp nữa. MongoDB thông báo họ sẽ đến phiên bản 4.0. Xem mongodb.com/blog/post/multi-document-transilities-in-mongodb
Grigori Melnik

1
Hiện tại, vì MongoDB 4.0 là mongodb.com/trans tương thích với các giao dịch đa tài liệu. Hãy xem mongodb.com/blog/post/ từ
Ratah

134

Thật ra không đúng khi MongoDB không tuân thủ ACID. Ngược lại, MongoDB là trình biên dịch ACID ở cấp độ tài liệu .

Mọi cập nhật cho một tài liệu là

  • Nguyên tử: nó hoàn thành đầy đủ hoặc không
  • Nhất quán: không người đọc sẽ thấy cập nhật "được áp dụng một phần"
  • Bị cô lập: một lần nữa, sẽ không có người đọc nào nhìn thấy một lần đọc "bẩn"
  • Bền: (với mối quan tâm viết thích hợp)

Những gì MongoDB không có là các giao dịch - nghĩa là các bản cập nhật nhiều tài liệu có thể được khôi phục và tuân thủ ACID.

Lưu ý rằng bạn có thể xây dựng các giao dịch trên đầu các bản cập nhật tuân thủ ACID cho một tài liệu bằng cách sử dụng cam kết hai pha .


3
Lưu ý rằng các giao dịch của các cam kết hai pha không tuân thủ ACID. Vì một số lý do, tôi đã suy luận ngược lại cho đến khi tôi theo liên kết.
Justin C

1
Có một số câu hỏi về độ bền của MongoDB phân tán ở cấp độ tài liệu, bất kể cấu hình liên quan đến ghi. Công cụ nguồn mở Jepsen nhận thấy rằng dữ liệu có thể bị mất khi đối mặt với phân vùng mạng ngay cả với mối quan tâm ghi MAJORITY. Xem bài viết tại đây: aphyr.com/posts/284-call-me-maybe-mongodb
jrullmann

9
Có ACID ở cấp độ của một tài liệu mà theo một cách nào đó tương đương với một bản ghi trong RDBMS không hữu ích trong nhiều trường hợp. Thời hạn của giao dịch không liên quan đến một bảng và thậm chí bạn có thể có cơ chế cam kết hai pha và liên quan đến một số XAResource, do đó đề cập đến tài liệu duy nhất là tuân thủ ACID có chút vấn đề, IMHO.
Yair Zaslavsky

5
Đồng ý với Yair. "Tuân thủ ACID ở cấp độ tài liệu" không phải là điểm bán hàng. Về cơ bản nó chỉ có nghĩa là "không tuân thủ ACID". ACID không bao giờ có nghĩa là "chỉ một hàng / tài liệu / thực thể". Đó là về việc giữ cho dữ liệu của bạn nhất quán trong toàn bộ cơ sở dữ liệu.
joshua.paling

34

Một lời giải thích tốt có trong "Starbucks Không sử dụng Cam kết hai pha" .

Đây không phải là về cơ sở dữ liệu NoQuery, nhưng nó minh họa điểm mà đôi khi bạn có thể đủ khả năng để mất một giao dịch hoặc tạm thời có cơ sở dữ liệu của bạn ở trạng thái không nhất quán.

Tôi sẽ không coi đó là một cái gì đó cần phải được "sửa chữa". Cách khắc phục là sử dụng cơ sở dữ liệu quan hệ tuân thủ ACID. Bạn chọn một giải pháp thay thế NoQuery khi hành vi của nó đáp ứng các yêu cầu ứng dụng của bạn.


1
Giống như bất kỳ sự tương tự, nó có những hạn chế của nó. Trong phần mềm, thật dễ dàng để tạo Array [Cashiers] mới và yêu cầu chúng xử lý các giao dịch đồng bộ từng giao dịch, trong khi chi phí trong thế giới thực sẽ rất tốn kém.
HRJ

16

Tôi nghĩ rằng những người khác đã đưa ra câu trả lời tốt. Tuy nhiên, tôi muốn thêm rằng có các DB NOSQL ACID (như http://ravendb.net/ ). Vì vậy, đó không chỉ là quyết định NOSQL - không có ACID so với quan hệ với ACID ....


1
cảm ơn @subGate. có ai có thể chia sẻ kinh nghiệm của họ với ravenDB không và liệu nó có thực sự thỏa mãn yêu cầu không?
Nir Pengas

12

"sẽ không lưu chính xác" có thể có nghĩa là:

  1. Theo mặc định MongoDB không lưu các thay đổi của bạn vào ổ đĩa ngay lập tức. Vì vậy, có khả năng bạn nói với người dùng "cập nhật thành công", mất điện xảy ra và cập nhật bị mất. MongoDB cung cấp các tùy chọn để kiểm soát mức độ cập nhật "độ bền". Nó có thể đợi (các) bản sao khác nhận được bản cập nhật này (trong bộ nhớ), chờ cho việc ghi xảy ra với tệp nhật ký cục bộ, v.v.

  2. Không có cập nhật "nguyên tử" dễ dàng cho nhiều bộ sưu tập và thậm chí nhiều tài liệu trong cùng một bộ sưu tập. Nó không phải là vấn đề trong hầu hết các trường hợp bởi vì nó có thể bị phá vỡ bằng Cam kết hai pha hoặc cơ cấu lại lược đồ của bạn để cập nhật được thực hiện cho một tài liệu. Xem câu hỏi này: Cơ sở dữ liệu tài liệu: Dữ liệu dự phòng, tài liệu tham khảo, v.v (cụ thể là MongoDB)


10

Kể từ MongoDB v4.0, các giao dịch ACID đa tài liệu sẽ được hỗ trợ. Thông qua cách ly ảnh chụp nhanh, các giao dịch sẽ cung cấp chế độ xem dữ liệu thống nhất toàn cầu và thực thi tất cả hoặc không có gì để duy trì tính toàn vẹn dữ liệu.

Họ cảm thấy như các giao dịch từ thế giới quan hệ, ví dụ:

with client.start_session() as s:
    s.start_transaction()
    try:
        collection.insert_one(doc1, session=s)
        collection.insert_one(doc2, session=s)
        s.commit_transaction()
    except Exception:
        s.abort_transaction()

Xem https://www.mongodb.com/blog/post/multi-document-transilities-in-mongodb


Các ứng cử viên phát hành đầu tiên của MongoDB4.0 là out - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik

5

Vui lòng đọc về các thuộc tính ACID để hiểu rõ hơn.

Cũng trong tài liệu MongoDB, bạn có thể tìm thấy một câu hỏi và câu trả lời .

MongoDB không tuân thủ ACID. Đọc dưới đây để thảo luận về việc tuân thủ ACID.

  1. MongoDB chỉ là Atomic ở cấp độ tài liệu. Nó không tuân thủ định nghĩa về nguyên tử mà chúng ta biết từ các hệ thống cơ sở dữ liệu quan hệ, đặc biệt là liên kết ở trên. Theo nghĩa này, MongoDB không tuân thủ A từ ACID.
  2. MongoDB được Cmặc định theo mặc định. Tuy nhiên, bạn có thể đọc từ các máy chủ thứ cấp trong một bộ bản sao. Bạn chỉ có thể có sự thống nhất cuối cùng trong trường hợp này. Điều này rất hữu ích nếu bạn không ngại đọc dữ liệu hơi lỗi thời.
  3. MongoDB không đảm bảo sự Igiải quyết (một lần nữa theo định nghĩa trên):
  1. Đối với các hệ thống có nhiều người đọc và người viết đồng thời, MongoDB sẽ cho phép khách hàng đọc kết quả của thao tác ghi trước khi hoạt động ghi trở lại.
  2. Nếu mongod chấm dứt trước khi tạp chí cam kết, ngay cả khi ghi trở lại thành công, các truy vấn có thể đã đọc dữ liệu sẽ không tồn tại sau khi mongod khởi động lại.

Tuy nhiên , MongoDB sửa đổi từng tài liệu một cách riêng biệt (để chèn và cập nhật); chỉ ở cấp độ tài liệu, không phải trên các giao dịch đa tài liệu.

  1. Liên quan đến tính Ddễ sử dụng - bạn có thể định cấu hình hành vi này với write concerntùy chọn, mặc dù không chắc chắn. Có lẽ ai đó biết rõ hơn.

Tôi tin rằng một số nghiên cứu đang tiếp tục để chuyển NoQuery sang các ràng buộc ACID hoặc tương tự. Đây là một thách thức vì cơ sở dữ liệu NoQuery thường nhanh (er) và các ràng buộc ACID có thể làm chậm hiệu suất đáng kể.


4

Lý do duy nhất nguyên tử sửa đổi hoạt động đối với một bộ sưu tập là bởi vì các nhà phát triển mongodb gần đây đã trao đổi một khóa cơ sở dữ liệu với một khóa ghi rộng của bộ sưu tập. Quyết định rằng sự đồng thời gia tăng ở đây là giá trị đánh đổi. Về cốt lõi, mongodb là một tệp ánh xạ bộ nhớ: họ đã ủy quyền quản lý nhóm bộ đệm cho hệ thống con vm của máy. Bởi vì nó luôn ở trong bộ nhớ, nên họ có thể thoát khỏi các khóa rất nhỏ: bạn sẽ chỉ thực hiện các thao tác trong bộ nhớ trong khi giữ nó, sẽ cực kỳ nhanh. Điều này khác biệt đáng kể so với một hệ thống cơ sở dữ liệu truyền thống, đôi khi buộc phải thực hiện I / O trong khi giữ một trang phục hoặc khóa.


bạn có thể vui lòng giải thích tại sao điều này làm tăng sự tương tranh? Xin lỗi nếu tôi thiếu điều hiển nhiên ở đây.
batbrat

@batbrat: Hãy xem xét hai khách hàng cố gắng ghi đồng thời vào các bộ sưu tập khác nhau trong cùng một cơ sở dữ liệu. Với khóa cơ sở dữ liệu, một trong các khách hàng sẽ phải đợi người kia kết thúc trước khi việc ghi của nó có thể xảy ra. Với một bộ sưu tập khóa cả hai khách hàng có thể viết cùng một lúc. Đó là những gì có nghĩa là tăng đồng thời. Tất nhiên, nếu cả hai khách hàng cố gắng ghi vào cùng một bộ sưu tập thì người ta sẽ phải chờ.
jrullmann

2

"Trong MongoDB, một hoạt động trên một tài liệu duy nhất là nguyên tử" - Đó là điều cho quá khứ

Trong phiên bản mới của MongoDB 4.0, bạn CÓ THỂ:

Tuy nhiên, đối với các tình huống yêu cầu tính nguyên tử để cập nhật nhiều tài liệu hoặc tính nhất quán giữa các lần đọc thành nhiều tài liệu, MongoDB cung cấp khả năng thực hiện các giao dịch đa tài liệu đối với các bộ bản sao. Giao dịch đa tài liệu có thể được sử dụng trên nhiều hoạt động, bộ sưu tập, cơ sở dữ liệu và tài liệu. Các giao dịch đa tài liệu cung cấp một đề xuất tất cả hoặc không có gì trên thế giới. Khi một giao dịch cam kết, tất cả các thay đổi dữ liệu được thực hiện trong giao dịch sẽ được lưu. Nếu bất kỳ hoạt động nào trong giao dịch không thành công, giao dịch sẽ hủy bỏ và tất cả các thay đổi dữ liệu được thực hiện trong giao dịch sẽ bị loại bỏ mà không bao giờ hiển thị. Cho đến khi một giao dịch được thực hiện, không có thao tác ghi nào trong giao dịch được hiển thị bên ngoài giao dịch.

Mặc dù có rất ít hiệu như thế nàonhững gì hoạt động có thể được thực hiện.

Kiểm tra Mongo Đốc. https://docs.mongodb.com/master/core/transilities/


1

Bạn có thể triển khai các cập nhật đa khóa nguyên tử (giao dịch tuần tự hóa) ở phía máy khách nếu bộ lưu trữ của bạn hỗ trợ tính tuyến tính theo khóa và so sánh và thiết lập (điều này đúng với MongoDB). Cách tiếp cận này được sử dụng trong Công cụ phần trăm của Google và trong CockroachDB nhưng không có gì ngăn bạn sử dụng nó với MongoDB.

Tôi đã tạo ra một hình dung từng bước của các giao dịch như vậy. Tôi hy vọng nó sẽ giúp bạn hiểu họ.

Nếu bạn ổn với mức độ cô lập đã cam kết thì nên xem qua các giao dịch RAMP của Peter Bailis. Chúng cũng có thể được triển khai cho MongoDB ở phía máy khách.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.