首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MongoTransactionException:查询失败,错误代码251

MongoTransactionException:查询失败,错误代码251
EN

Stack Overflow用户
提问于 2020-09-27 05:06:08
回答 3查看 4.8K关注 0票数 6

在查询事务中的文档时,只使用特定的id (其他所有id都可以)时,会遇到这个Mongo异常:

代码语言:javascript
运行
复制
Exception occured: org.springframework.data.mongodb.MongoTransactionException: 
Query failed with error code 251 and error message 
'Given transaction number 1 does not match any in-progress transactions. The active transaction number is -1' on server mongo-1:27017; 
nested exception is com.mongodb.MongoQueryException: 
Query failed with error code 251 and error message 
'Given transaction number 1 does not match any in-progress transactions. The active transaction number is -1' on server mongo-1:27017 
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:136) 
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2902) 
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2810) 
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2555) 
at org.springframework.data.mongodb.core.ExecutableFindOperationSupport$ExecutableFindSupport.doFind(ExecutableFindOperationSupport.java:216) 
at org.springframework.data.mongodb.core.ExecutableFindOperationSupport$ExecutableFindSupport.oneValue(ExecutableFindOperationSupport.java:128) 
at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.lambda$getExecution$4(AbstractMongoQuery.java:153) 
at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.doExecute(AbstractMongoQuery.java:126) 
at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.execute(AbstractMongoQuery.java:101) 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:618) 

MongoDB是一个切分的集群,对一个完全相似的集群(在另一个测试环境中)执行类似的操作,但没有出现异常。

另一个信息是,此异常总是在MongoDB套接字异常之后,如下所示:

代码语言:javascript
运行
复制
Got socket exception on connection [connectionId{localValue:9, serverValue:11760}] to mongo-1:27017. All connections to mongo-1:27017 will be closed.
EN

回答 3

Stack Overflow用户

发布于 2021-07-15 12:06:07

我们的项目中有一个类似的问题:一些测试失败了251‘给定的事务号*不匹配任何正在进行的事务’。我们编写了一个测试来重现这个问题,然后对它进行了调试。我百分之九十肯定我们找到了这个问题。

因此,假设如下:

当我们使用spring事务时,当第一个请求被发送到数据库时,实际的事务就会启动(不管是什么样的请求--查询、更新等等)。因此,当第一个请求与任何其他请求并行发送时,但是无法在它们之前完成,并且他们认为事务已经启动(但没有),那么我们就会看到这个错误发生了。“事务x+1不存在。最后一个事务是x”。得出这个结论的原因是以下日志序列(我们在测试执行期间启用了跟踪日志):

  • 2021-07-15 12:56:41.331 DEBUG 4900 -测试工作者org.mongodb.driver.protocol.command :发送命令{“查找”:“项”,“筛选器”:{"_id":"d1"},“限制”:1,"$db":“.”,"txnNumber":1"startTransaction":true,"autocommit":false,.}‘请求id 23到数据库.在连接...
  • ...
  • 2021-07-15 12:56:41.334调试4900 - Test org.mongodb.driver.protocol.command :发送命令{“查找”:“项”、“筛选器”:{"_id":"d2"}、“限制”:1、"$db":“.”、.、"txnNumber":1、“自动提交”:false,.}‘请求id 24到数据库.在连接...
  • ...
  • 2021-07-15 12:56:41.337调试4900 - ntLoopGroup-3-6 org.mongodb.driver.protocol.command :执行请求id 24的命令时,未能成功完成.

命令失败,错误251 ( ...

  • ...

  • 2021-07-15 ):“给定的事务号1与任何正在进行的事务不匹配。在服务器com.mongodb.MongoCommandException 12:56:41.379 DEBUG 4900 - ntLoopGroup-3-8 org.mongodb.driver.protocol.command上,活动事务号为-1”:使用请求id 23成功完成命令的执行.

注意,在第一个日志中,我们是如何使用"startTransaction":true,而在第二个日志中,我们没有。然而,第二个请求首先完成了,因此它出错了。如果第二请求在第一请求开始和第一请求完成之间启动,例如:第一请求启动,第二请求启动,第一请求完成,第二请求完成,则也会发生此错误。

测试代码( kotlin):

服务:

代码语言:javascript
运行
复制
@Service
class TestService {

    @Autowired private lateinit var itemRepository: ItemRepository

