会话 Session
Session 是 MongoDB 3.6 之后引入的概念,在以前的版本中,Mongod
进程中的每一个请求会创建一个上下文(OperationContext),可以理解为一个单行事务,这个单行事务中对于数据、索引、oplog
的修改都是原子性的。
MongoDB 3.6 之后的 Session 本质上也是一个上下文,在这个 Session
会话中多个请求共享一个上下文,为多文档事务实现提供了基础。
事务函数
Nodejs 中事务实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| const db = require('./db');
const testTransaction = async (goodId) => { const client = await db.dbInstance(); const transactionOptions = { readConcern: { level: 'majority' }, writeConcern: { w: 'majority' }, readPreference: 'primary', };
const session = client.startSession(); console.log('事务状态:', session.transaction.state);
try { session.startTransaction(transactionOptions); console.log('事务状态:', session.transaction.state);
const goodsColl = await client.db('test').collection('goods'); const orderGoodsColl = await client.db('test').collection('order_goods'); const { stock, price } = await goodsColl.findOne({ goodId }, { session }); console.log('事务状态:', session.transaction.state); if (stock <= 0) { throw new Error('库存不足'); }
await goodsColl.updateOne({ goodId }, { $inc: { stock: -1 } }) await orderGoodsColl.insertOne({ id: Math.floor(Math.random() * 1000), goodId, price }, { session }); await session.commitTransaction(); } catch(err) { console.log(`[MongoDB transaction] ERROR: ${err}`); await session.abortTransaction(); } finally { await session.endSession(); console.log('事务状态:', session.transaction.state); } }
testTransaction('g1000')
|
运行测试结果:
1 2 3 4 5
| node index 事务状态: NO_TRANSACTION 事务状态: STARTING_TRANSACTION 事务状态: TRANSACTION_IN_PROGRESS 事务状态: TRANSACTION_COMMITTED
|
mogoose 中支持事务的方法
新建文档 |
create(docs,options) |
一定要传入数组,使用它的重载方法 |
注意事项
- 在事务中,只能使用事务语句进行操作,不能与普通语句混用