Rumah >pembangunan bahagian belakang >Golang >Adakah amalan yang baik untuk meninggalkan pengembalian transaksi mongodb apabila ralat?

Adakah amalan yang baik untuk meninggalkan pengembalian transaksi mongodb apabila ralat?

WBOY
WBOYke hadapan
2024-02-06 10:12:08485semak imbas

在发生错误时省略 mongodb 事务回滚是一个好习惯吗

Kandungan soalan

Saya menggunakan pemandu golanggo.mongodb.org/mongo-driver/mongo untuk mempelajari transaksi mongodb. Saya mengikuti ini jadi jawapan dan contoh ini di github.

Contoh kod diberikan oleh @simagix:

if session, err = client.StartSession(); err != nil {
    t.Fatal(err)
}
if err = session.StartTransaction(); err != nil {
    t.Fatal(err)
}
if err = mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error {
    if result, err = collection.UpdateOne(sc, bson.M{"_id": id}, update); err != nil {
        t.Fatal(err)
    }
    if result.MatchedCount != 1 || result.ModifiedCount != 1 {
        t.Fatal("replace failed, expected 1 but got", result.MatchedCount)
    }

    // more interrelated operations ...

    if err = session.CommitTransaction(sc); err != nil {
        t.Fatal(err)
    }
    return nil
}); err != nil {
    t.Fatal(err)
}
session.EndSession(ctx)

Dalam kedua-dua contoh, mereka tidak akan berundur jika ralat berlaku. Saya tahu ini adalah contoh demo. Tetapi apabila saya melakukan perkara yang sama dalam kod, ia berfungsi dengan baik.

Adakah mungkin untuk mengetepikan rollback apabila ralat berlaku (adakah pemandu mengendalikannya)? Atau adakah saya kehilangan sesuatu?


Jawapan betul


mongo.withsession() tidak menganggap sebarang transaksi aktif, ia "hanya" membantu menjalankan panggilan balik di bawah sesi tertentu. Oleh itu, jika anda mahu ia dilaksanakan sebagai sebahagian daripada urus niaga yang dimulakan, anda harus mengendalikan komit dan menggugurkan sendiri. Ini membolehkan kawalan yang lebih halus.

Walau bagaimanapun, jika anda bercadang untuk menjalankan panggilan balik sebagai transaksi, gunakan session.withtransaction() kerana ia mengendalikan urus niaga dan kitaran hayatnya dengan cara yang telus: ia mencipta urus niaga dan melakukan atau membatalkannya berdasarkan ralat yang dikembalikan oleh panggilan balik. Sebagai ciri tambahan, ia juga boleh mengendalikan percubaan semula. Seperti yang ditunjukkan oleh dokumentasinya:

Jika panggilan balik gagal, pemandu akan memanggil aborttransaction.

Berikut ialah contoh mudah cara melaksanakan panggilan balik dengan betul dalam transaksi:

var docToInsert, idToUpdate, updateDoc any

func doInTransactionExample(ctx context.Context, client *mongo.Client) error {
    sess, err := client.StartSession(options.Session().SetDefaultReadConcern(readconcern.Majority()))
    if err != nil {
        return fmt.Errorf("client.StartSession() error: %w", err)
    }
    defer sess.EndSession(ctx)

    result, err := sess.WithTransaction(
        ctx,
        func(sessCtx mongo.SessionContext) (any, error) {
            // sessCtx must be used as context.Context for all operations to be run in the transaction.
            var ctx context.Context = sessCtx // Shadow ctx on purpose!

            c := client.Database("foo").Collection("bar")

            // Insert example
            if _, err := c.InsertOne(ctx, docToInsert); err != nil {
                return nil, fmt.Errorf("InsertOne() failed: %w", err)
            }

            // Update example
            if ur, err := c.UpdateByID(ctx, idToUpdate, updateDoc); err != nil {
                return nil, fmt.Errorf("UpdateByID() failed: %w", err)
            } else {
                if ur.MatchedCount == 0 {
                    return nil, fmt.Errorf("UpdateByID() failed: %w", mongo.ErrNoDocuments)
                }
            }

            return "arbitrary-result-to-return", nil
        },
        options.Transaction().SetReadPreference(readpref.PrimaryPreferred()),
    )

    if err != nil {
        return fmt.Errorf("sess.WithTransaction() error: %w", err)
    }

    _ = result // Not using result

    return nil
}

Atas ialah kandungan terperinci Adakah amalan yang baik untuk meninggalkan pengembalian transaksi mongodb apabila ralat?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam