老衲不吃肉 發表於 2020-4-15 21:57:00

【Mongodb】事务

<p>&nbsp;</p>
<p class="ws-title">概述</p>
<div class="ws-content">
<ul>
<li>Mongodb 4.0 支持副本集的多文档事务</li>
<li>Mongodb 4.2 支持分片集群的多文档事务</li>
</ul>
<p class="line" data-line="5">单个Server是不支持使用事务,所以要学习事务,需要搭建一个副本集/分片集群</p>
<p class="line" data-line="7">另外需要说明是,单个文档操作是原子操作,而mongodb是文档型数据库,在单个文档上,可以嵌入对象/数组这种格式来维护数据的关系,而不应该使用多个集合来维护数据之间的关系。由于mongodb的这种特性,所以单个文档操作消除了很多需要事务的需求。</p>
<p>&nbsp;</p>
</div>
<p class="ws-title">搭建副本集</p>
<div class="ws-content">
<p class="line" data-line="11">下面以最简单的方式搭建一个副本集</p>
<p>1.&nbsp; 启动多个mongod实例,这里使用cmd命令启动</p>
<div class="cnblogs_code">
<pre>start <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Mongodb Service - 27017</span><span style="color: rgba(128, 0, 0, 1)">"</span> /min mongod --port <span style="color: rgba(128, 0, 128, 1)">27017</span> --replSet <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rs0</span><span style="color: rgba(128, 0, 0, 1)">"</span> --dbpath <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">F:\Database\Mongodb\Data27017</span><span style="color: rgba(128, 0, 0, 1)">"</span> --logpath <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">F:\Database\Mongodb\Log\mongod.27017.log</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
start </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Mongodb Service - 27018</span><span style="color: rgba(128, 0, 0, 1)">"</span> /min mongod --port <span style="color: rgba(128, 0, 128, 1)">27018</span> --replSet <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rs0</span><span style="color: rgba(128, 0, 0, 1)">"</span> --dbpath <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">F:\Database\Mongodb\Data27018</span><span style="color: rgba(128, 0, 0, 1)">"</span> --logpath <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">F:\Database\Mongodb\Log\mongod.27018.log</span><span style="color: rgba(128, 0, 0, 1)">"</span></pre>
</div>
<p class="line" data-line="18">参数说明</p>
<ul>
<li>replSet : 设置副本集名称</li>
<li>port : 设置端口,因为我是单机,所以只能设置不同端口</li>
<li>dbpath: 数据文件路径,注:文件夹必须是存在,mongod不会自动创建</li>
<li>logpath: 日志文件名称,这个不需要提前新建,若不存在mongod会自动创建</li>
</ul>
<p>2.&nbsp;&nbsp;连接任意一个实例,这里就选择27017这个默认端口</p>
<div class="cnblogs_code">
<pre>mongo</pre>
</div>
<p>&nbsp;</p>
<p>3.&nbsp;启动副本集</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">rs.initiate({
    _id: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rs0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    members: [
      { _id: </span><span style="color: rgba(128, 0, 128, 1)">0</span>, host: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">127.0.0.1:27017</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> },
      { _id: </span><span style="color: rgba(128, 0, 128, 1)">1</span>, host: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">127.0.0.1:27018</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
    ]
})</span></pre>
</div>
<p class="line" data-line="38">参数说明</p>
<ul>
<li>_id : 副本集名称,就是启动实例时指定那个名称</li>
<li>members : 这个就是所有成员,_id每个成员的标识,整数型</li>
</ul>
<p class="line" data-line="42">返回字段"ok" : 1 代表创建成功</p>
<p class="line" data-line="44">rs.initiate({}),这里除了几个必须的,都是使用默认配置去启动,更多配置参数可以参考replica-configuration</p>
<p>&nbsp;</p>
<p>4.&nbsp;查看当前配置信息</p>
<div class="cnblogs_code">
<pre>rs.conf()</pre>
</div>
<p>&nbsp;</p>
<p>5.&nbsp;查看副本集信息</p>
<div class="cnblogs_code">
<pre>rs.status()</pre>
</div>
<p class="line" data-line="56">&nbsp;</p>
<p class="line" data-line="56">到这,副本集就搭建完成</p>
<p>&nbsp;</p>
</div>
<p class="ws-title">事务</p>
<div class="ws-content">
<p>1. 连接副本集</p>
<div class="cnblogs_code">
<pre>mongo mongodb:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">127.0.0.1:27017,127.0.0.1:27018/?replicaSet=rs0</span></pre>
</div>
<p>可以直接连接主副本的实例,也可以用这种url形式可以自动连接主副本(推荐使用后者)</p>
<p>&nbsp;</p>
<p>2.&nbsp;准备2条数据</p>
<div class="cnblogs_code">
<pre>db.balance.insert({ name: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span>, balance: <span style="color: rgba(128, 0, 128, 1)">100</span> }, { writeConcern: { <span style="color: rgba(0, 0, 255, 1)">w</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">majority</span><span style="color: rgba(128, 0, 0, 1)">"</span>, wtimeout: <span style="color: rgba(128, 0, 128, 1)">2000</span><span style="color: rgba(0, 0, 0, 1)"> } });
db.record.insert({ name: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span>, change: <span style="color: rgba(128, 0, 128, 1)">100</span>, balance: <span style="color: rgba(128, 0, 128, 1)">100</span>, }, { writeConcern: { <span style="color: rgba(0, 0, 255, 1)">w</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">majority</span><span style="color: rgba(128, 0, 0, 1)">"</span>, wtimeout: <span style="color: rgba(128, 0, 128, 1)">2000</span> } });</pre>
</div>
<p>&nbsp;</p>
<p><strong>测试正常提交</strong></p>
<p>模拟一个扣钱动作,其中扣款和流水在一个事务里</p>
<div class="cnblogs_code">
<pre>session = db.getMongo().startSession({ readPreference: { mode: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">primary</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> } });
balanceCol </span>= session.getDatabase(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mongo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">).balance;
recordCol </span>= session.getDatabase(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mongo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">).record;
session.startTransaction({ readConcern: { level: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">local</span><span style="color: rgba(128, 0, 0, 1)">"</span> }, writeConcern: { <span style="color: rgba(0, 0, 255, 1)">w</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">majority</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> } });

try {
    balanceCol.updateOne({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span> }, { $set: { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">50</span><span style="color: rgba(0, 0, 0, 1)"> } });
    recordCol.insertOne({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span>, change: -<span style="color: rgba(128, 0, 128, 1)">50</span>, balance: <span style="color: rgba(128, 0, 128, 1)">50</span><span style="color: rgba(0, 0, 0, 1)"> });
} catch (error) {
    session.abortTransaction();
}
session.commitTransaction();
session.endSession();</span></pre>
</div>
<p>&nbsp;</p>
<p>查看余额情况</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">db.balance.aggregate([
    { $lookup: { from: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">record</span><span style="color: rgba(128, 0, 0, 1)">"</span>, localField: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, foreignField: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, as: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> } },
    { $project: { </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs._id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs.name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> } },
]);</span></pre>
</div>
<p>结果,可以看到余额扣了,多了一条流水</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">50</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs</span><span style="color: rgba(128, 0, 0, 1)">"</span> : [ { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">change</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">100</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">100</span> }, { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">change</span><span style="color: rgba(128, 0, 0, 1)">"</span> : -<span style="color: rgba(128, 0, 128, 1)">50</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">50</span> } ] }</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>测试失败回滚</strong></p>
<p>事务内多增加一个插入不存在的集合操作,让事务报错</p>
<div class="cnblogs_code">
<pre>session.startTransaction({ readConcern: { level: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">local</span><span style="color: rgba(128, 0, 0, 1)">"</span> }, writeConcern: { <span style="color: rgba(0, 0, 255, 1)">w</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">majority</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> } });
try {
    balanceCol.updateOne({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span> }, { $set: { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span>: -<span style="color: rgba(128, 0, 128, 1)">50</span><span style="color: rgba(0, 0, 0, 1)"> } });
    recordCol.insertOne({ </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span>, change: -<span style="color: rgba(128, 0, 128, 1)">50</span>, balance: <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> });
    session.getDatabase(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mongo</span><span style="color: rgba(128, 0, 0, 1)">"</span>).user.insert({ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">time</span><span style="color: rgba(128, 0, 0, 1)">"</span>: new Date() });    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">多增加操作一个不存在的表</span>
<span style="color: rgba(0, 0, 0, 1)">} catch (error) {
    session.abortTransaction();
    throw error;
}
session.commitTransaction();
session.endSession();</span></pre>
</div>
<p>&nbsp;</p>
<p class="line" data-line="114">返回报错信息,显示事务被中断了</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 128, 1)">2020</span>-<span style="color: rgba(128, 0, 128, 1)">04</span>-15T21:<span style="color: rgba(128, 0, 128, 1)">37</span>:<span style="color: rgba(128, 0, 128, 1)">05.576</span>+<span style="color: rgba(128, 0, 128, 1)">0800</span><span style="color: rgba(0, 0, 0, 1)"> EQUERY    uncaught exception: Error: command failed: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">errorLabels</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> : [
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">TransientTransactionError</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
      ],
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">operationTime</span><span style="color: rgba(128, 0, 0, 1)">"</span> : Timestamp(<span style="color: rgba(128, 0, 128, 1)">1586957825</span>, <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">),
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ok</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">errmsg</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Transaction 0 has been aborted.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">code</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">251</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">codeName</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">NoSuchTransaction</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">$clusterTime</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> : {
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">clusterTime</span><span style="color: rgba(128, 0, 0, 1)">"</span> : Timestamp(<span style="color: rgba(128, 0, 128, 1)">1586957825</span>, <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">),
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">signature</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> : {
                        </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hash</span><span style="color: rgba(128, 0, 0, 1)">"</span> : BinData(<span style="color: rgba(128, 0, 128, 1)">0</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AAAAAAAAAAAAAAAAAAAAAAAAAAA=</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">),
                        </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">keyId</span><span style="color: rgba(128, 0, 0, 1)">"</span> : NumberLong(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
                }
      }
} :
_getErrorWithCode@src</span>/mongo/shell/utils.js:<span style="color: rgba(128, 0, 128, 1)">25</span>:<span style="color: rgba(128, 0, 128, 1)">13</span><span style="color: rgba(0, 0, 0, 1)">
doassert@src</span>/mongo/shell/assert.js:<span style="color: rgba(128, 0, 128, 1)">18</span>:<span style="color: rgba(128, 0, 128, 1)">14</span><span style="color: rgba(0, 0, 0, 1)">
_assertCommandWorked@src</span>/mongo/shell/assert.js:<span style="color: rgba(128, 0, 128, 1)">583</span>:<span style="color: rgba(128, 0, 128, 1)">17</span><span style="color: rgba(0, 0, 0, 1)">
assert.commandWorked@src</span>/mongo/shell/assert.js:<span style="color: rgba(128, 0, 128, 1)">673</span>:<span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">
commitTransaction@src</span>/mongo/shell/session.js:<span style="color: rgba(128, 0, 128, 1)">971</span>:<span style="color: rgba(128, 0, 128, 1)">17</span><span style="color: rgba(0, 0, 0, 1)">
@(shell):</span><span style="color: rgba(128, 0, 128, 1)">1</span>:<span style="color: rgba(128, 0, 128, 1)">1</span></pre>
</div>
<pre></pre>
<p class="line" data-line="140">再查看当前余额情况</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">db.balance.aggregate([
    { $lookup: { from: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">record</span><span style="color: rgba(128, 0, 0, 1)">"</span>, localField: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, foreignField: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, as: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> } },
    { $project: { </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs._id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs.name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> } },
]);</span></pre>
</div>
<p class="line" data-line="150">可以看到,余额和流水都没变化。</p>
<div class="cnblogs_code">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Wilson</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">50</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">changs</span><span style="color: rgba(128, 0, 0, 1)">"</span> : [ { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">change</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">100</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">100</span> }, { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">change</span><span style="color: rgba(128, 0, 0, 1)">"</span> : -<span style="color: rgba(128, 0, 128, 1)">50</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">balance</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 128, 1)">50</span> } ] }</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;<strong>参考文章</strong></p>
<hr>
<p>Replication — MongoDB Manual</p>
<p class="line" data-line="156">Transactions — MongoDB Manual</p>
</div>
<div class="ws-copyright">
<p>转发请标明出处:https://www.cnblogs.com/WilsonPan/p/12708710.html</p>
</div><br><br>
来源:https://www.cnblogs.com/WilsonPan/p/12708710.html
頁: [1]
查看完整版本: 【Mongodb】事务