Mongodb cập nhật đồng thời cùng một tài liệu

Mongo không hỗ trợ các hạt nhận dạng (như oracle hoặc mssql), để đơn giản hóa vấn đề này - có thể các thông báo có thể được lưu trữ bên trong mảng không?

message: [
   {msg:"my message", dateTime:2016-04-29 11:22:45.9950},
   {msg:"your message", dateTime:2016-04-29 11:22:46.0110} 
]

$push -ing một mục sẽ luôn thêm nó vào cuối mảng và sau đó bạn có thể lấy phiên bản theo chỉ mục mảng của thông báo không?

Để nhận tin nhắn cuối cùng, hãy sử dụng $slice. -1

Để tránh tạo rãnh cấu trúc dữ liệu - nếu bạn cần có tất cả các phiên bản - dữ liệu cần phát triển. Nếu bạn có thể giữ n cuối cùng - thì hãy tạo một công việc sẽ xóa các mục đầu tiên (đại loại như bộ sưu tập được giới hạn - nhưng trong trường hợp này là mảng bị giới hạn)

CHỈNH SỬA

vui lòng tìm thảo luận

Có một trường hợp cạnh nếu trường bạn đang sắp xếp không phải lúc nào cũng là duy nhất và sau đó nó không được đảm bảo (ít nhất là không thể làm rõ điều đó) rằng thứ tự được trả về sẽ luôn giống nhau

Để cập nhật, chỉ cần sử dụng update(). Sử dụng toán tử $push để nối thêm một giá trị đã chỉ định và ký hiệu dấu chấm để tiếp cận bộ sưu tập phụ và cập nhật bên trong update()

Hãy để chúng tôi tạo một bộ sưu tập với các tài liệu -

> db.demo547.insertOne(
.. {
..    Name : "Chris",
..    Test :
..    {
..       "FirstTest" :
..       {
..          Scores: [56,29,76]
..       },
..       "SecondTest" :
..       {
..          Scores: [98,91,78]
..       }
..    }
.. }
.. );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e8e2d579e5f92834d7f05dd")
}

Hiển thị tất cả các tài liệu từ một bộ sưu tập với sự trợ giúp của phương thức find() -

> db.demo547.find();

Điều này sẽ tạo ra đầu ra sau -

{ "_id" : ObjectId("5e8e2d579e5f92834d7f05dd"), "Name" : "Chris", "Test" : { "FirstTest" : {
"Scores" : [ 56, 29, 76 ] }, "SecondTest" : { "Scores" : [ 98, 91, 78 ] } } }

Sau đây là truy vấn cập nhật đồng thời với bộ sưu tập con -

