使用原生驱动实现
const { MongoClient } = require('mongodb');
// 连接字符串
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
async function insertUsers(users) {
try {
await client.connect();
const session = client.startSession();
session.startTransaction();
const db = client.db('test');
const usersCollection = db.collection('users');
await usersCollection.insertMany(users, { session });
await session.commitTransaction();
console.log('Users inserted successfully');
} catch (e) {
console.error('Error inserting users:', e);
// 事务回滚
if (session) {
await session.abortTransaction();
}
} finally {
await client.close();
}
}
// 示例用户数组
const usersToInsert = [
{ name: 'Alice', email: 'alice@example.com', age: 25 },
{ name: 'Bob', email: 'bob@example.com', age: 30 }
];
insertUsers(usersToInsert);
使用Mongoose实现
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true });
const userSchema = new mongoose.Schema({
name: String,
email: String,
age: Number
});
const User = mongoose.model('User', userSchema);
async function insertUsers(users) {
try {
const session = await mongoose.startSession();
session.startTransaction();
await User.insertMany(users, { session });
await session.commitTransaction();
console.log('Users inserted successfully');
} catch (e) {
console.error('Error inserting users:', e);
// 事务回滚
if (session) {
await session.abortTransaction();
}
} finally {
await mongoose.disconnect();
}
}
// 示例用户数组
const usersToInsert = [
{ name: 'Alice', email: 'alice@example.com', age: 25 },
{ name: 'Bob', email: 'bob@example.com', age: 30 }
];
insertUsers(usersToInsert);
不同场景下使用事务的必要性
- 数据一致性场景:例如银行转账,从一个账户扣除金额,同时在另一个账户增加金额,这两个操作必须同时成功或失败,否则会导致数据不一致。在用户信息批量插入场景中,如果部分用户插入成功,部分失败,可能导致数据不完整,使用事务可以确保要么所有用户都插入成功,要么都失败,维护数据一致性。
- 业务逻辑完整性场景:当多个操作构成一个完整的业务流程时,例如创建订单时,不仅要插入订单信息,还要更新库存等,这些操作需要作为一个整体来处理,事务保证了业务逻辑的完整性。
可能遇到的问题
- 性能问题:事务会增加额外的开销,因为需要协调多个操作并保证原子性。在高并发场景下,事务可能导致锁争用,降低系统的整体性能。
- 兼容性问题:并非所有的MongoDB部署模式都支持事务,例如某些旧版本或特定的集群配置可能不支持,在使用事务前需要确保环境支持。
- 回滚复杂性:如果在事务执行过程中出现错误进行回滚,可能需要处理各种已执行操作的反向操作,对于复杂的业务逻辑,回滚操作可能变得复杂且易错。