多文档事务不使用 MongoDB Atlas
Posted
技术标签:
【中文标题】多文档事务不使用 MongoDB Atlas【英文标题】:Multi-Document Transactions not Working using MongoDB Atlas 【发布时间】:2019-05-28 22:49:53 【问题描述】:更新
根据一些建议,我修改如下代码:
const session = await mongoose.startSession()
session.startTransaction()
try
const udpated = await Schema1.findByIdAndUpdate(
'id', $set: /* ... */ , session
)
const array = await Promise.all(
updated.array.map(async item =>
// change 1
const doc = await Schema2.findById(item.someId).session(session)
const payload = /* ... */
// change 2
return new Schema3(payload).save( session )
)
)
await session.commitTransaction()
session.endSession()
catch (err)
await session.abortTransaction()
session.endSession()
throw err
但这给了我另一个错误:
MongoError: internal atlas error checking things: Failure getting dbStats: read tcp 192.168.254.116:52242->192.168.254.116:27000: i/o timeout
at /some-path/node_modules/mongodb-core/lib/connection/pool.js:581:63
at authenticateStragglers (/some-path/node_modules/mongodb-core/lib/connection/pool.js:504:16)
at Connection.messageHandler (/some-path/node_modules/mongodb-core/lib/connection/pool.js:540:5)
at emitMessageHandler (/some-path/node_modules/mongodb-core/lib/connection/connection.js:310:10)
at TLSSocket.<anonymous> (/some-path/node_modules/mongodb-core/lib/connection/connection.js:453:17)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at TLSSocket.Readable.push (_stream_readable.js:208:10)
at TLSWrap.onread (net.js:597:20)
ok: 0,
errmsg: 'internal atlas error checking things: Failure getting dbStats: read tcp 192.168.254.116:52242->192.168.254.116:27000: i/o timeout',
code: 8000,
codeName: 'AtlasError',
name: 'MongoError',
[Symbol(mongoErrorContextSymbol)]:
× Unexpected error occured MongoError: internal atlas error checking things: Failure getting dbStats: read tcp 192.168.254.116:52242->192.168.254.116:27000: i/o timeout
at /some-path/node_modules/mongodb-core/lib/connection/pool.js:581:63
at authenticateStragglers (/some-path/node_modules/mongodb-core/lib/connection/pool.js:504:16)
at Connection.messageHandler (/some-path/node_modules/mongodb-core/lib/connection/pool.js:540:5)
at emitMessageHandler (/some-path/node_modules/mongodb-core/lib/connection/connection.js:310:10)
at TLSSocket.<anonymous> (/some-path/node_modules/mongodb-core/lib/connection/connection.js:453:17)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at TLSSocket.Readable.push (_stream_readable.js:208:10)
at TLSWrap.onread (net.js:597:20)
顺便说一句:我还重构了代码而不使用mongoose
(我只是使用标准mongodb
客户端来处理nodejs
,但我仍然遇到这些错误。
由于this question 中提到的问题,我正在使用mongoose
事务。
但是,我的问题是,我的Promise.all()
实现似乎不适用于mongoose
事务。问题可能来自使用多个Schemas
和一个session
或创建一组文档。 (但我真的不确定)
const session = await mongoose.startSession()
session.startTransaction()
try
const udpated = await Schema1.findByIdAndUpdate(
'id', $set: /* ... */ , session
)
const array = await Promise.all(
updated.array.map(async item =>
const doc = await Schema2.findById(item.someId)
const payload = /* ... */
return Schema3.createa(payload, session )
)
)
await session.commitTransaction()
session.endSession()
catch (err)
await session.abortTransaction()
session.endSession()
throw err
我收到错误,Schema3
的验证对于某些必需的路径失败。即使payload
在console.log 时找到。
ValidationError: xxx validation failed: xxx: Path `xxx` is required., xxx: Path `xxx` is required., xxx: Path `xxx` is required.
at ValidationError.inspect (/xxx/node_modules/mongoose/lib/error/validation.js:59:24)
at formatValue (util.js:400:38)
at inspect (util.js:294:10)
at format (util.js:223:18)
at Console.log (console.js:130:21)
at module.exports (xxx.js:228:17)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
errors:
xxx:
ValidatorError: Path `xxx` is required.
at new ValidatorError (/xxx/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/xxx/node_modules/mongoose/lib/schematype.js:871:13)
at /xxx/node_modules/mongoose/lib/schematype.js:924:11
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (/xxx/node_modules/mongoose/lib/schematype.js:880:19)
at /xxx/node_modules/mongoose/lib/document.js:1913:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
message: 'Path `xxx` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'xxx',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true ,
xxx:
ValidatorError: Path `xxx` is required.
at new ValidatorError (/xxx/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/xxx/node_modules/mongoose/lib/schematype.js:871:13)
at /xxx/node_modules/mongoose/lib/schematype.js:924:11
at Array.forEach (<anonymous>)
at ObjectId.SchemaType.doValidate (/xxx/node_modules/mongoose/lib/schematype.js:880:19)
at /xxx/node_modules/mongoose/lib/document.js:1913:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
message: 'Path `xxx` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'xxx',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true ,
xxx:
ValidatorError: Path `xxx` is required.
at new ValidatorError (/xxx/node_modules/mongoose/lib/error/validator.js:29:11)
at validate (/xxx/node_modules/mongoose/lib/schematype.js:871:13)
at /xxx/node_modules/mongoose/lib/schematype.js:924:11
at Array.forEach (<anonymous>)
at ObjectId.SchemaType.doValidate (/xxx/node_modules/mongoose/lib/schematype.js:880:19)
at /xxx/node_modules/mongoose/lib/document.js:1913:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
message: 'Path `xxx` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'xxx',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true ,
_message: 'xxx validation failed',
name: 'ValidationError'
在不使用mongoose
事务的情况下重构代码时,一切正常:
try
const udpated = await Schema1.findByIdAndUpdate(
'id', $set: /* ... */
)
const array = await Promise.all(
updated.array.map(async item =>
const doc = await Schema2.findById(item.someId)
const payload = /* ... */
return Schema3.createa(payload)
)
)
catch (err)
throw err
【问题讨论】:
我相信,如果你使用 Promise.all,你就不需要在 map 函数中使用 async/await。尝试删除它。 没用 :-( createa 是一个异步函数吗?还是只能通过 id 查找?create
返回Promise
我有版本 4。我联系了支持人员,这是一个已知问题,将在版本 4.0.5 中修复。还是谢谢你:)
【参考方案1】:
我联系了 MongoDB 支持,结果发现这是一个已知问题:
我们目前知道 M0 免费套餐集群存在一个问题,即多语句事务超时并出现错误。这应该随着 MongoDB 版本 4.0.5 的推出而得到解决。同时,如果您迫切需要此功能,我建议您将集群升级到 M10+ 集群。
所以出现问题是因为我使用的是免费套餐。但这个错误有望在 MongoDB 4.0.5 版本中得到修复。
更新
由于我的数据库现在在 4.0.5 版上运行,因此问题已得到解决。所以不一定是代码的问题。
【讨论】:
【参考方案2】:尝试在每个查询中添加.session(session)
const doc = await Schema2.findById(item.someId).session(session)
https://mongoosejs.com/docs/api.html#query_Query-session
【讨论】:
感谢您的建议!不幸的是,更改后我收到一个新错误(我更新了我的问题) 我在创建/保存交易时遇到了与您相同的错误。这个讨论中的解决方案似乎也没有解决问题github.com/Automattic/mongoose/issues/6761 我发现了这个问题:***.com/questions/53254164 看来这个错误无法修复 我联系了 mongodb 支持。也许他们会为此做点什么 以防万一您还没有注意到。升级到 4.0.5(现在可用)解决了这个问题【参考方案3】:您在findOne()
中似乎缺少会话选项:
const doc = await Schema2.findById(item.someId, null, session )
见:https://mongoosejs.com/docs/api.html#model_Model.findOne
【讨论】:
【参考方案4】:我遇到了类似的问题,我在会话中创建了一个文档,然后我使用了从其他文档“B”创建的 ._id,然后找到具有其他属性的第一个文档,当第一个文档时,我推送了那个B 在第一个文档中,我尝试的解决方案是使用倍数 session.startTransaction();
示例:
session.startTransaction();
创建第一个文档
await session.commitTransaction();
session.startTransaction();
创建第二个文档,用其他属性搜索第一个文档 使用它创建它,并将这个 B._id 推送到第一个文档中,然后更新这个第一个文档
await session.commitTransaction();
最后session.endSession()
当我再次搜索console.log(第一个文档)并将b推送到其中时,我意识到了这一点,只是我认为,它就像集群中的提交?所以也许与其他会话工作......它工作了
【讨论】:
以上是关于多文档事务不使用 MongoDB Atlas的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB 支持多文档 ACID 事务,现在 MongoDB 是不是适合金融应用? [关闭]