> db.demo547.update({"Name":"Chris"}, { $push:{ "Test.FirstTest.Scores" : 99}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

Hiển thị tất cả các tài liệu từ một bộ sưu tập với sự trợ giúp của phương thức find() -

> db.demo547.find();

Điều này sẽ tạo ra đầu ra sau -

{ "_id" : ObjectId("5e8e2d579e5f92834d7f05dd"), "Name" : "Chris", "Test" : { "FirstTest" : {
"Scores" : [ 56, 29, 76, 99 ] }, "SecondTest" : { "Scores" : [ 98, 91, 78 ] } } }

Mongodb cập nhật đồng thời cùng một tài liệu


Mongodb cập nhật đồng thời cùng một tài liệu

Hiện tại tôi đã có một số dự án đã sử dụng MongoDB và mỗi lần, tôi cần tìm hiểu sâu về hỗ trợ giao dịch. Nhưng ngoài hỗ trợ giao dịch, tôi cần hiểu các mô hình đồng thời và khóa của Mongo. Không giống như nhiều cơ sở dữ liệu NoSQL khác, Mongo có các khóa ở cấp toàn cầu, cơ sở dữ liệu hoặc bộ sưu tập, nhưng không phải ở cấp tài liệu (hoặc cấp hàng, như SQL)

Nếu hai quy trình đọc một tài liệu, thì hãy cập nhật tài liệu đó, miễn là những cập nhật đó không xung đột với nhau thì cả hai sẽ thành công và chúng tôi sẽ có khả năng mất dữ liệu

Mongo đã hoàn thành rất nhiều việc để tăng cường câu chuyện phân tán của nó (xem phân tích của Jepsen), nó không có hỗ trợ tích hợp để kiểm soát đồng thời lạc quan ở cấp độ tài liệu. Với SQL Server, bạn có thể sử dụng Snapshot Isolation để đảm bảo không có quy trình nào khác sửa đổi dữ liệu kể từ khi bạn đọc. Với Cosmos DB, được sử dụng để kiểm tra phiên bản của tài liệu đang được viết so với. những gì tồn tại

May mắn thay, việc triển khai kiểm soát đồng thời lạc quan ở cấp độ tài liệu khá đơn giản. Nhưng trước tiên, hãy chứng minh rằng nếu không có OCC, chúng ta có thể viết xấu

không có OCC

Để bắt đầu, tôi sẽ tạo một tài liệu rất đơn giản, chỉ một mã định danh và một bộ đếm

public class Counter
{
    public Guid Id { get; set; }
    public int Value  { get; set; }
}

Tôi sẽ thực hiện một số tác vụ để tăng giá trị của bộ đếm, theo dõi số lần ghi và giá trị cuối cùng

________số 8_______

Mỗi lượt, tôi tải tài liệu lên và tăng giá trị lên 1. Tuy nhiên, tôi có thể có nhiều tác vụ thực thi cùng một lúc, vì vậy hai tác vụ có thể đọc cùng một giá trị, nhưng chỉ tăng thêm 1. Để buộc ghi kép, tôi tiếp tục cập nhật cho đến khi khóa bộ sưu tập được giải phóng. Trong một kịch bản trong thế giới thực, sẽ có sự chậm trễ giữa các lần đọc/ghi sẽ gây ra sự cố này

Khi tôi chạy cái này, tôi sẽ thấy giá trị ban đầu là 0, giá trị cuối cùng là 100 và số lượng đã sửa đổi là 100. Nhưng tôi thì không, bởi vì một số giá trị ghi đè lẫn nhau

Before  : 1
After   : 92
Modified: 100

Tôi đã sửa đổi 100 lần, nhưng bộ đếm chỉ thực hiện tới 92. Hãy thêm một số đồng thời lạc quan để cải thiện mọi thứ

Với OCC

Một số triển khai của OCC sử dụng dấu thời gian, nhưng điều đó thường không đủ chính xác, vì vậy, thay vào đó, tôi đang sử dụng bộ đếm đơn điệu làm phiên bản của mình. Nó bắt đầu từ số không và đi lên từ đó

public class Counter
{
    public Guid Id { get; set; }
    public int Version { get; set; }
    public int Value  { get; set; }
}

Thiết kế phiên bản phức tạp hơn một chút, tôi chỉ giữ mọi thứ đơn giản nhưng chúng ta có thể phức tạp như chúng ta muốn. Bây giờ khi tôi cập nhật, tôi sẽ đảm bảo rằng tôi tăng cả bộ đếm và phiên bản của mình và khi tôi gửi bản cập nhật, tôi sẽ bao gồm một điều khoản bổ sung so với phiên bản đã đọc ban đầu

var tasks = Enumerable.Range(0, 100).Select(async i =>
{
    var loaded = await collection.AsQueryable().Where(doc => doc.Id == id).SingleAsync();
    var version = loaded.Version;

    loaded.Value++;
    loaded.Version++;

    var result = await collection.ReplaceOneAsync(
        c => c.Id == id && c.Version == version, 
        loaded, new UpdateOptions { IsUpsert = false });

    return result;
}).ToList();

Tôi đã xóa "thử lại" để đảm bảo rằng tôi không bị ghi đè và với điều này, các giá trị cuối cùng sẽ xếp hàng

Before  : 0
After   : 92
Modified: 92

Tuy nhiên, nếu tôi thực sự muốn đảm bảo rằng tôi thực sự nhận được tất cả các bản cập nhật đó, thì tôi cần thử lại toàn bộ thao tác

var tasks = Enumerable.Range(0, 100).Select(async i =>
{
    ReplaceOneResult result;

    do
    {
        var loaded = await collection.AsQueryable()
                           .Where(doc => doc.Id == id)
                           .SingleAsync();
        var version = loaded.Version;

        loaded.Value++;
        loaded.Version++;

        result = await collection.ReplaceOneAsync(
            c => c.Id == id && c.Version == version, loaded,
            new UpdateOptions {IsUpsert = false});
    } while (result.ModifiedCount != 1);

    return result;
}).ToList();

Với một lần thử lại đơn giản tại chỗ, tôi đảm bảo rằng tôi tải lại tài liệu được đề cập, nhận phiên bản làm mới và bây giờ tất cả các số của tôi cộng lại

Before  : 0
After   : 100
Modified: 100

Chính xác những gì tôi đang tìm kiếm

Một giải pháp chung

Điều này chỉ hoạt động tốt nếu tôi "nhớ" bao gồm chính xác mệnh đề Where đó, nhưng có một cách tốt hơn nếu chúng ta muốn một giải pháp chung. Để làm được điều đó, tôi sẽ làm gần như những gì tôi sẽ có trong loạt bài Life Beyond Distributed Transactions - giới thiệu Kho lưu trữ, Đơn vị công việc và Bản đồ nhận dạng. Tất cả những điều này có thể bắt đầu rất đơn giản, nhưng tôi có thể gói gọn tất cả việc kiểm tra/quản lý phiên bản trong các đối tượng này thay vì buộc tất cả người dùng phải nhớ bao gồm mệnh đề Where đó

Nếu thậm chí có khả năng từ xa rằng bạn sẽ thấy các bản cập nhật đồng thời, thì bạn có thể sẽ đi theo con đường đồng thời lạc quan. May mắn thay, một giải pháp cơ bản không phải là nhiều mã

MongoDB xử lý đồng thời như thế nào?

MongoDB cho phép nhiều client đọc và ghi cùng một dữ liệu. Để đảm bảo tính nhất quán, MongoDB sử dụng khóa và kiểm soát đồng thời để ngăn khách hàng sửa đổi cùng một dữ liệu . Ghi vào một tài liệu duy nhất xảy ra đầy đủ hoặc không ghi và khách hàng luôn thấy dữ liệu nhất quán.

MongoDB có thể xử lý bao nhiêu yêu cầu đồng thời?

Dịch vụ ứng dụng giới hạn lưu lượng yêu cầu ở 5.000 yêu cầu đồng thời .

Hai tài liệu có thể có cùng ID trong MongoDB không?

Nếu nhiều tài liệu được tạo cùng lúc, trên cùng một máy và cùng một quy trình, hai tài liệu có thể chia sẻ cùng một ID đối tượng.

MongoDB có hỗ trợ giao dịch nhiều tài liệu không?

Đối với các tình huống yêu cầu tính nguyên tử của việc đọc và ghi vào nhiều tài liệu (trong một hoặc nhiều bộ sưu tập), MongoDB hỗ trợ giao dịch nhiều tài liệu . Với các giao dịch phân tán, các giao dịch có thể được sử dụng trên nhiều hoạt động, bộ sưu tập, cơ sở dữ liệu, tài liệu và phân đoạn.