现在如何在MongoDB中感受交易

在2018年夏天(即目前,在撰写本文时),令人难以置信的事情发生了-诚实的ACID交易被引入MongoDB中 。 随着此面向文档的DBMS的第四个版本的发布,它可以用于稍微更严格的应用程序。


简而言之,对于那些处于困境中的人:交易使我们能够对多个文档进行一系列更改并立即保存它们,或者在出现问题或应用程序崩溃时也以相同的方式取消交易中所做的所有更改。


不幸的是,开发人员使用此超级功能并不容易。 下面,我将告诉您原因以及如何处理。


如果在“ 事务”部分中打开DBMS的文档,则可以看到以下注释:


多文档事务仅适用于副本集。 分片群集的事务计划在MongoDB 4.2中进行

这告诉我们,简单的MongoDB服务器不支持事务,仅支持副本集模式下的集群。 对分片群集的支持也将在4.2版以后提供。


同时,普通服务器将允许我们开始交易,保存交易或取消交易,但其中无法执行任何操作,将显示如下错误:


WriteCommandError({ "ok" : 0, "errmsg" : "Transaction numbers are only allowed on a replica set member or mongos", "code" : 20, "codeName" : "IllegalOperation" }) 

幸运的是,任何人都可以运行单服务器MongoDB集群。 在我从事开发工作的机器上,我在docker容器中运行所有DBMS。 例如,启动常规的MongoDB服务器如下所示:


 docker run -v ~/mongo/:/data/db --name mongo --restart=always -p 27017:27017 -d mongo mongod --smallfiles 

让我们分析启动键:


  • -v〜/ mongo /:/ data / db表示将本地目录〜/ mongo /安装在容器的/ data / db中 ,因此数据库本身将存储在主机上,这将允许我们删除正在运行的容器,更新版本等。 d。 保存我们的数据;
  • --name mongo设置容器的名称;
  • --restart =始终表示在容器中发生任何服务崩溃的情况下,应重新启动它,以及在加载操作系统后启动容器;
  • -p 27017:27017将端口“转发”到主机;
  • -d表示您需要将容器作为守护程序启动;
  • mongo-运行容器的图像的名称;
  • mongod --smallfiles-用于在容器中启动服务的命令。

如何启动一个简单的服务器,我带来仅供参考。 现在,让我们了解启动启动支持事务的服务器需要做什么。


首先,您应该在docker内部创建一个新网络,集群中的所有服务器都将在其中运行。 是的,我在上面写道,将有一台服务器,但是必须创建一个网络,否则将无法工作。


 docker network create mongo-cluster 

接下来,在容器启动参数中,您需要指定使用新的网络--net mongo-cluster ,并将该参数传递给服务器以在副本集模式下工作:-- replSet rs0 。 另外,我故意省略了--restart = always开关,因为 目前,我并不总是在工作中使用MongoDB,也不希望它从操作系统开始。


 docker run -v ~/mongo/:/data/db --name mongo -p 27017:27017 -d mongo mongod --smallfiles --replSet rs0 

很好,容器正在运行,正如我们通过运行docker ps命令并看到类似以下内容所看到的:


 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 

接下来,我们需要初始化集群,为此,我们进入正在运行的服务器的控制台,创建集群的配置并执行初始化:


 docker exec -it mongo mongo # output omited # > config = { "_id" : "rs0", "members" : [ { "_id" : 0, "host" : "mongo:27017" } ] } > rs.initiate(config) { "ok" : 1, "operationTime" : Timestamp(1531248932, 1), "$clusterTime" : { "clusterTime" : Timestamp(1531248932, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } rs0:SECONDARY> rs0:PRIMARY> 

做完了! 我们从一台MongoDB服务器获得了一个集群。 现在,您可以验证一切正常。


 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> 

因此,无需费劲,您可以立即尝试Mong事务,而无需启动多服务器集群。 我建议您查看文档并阅读有关交易限制的信息。 例如,该事务“生效”的时间不超过1分钟,如果您不设法保存更改,则它们将被取消。


PS:本文的目的不是要教您如何使用docker或与monga一起使用,而只是教您尝试使用此有趣的DBMS的新工具的快速方法。

Source: https://habr.com/ru/post/zh-CN417131/


All Articles