Pada musim panas 2018 (yaitu, saat ini, pada saat penulisan ini), yang luar biasa terjadi - transaksi ACID yang jujur โโdibawa ke MongoDB . Dengan rilis versi keempat dari DBMS berorientasi dokumen ini, dapat digunakan untuk aplikasi yang sedikit lebih serius.
Bagi mereka yang berada di dalam tangki, singkatnya: transaksi memungkinkan kami untuk melakukan serangkaian perubahan dalam beberapa dokumen dan menyimpannya sekaligus, atau juga membatalkan semua perubahan yang dibuat dalam transaksi dengan cara yang sama, jika terjadi kesalahan, atau aplikasi macet. .
Sayangnya, pengembang tidak begitu mudah menggunakan fitur super ini. Di bawah ini saya akan memberi tahu Anda alasannya, dan apa yang harus dilakukan tentang itu semua.
Jika kita membuka dokumentasi untuk DBMS di bagian Transaksi , kita dapat melihat komentar berikut:
Transaksi multi-dokumen hanya tersedia untuk set replika. Transaksi-transaksi untuk kluster-kluster yang diarsir dijadwalkan untuk MongoDB 4.2
Ini memberitahu kita bahwa server MongoDB sederhana tidak mendukung transaksi, hanya sebuah cluster dalam mode set replika . Dukungan untuk klaster yang terbengkalai juga akan datang kemudian dalam versi 4.2.
Pada saat yang sama, server normal akan membiarkan kami memulai transaksi, menyimpannya, atau membatalkannya, tetapi tidak ada yang dapat dilakukan di dalamnya, kesalahan seperti ini akan ditampilkan:
WriteCommandError({ : 0, : , : 20, : })
Untungnya, siapa pun dapat menjalankan kluster MongoDB server tunggal. Pada mesin saya, yang saya gunakan dalam pengembangan, saya menjalankan semua DBMS dalam wadah buruh pelabuhan . Misalnya, memulai server MongoDB biasa terlihat seperti ini:
docker run -v ~/mongo/:/data/db --name mongo --restart=always -p 27017:27017 -d mongo mongod --smallfiles
Mari kita menganalisis kunci startup:
- -v ~ / mongo /: / data / db berarti me-mount direktori lokal ~ / mongo / in / data / db wadah, sehingga database itu sendiri akan disimpan pada mesin host, yang akan memungkinkan kita untuk menghapus wadah yang sedang berjalan, memperbarui versi, dll. d. dengan pelestarian data kami;
- --name mongo menetapkan nama wadah;
- --restart = selalu mengatakan bahwa dalam hal terjadi kerusakan layanan dalam wadah, itu harus dimulai kembali, serta memulai wadah setelah memuat sistem operasi;
- -p 27017: 27017 โmeneruskanโ port ke mesin host;
- -d menunjukkan bahwa Anda harus memulai wadah sebagai daemon;
- mongo - nama gambar untuk menjalankan wadah;
- mongod --smallfiles - perintah untuk memulai layanan dalam wadah.
Cara memulai server sederhana, saya bawa hanya untuk referensi. Sekarang mari kita mengerti apa yang perlu dilakukan untuk memulai server yang mendukung transaksi.
Pertama-tama, Anda harus membuat jaringan baru di dalam buruh pelabuhan, di mana semua server kluster kami akan bekerja. Ya, saya menulis di atas bahwa akan ada satu server, tetapi jaringan harus dibuat, jika tidak tidak ada yang akan berhasil.
docker network create mongo-cluster
Selanjutnya, dalam parameter peluncuran wadah, Anda perlu menentukan penggunaan jaringan baru --net mongo-cluster , dan juga meneruskan parameter ke server untuk bekerja dalam mode set replika: --replSet rs0 . Juga, saya sengaja menghapus --restart = selalu aktif , as Saya tidak selalu menggunakan MongoDB di tempat kerja saat ini dan saya tidak ingin memulainya dengan sistem operasi.
docker run -v ~/mongo/:/data/db --name mongo -p 27017:27017 -d mongo mongod --smallfiles --replSet rs0
Hebat, wadah sedang berjalan, seperti yang bisa kita lihat dengan menjalankan perintah buruh pelabuhan ps dan melihat sesuatu seperti berikut:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2292d7e0778b mongo "docker-entrypoint.sโฆ" About a minute ago Up About a minute 0.0.0.0:27017->27017/tcp mongo
Selanjutnya, kita perlu menginisialisasi cluster, untuk ini kita masuk ke konsol server yang sedang berjalan, membuat konfigurasi cluster kami dan melakukan inisialisasi:
docker exec -it mongo mongo
Selesai! Kami mendapat kluster dari satu server MongoDB. Sekarang Anda dapat memverifikasi bahwa semuanya berfungsi seperti yang diharapkan.
rs0:PRIMARY> session = db.getMongo().startSession() session { "id" : UUID("7eb81006-983f-4398-adc7-5ed23e027377") } rs0:PRIMARY> database = session.getDatabase("test") test rs0:PRIMARY> // rs0:PRIMARY> database.col.insert({name: "1"}) WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> database.col.insert({name: "2"}) WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> database.col.insert({name: "3"}) WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> database.col.insert({name: "4"}) WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> // , rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "1" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "4" } rs0:PRIMARY> // rs0:PRIMARY> session.startTransaction() rs0:PRIMARY> // rs0:PRIMARY> database.col.update({name: "4"}, {name: "44"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) rs0:PRIMARY> // rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "1" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "44" } rs0:PRIMARY> // , -: rs0:PRIMARY> // { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "4" } rs0:PRIMARY> // rs0:PRIMARY> session.commitTransaction() rs0:PRIMARY> // rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "1" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "44" } rs0:PRIMARY> // rs0:PRIMARY> session.startTransaction() rs0:PRIMARY> database.col.update({name: "44"}, {name: "42"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "1" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "42" } rs0:PRIMARY> database.col.update({name: "1"}, {name: "21"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "21" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "42" } rs0:PRIMARY> session.commitTransaction() rs0:PRIMARY> // rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "21" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "42" } rs0:PRIMARY> // , rs0:PRIMARY> session.startTransaction() rs0:PRIMARY> database.col.update({name: "21"}, {name: "1"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "1" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "42" } rs0:PRIMARY> // rs0:PRIMARY> session.abortTransaction() rs0:PRIMARY> database.col.find({}) { "_id" : ObjectId("5b45026edc396f534f11952f"), "name" : "21" } { "_id" : ObjectId("5b450272dc396f534f119530"), "name" : "2" } { "_id" : ObjectId("5b450274dc396f534f119531"), "name" : "3" } { "_id" : ObjectId("5b450276dc396f534f119532"), "name" : "42" } rs0:PRIMARY> // ! ! rs0:PRIMARY>
Dengan demikian, tanpa melelahkan, Anda dapat mencoba transaksi Mong sekarang juga tanpa memulai multiserver cluster. Saya menyarankan Anda untuk melihat dokumentasi dan membaca tentang batasan transaksi. Misalnya, transaksi itu "hidup" selama tidak lebih dari 1 menit, jika Anda tidak berhasil menyimpan perubahan, itu akan dibatalkan.
PS: tujuan artikel ini bukan untuk mengajari Anda cara menggunakan buruh pelabuhan atau bekerja dengan monga, tetapi hanya cara cepat untuk mencoba alat baru dari DBMS yang menarik ini.