2011-08-22 64 views
194

Tôi không phải là chuyên gia về 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 chịu đựng tôi. Tôi muốn biết các loại thế giới thực những điều tiêu cực có thể xảy ra nếu bạn sử dụng MongoDB, 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.MongoDB không tuân thủ ACID thực sự có ý nghĩa gì?

Tôi hiểu rằng MongoDB có thể thực hiện Atomic Operations, nhưng họ không "hỗ trợ khóa truyền thống và giao dịch phức tạp", chủ yếu vì lý do hiệu suất. Tôi cũng hiểu tầm quan trọng của các giao dịch cơ sở dữ liệu và ví dụ khi 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 được đồng bộ hóa, bạn muốn giao dịch hoàn nguyên về trạng thái ban đầu nếu có cúp điện nên tín dụng bằng mua vv

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

MongoDB nhanh hơn MySQL và Postgres, nhưng có một cơ hội nhỏ, như 1 trong một triệu, rằng nó "sẽ không lưu đúng".

Phần "sẽ không lưu đúng" đề cập đến sự hiểu biết này: Nếu có cúp điện ngay lập tức bạn đang viết cho MongoDB, có cơ hội cho một bản ghi cụ thể (nói rằng bạn đang theo dõi số lần truy cập trang trong các tài liệu có 10 thuộc tính), một trong các tài liệu chỉ lưu 5 thuộc tính… có nghĩa là theo thời gian, các số lần truy cập trang của bạn sẽ bị "tắt" một chút. Bạn sẽ không bao giờ biết được bao nhiêu, bạn biết chúng sẽ đúng 99.999%, nhưng không phải 100%. Điều này là do, trừ khi bạn đã thực hiện cụ thể điều này là mongodb atomic operation, 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 thời điểm và lý do tại sao MongoDB có thể không "lưu chính xác"? Những phần nào của ACID không thỏa mãn, và trong hoàn cảnh 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ể sửa được 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ư bảng users của bạn trong MongoDB, vì một bản ghi có thể không lưu. Nhưng sau đó một lần nữa, rằng 1/1.000.000 người dùng có thể chỉ cần "thử đăng ký lại", phả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 một cơ sở dữ liệu không tuân thủ ACID như MongoDB, và lý tưởng nếu có cách giải quyết 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 điều này). , v.v.)

Trả lời

111

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

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

tôi gặp phải vấn đề này rất trong một ứng dụng tôi đang làm việc trên và hai giải pháp có thể tồn tại:

1) Cấu trúc tài liệu của bạn một cách tốt nhất bạn có thể và sử dụng bổ nguyên tử một cách tốt nhất bạn có thể và cho ông còn lại chút, sử dụng một quá trình nền để dọn dẹp các bản ghi có thể không đồng bộ. Ví dụ: tôi xóa các mục khỏi khoảng không quảng cáo và thêm chúng vào mảng reservedInventory của cùng một tài liệu bằng cách sử dụng các công 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ục KHÔNG có sẵn trong khoảng không quảng cáo (vì chúng được đặt trước bởi khách hàng). Khi kiểm tra của khách hàng ra, tôi sau đó loại bỏ các mục từ reservedInventory. Nó 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 xe bị bỏ rơi và di chuyển khoảng không quảng cáo dự trữ trở lại vào kho lưu trữ 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 với nhu cầu một cách hoàn hảo. 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 trường hợp, nhưng vì cấu trúc tài liệu tôi đang sử dụng, nó 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ứ hoàn toàn cần chúng trong khi để MongoDB (hoặc bất kỳ NoSQL 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ừ # 1 không hoạt động trong thời gian dài, tôi sẽ điều tra thêm về 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.

+21

"* Bộ sửa đổi nguyên tử trong MongoDB chỉ có thể hoạt động dựa trên 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 ** đơn". – assylias

+1

Thông tin tuyệt vời, thường là một câu trả lời tuyệt vời với ngoại lệ đề xuất sử dụng MySQL. –

+0

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

31

Giải thích tốt được chứa trong "Starbucks Does Not Use Two Phase Commit".

Nó không phải về cơ sở dữ liệu NoSQL, 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 có cơ sở dữ liệu của bạn trong một trạng thái không nhất quán tạm thời.

Tôi sẽ không coi đó là thứ cần được "cố định". Khắc phục là sử dụng cơ sở dữ liệu quan hệ tuân thủ ACID. Bạn chọn phương án NoSQL khi hành vi của nó đáp ứng các yêu cầu ứng dụng của bạn.

+1

đẹp ví dụ thế giới thực – gbn

+1

Giống như bất kỳ loại suy nó có những hạn chế của nó. Trong phần mềm, nó rất dễ dàng để tạo ra Array mới [Nhân viên thu ngân] và có họ xử lý các giao dịch đồng bộ mỗi, trong khi chi phí thực tế của điều đó sẽ là ridiculously đắt tiền. – HRJ

11

"sẽ không tiết kiệm một cách chính xác" có thể có nghĩa:

  1. Theo mặc định MongoDB không lưu 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ể chờ cho (các) bản sao khác nhận bản cập nhật này (trong bộ nhớ), chờ ghi để xảy ra với tệp nhật ký cục bộ, v.v.

  2. Không có bản 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à một vấn đề trong hầu hết các trường hợp bởi vì nó có thể được phá vỡ với Two Phase Commit, hoặc tái cơ cấu lược đồ của bạn để cập nhật được thực hiện cho một tài liệu duy nhất. Xem câu hỏi này: Document Databases: Redundant data, references, etc. (MongoDB specifically)

15

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

+0

cảm ơn @subGate. bất cứ ai có thể chia sẻ kinh nghiệm của họ với ravenDB và nếu nó thực sự đáp ứng yêu cầu? –

5

Lý do duy nhất thay đổi nguyên tử hoạt động dựa trên một bộ sưu tập đơn là do các nhà phát triển mongodb gần đây đã trao đổi khóa cơ sở dữ liệu với bộ ghi khóa rộng . Quyết định rằng sự gia tăng đồng thời ở đây là giá trị thương mại-off. Tại lõi của nó, mongodb là một tệp ánh xạ bộ nhớ: chúng đã ủy quyền quản lý vùng đệm cho hệ thống con vm của máy. Bởi vì nó luôn luôn trong bộ nhớ, họ có thể để có được đi với khóa học khóa học rất: bạn sẽ được thực hiện trong bộ nhớ chỉ hoạt động trong khi giữ nó, mà sẽ rất nhanh. Điều này khác đá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 pagelock hoặc một rowlock.

+0

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

+0

@batbrat: Xem xét hai khách hàng cố gắng đồng thời viết thư cho các bộ sưu tập khác nhau trong cùng một cơ sở dữ liệu. Với một khóa cơ sở dữ liệu, một trong những khách hàng sẽ phải chờ người khác hoàn thành trước khi việc ghi của nó có thể xảy ra. Với khóa bộ sưu tập, cả hai máy khách đều có thể ghi 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 viết vào cùng một bộ sưu tập thì một người sẽ phải đợi. – jrullmann

108

Thực ra không đúng là MongoDB không tuân thủ ACID.Ngược lại, MongoDB là ACID-compilant ở cấp tài liệu.

Bất kỳ cập nhật cho một tài liệu duy nhất là

  • nguyên tử: nó hoặc là hoàn thành toàn bộ hoặc nó không
  • Phù hợp: không có người đọc sẽ thấy một "áp dụng một phần" cập nhật
  • Isolated: một lần nữa, không có người đọc sẽ thấy một "bẩn" đọc
  • Durable: (với sự quan tâm ghi thích hợp)

gì MongoDB không hav e là giao dịch - tức 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ể tạo 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, theo using two-phase commit.

+2

Câu trả lời rõ ràng nhất cho tôi – babonk

+3

Lưu ý rằng các giao dịch của các cam kết hai giai đoạn không tuân thủ ACID. Vì một lý do nào đó tôi suy ra điều ngược lại cho đến khi tôi theo liên kết. –

+1

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

4

Vui lòng đọc về số ACID properties để hiểu rõ hơn.

Cũng trong tài liệu MongoDB, bạn có thể tìm thấy question and answer.

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

  1. MongoDB là A chỉ ở mức tài liệu. Nó không tuân theo định nghĩa 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. Trong ý nghĩa này MongoDB không tuân thủ A từ ACID.
  2. MongoDB là C tiện ích theo mặc định. Tuy nhiên, bạn có thể đọc từ máy chủ phụ trong bộ bản sao. Bạn chỉ có thể có tính nhất quán 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 nhớ đọc dữ liệu hơi lỗi thời.
  3. MongoDB không đảm bảo I solation (một lần nữa theo định nghĩa ở trên):
  1. Đối với hệ thống với nhiều độc giả đồng thời và các nhà văn, MongoDB sẽ cho phép khách hàng để đọc kết quả của một hoạt động viết trước trả về hoạt động ghi.
  2. Nếu mongod chấm dứt trước khi tạp chí cam kết, ngay cả khi viết trả về thành công, 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ẽ thay đổi mỗi tài liệu trong sự cô lập (đối với chèn và cập nhật); ở 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 D urability - bạn có thể cấu hình hành vi này với tùy chọn write concern, không chắc chắn mặc dù. Có thể ai đó biết rõ hơn.

Tôi tin rằng một số nghiên cứu đang tiến hành để di chuyển NoSQL về 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 NoSQL thường nhanh (er) và các ràng buộc ACID có thể làm chậm hiệu suất đáng kể.

1

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

Tôi đã tạo một step-by-step visualization các giao dịch như vậy. Tôi hy vọng nó sẽ giúp bạn hiểu chúng.

Nếu bạn ổn với mức độ cách ly đã đọc cam kết thì bạn có thể xem RAMP transactions bởi Peter Bailis. Chúng cũng có thể được triển khai cho MongoDB ở phía máy khách.

2

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

Họ cảm thấy như 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-transactions-in-mongodb

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