    @Transactional
    fun parallelQuery(): Mono<Void> {
        return Flux.fromIterable(listOf("d1", "d2"))
            .flatMap {
                itemRepository.findById(it)
            }
            .then()
    }
}

测试本身:

代码语言:javascript
运行
复制
internal class MonoZipTest: BaseTest() {
    @Autowired private lateinit var testService: TestService

    @Test
    fun test() {

        val mono =
            Flux.fromIterable(1..1000)
                .flatMap {
                    testService.parallelQuery()
                }
                .then()

        StepVerifier.create(mono)
            .expectError(MongoTransactionException::class.java)
            .verify()
    }
}

结论:确保在交易中对mongodb的第一次请求不会与该交易中的任何其他请求并行进行。

票数 5
EN

Stack Overflow用户

发布于 2020-10-04 11:19:26

一个小小的免责声明:这不是一个正确的答案,因为我不确定它是否能帮助原来的海报;而且,我也没有适当的解释这个效果。我只是想让人们知道这个效果,通常我会用一个评论来表达,但是它太长了,不能发表评论。我发这篇文章是希望它能帮助人们解决他们的问题。

我们最近也看到了一个类似的例外:

代码语言:javascript
运行
复制
Caused by: com.mongodb.MongoQueryException: Query failed with error code 251 and error message 'Given transaction number 198 does not match any in-progress transactions. The active transaction number is 197' on server aaa.bbb.ccc:27017
    at com.mongodb.operation.FindOperation$3.onResult(FindOperation.java:822)

我无法显示代码,所以我将尝试解释它的功能。

在没有反应的情况下,情况会是这样的:

代码语言:javascript
运行
复制
X = getX()
Y = saveAndReturnY()
pair = (X, Y)
processPair(pair)

这个逻辑是实现的,它工作得很好(我没有显示工作代码版本,它不相关)。此代码在事务下运行。

然后,我重构了这段代码,以简化它。结果看起来是这样的:

代码语言:javascript
运行
复制
getX() // Mono<X>
    .zipWith(saveAndReturnY()) // Mono<Tuple<X, Y>>
    .flatMap(this::processPair)

使用这段代码,我们观察到了上面的异常。它不是100%发生的,大约是50/50:有时发生,有时不发生。这只发生在MongoDB地图集上。我们的集成测试使用相同版本(4.2.9)的MongoDB在Docker容器(通过测试容器)中工作,运行良好,我们从未在那里重现问题。

长话短说:事实证明,如果我们用zipWith()替换zipWhen(),问题就解决了:

代码语言:javascript
运行
复制
getX() // Mono<X>
    .zipWhen(x -> saveAndReturnY()) // Mono<Tuple<X, Y>>
    .flatMap(this::processPair)

不同的是,使用zipWith()时,订阅同时发生在两个被压缩在一起的Monos上,即Mono<X>Mono<Y>,因此它们“并行”执行。但是对于zipWhen(),它们严格按顺序执行:首先从Mono<X>中获取X,然后订阅Mono<Y>。在原始代码中(在重构之前),它以相同的方式工作(顺序的,或者更好地说是因果的)。

我不知道为什么会这样,我们还在调查。也许是因为这种并行性而出现了一些问题。或者,在MongoDB事务中有一些我还不理解的东西,当并行性开始时,就会产生这样的异常。

无论如何,在我们的例子中,消除并行性解决了这个问题。尝试分析您的代码,看看是否有一些操作符(如Mono.zipWith()Flux.flatMap() )订阅了多个Publisher,从而产生了这样的“并行性”效果。

票数 2
EN

Stack Overflow用户

发布于 2022-01-14 12:03:26

我的答案可能对使用猫鼬做nodejs的人有用。

我也遇到了同样的错误。经过研究发现,这个问题是由写作冲突引起的。您可以在mongosh中运行db.currentOp()来检查。

此命令的文档:https://docs.mongodb.com/manual/faq/concurrency/#how-do-i-see-the-status-of-locks-on-my--instances-

如果存在一些写冲突,则在事务中进行mongo重试操作,直到冲突得到解决,在我的示例中,需要超过60秒(事务完成的默认最大时间),因此它被中止。

关于写冲突的好文章:https://blog.clairvoyantsoft.com/mongodb-transaction-management-884f82f62767

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64084992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档