Cosmos DB:不支持可重试写入。请通过指定禁用可重试写入

Posted

技术标签:

【中文标题】Cosmos DB:不支持可重试写入。请通过指定禁用可重试写入【英文标题】:Cosmos DB: Retryable writes are not supported. Please disable retryable writes by specifying 【发布时间】:2021-09-12 23:57:08 【问题描述】:

关于这个问题有很多线程,没有一个有适合我的解决方案。 我正在使用 NestJS、TypeORM 和 Cosmos DB Mongo API。

我在我的机器上运行 NestJS 服务,访问 Azure 中的数据库。 我可以很好地从集合中读取,但是每当我尝试写入时,我都会收到以下错误:

MongoError: Retryable writes are not supported. Please disable retryable writes by specifying "retrywrites=false" in the connection string or an equivalent driver specific config.

保存到数据库的逻辑的精简版本。我保存的对象在 Azure 的 Mongo Shell 中执行 db.collection.save() 时工作​​正常。但是完全相同的 save() 在这里失败了

@Injectable()
export class PatientService 

constructor(
    @InjectRepository(PatientsByUser)
    private readonly patientsByUserRepo: MongoRepository<PatientsByUser>
) 

async addPatientToFavoritesList() 
            this.patientsByUserRepo.save(
                email: "test",
                patientList: [
                    accountNumber: 1,
                    firstName: "test",
                    lastName: "test",
                    dob: "test"
                ]
            )
  

这里是配置 TypeORM 的模块:

import HttpModule, Module from '@nestjs/common';
import ConfigModule from "@nestjs/config";
import TypeOrmModule from "@nestjs/typeorm";
import PatientService from "./patient.service";
import PatientController from "./patient.controller";
import PatientsByUser from "./patient.entity";

@Module(
    imports: [
        HttpModule,
        ConfigModule.forRoot(),
        TypeOrmModule.forRoot(
            type: 'mongodb',
            url: process.env.MONGODB_CONNECTION_STRING,
            database: process.env.MONGODB_DATABASE,
            entities: [
                __dirname + '/**/*.entity.ts,.js',
            ],
            ssl: true,
            useUnifiedTopology: true,
            useNewUrlParser: true,

        ),
        TypeOrmModule.forFeature([PatientsByUser])
    ],
    providers: [PatientService],
    controllers: [PatientController],
    exports: [PatientService]
)
export class PatientModule 

我的连接字符串确实包含 retrywrites=false。我还尝试了 retryWrites=false,并在连接字符串的末尾都尝试了。都没有用。

MONGODB_CONNECTION_STRING=mongodb://portal-db-dev:<private>==@portal-db-dev.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@portal-db-dev@

我们的 Cosmos DB 是第 4 版。我知道回滚到 3.2 可以解决这个问题,但如果这是唯一的出路,那将是次优的,而且在微软方面是完全荒谬的。

package.json


  "name": "portal-be",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": 
    "prebuild": "rimraf dist",
    "build": "nest build && mkdir dist/src/assets && cp -r src/assets/* dist/src/assets",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"src,apps,libs,test/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  ,
  "dependencies": 
    "@nestjs/common": "^7.6.13",
    "@nestjs/config": "^0.6.3",
    "@nestjs/core": "^7.6.13",
    "@nestjs/passport": "^7.1.5",
    "@nestjs/platform-express": "^7.6.13",
    "@nestjs/swagger": "^4.7.15",
    "@nestjs/typeorm": "^7.1.5",
    "@types/mongodb": "^3",
    "@types/passport-azure-ad": "^4.0.8",
    "class-transformer": "^0.4.0",
    "class-validator": "^0.13.1",
    "dotenv": "^8.2.0",
    "jwt-decode": "^3.1.2",
    "moment": "^2.29.1",
    "mongodb": "^3.6.9",
    "passport": "^0.4.1",
    "passport-azure-ad": "^4.3.0",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.6.7",
    "soap": "^0.39.0",
    "typeorm": "^0.2.32"
  ,
  "devDependencies": 
    "@nestjs/cli": "^7.5.6",
    "@nestjs/schematics": "^7.2.7",
    "@nestjs/testing": "^7.6.13",
    "@types/express": "^4.17.11",
    "@types/jest": "^26.0.20",
    "@types/mongodb": "^3",
    "@types/node": "^14.14.31",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/eslint-plugin": "^4.15.2",
    "@typescript-eslint/parser": "^4.15.2",
    "eslint": "^7.20.0",
    "eslint-config-prettier": "^8.1.0",
    "eslint-plugin-prettier": "^3.3.1",
    "jest": "^26.6.3",
    "prettier": "^2.2.1",
    "supertest": "^6.1.3",
    "ts-jest": "^26.5.2",
    "ts-loader": "^8.0.17",
    "ts-node": "^9.1.1",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^4.1.5"
  ,
  "jest": 
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": 
      "^.+\\.(t|j)s$": "ts-jest"
    ,
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  

【问题讨论】:

【参考方案1】:

Cosmos DB 不支持可重试写入。

mongo shell 默认不启用可重试写入。

与 MongoDB 4.2 或更高版本兼容的 MongoDB 驱动程序默认启用可重试写入。

MongoDB Node.JS 驱动程序版本 3.3+ 与 MongoDB 4.2 兼容

要使用默认启用可重试写入的驱动程序连接到不支持可重试写入的数据库服务器,您需要通过在连接字符串 URI 中传递 retryWrites=false 来禁用可重试写入。

https://docs.mongodb.com/manual/core/retryable-writes/#enabling-retryable-writes

【讨论】:

我已经把retryWrites=flase放在了连接字符串里,在post里。除此之外还有什么我可以尝试的吗? 在帖子中,它全部显示为小写。确保大小写正确。 我已经尝试了每种情况的所有可能组合。问题不在此标志之外。由于某种原因,NestJS 中的驱动程序不尊重该标志。回滚到 mongo 3.2 可以解决此问题,但使用 6 年旧版本的数据库不太理想

以上是关于Cosmos DB:不支持可重试写入。请通过指定禁用可重试写入的主要内容,如果未能解决你的问题,请参考以下文章

MongoError:此 MongoDB 部署不支持可重试写入。请将 retryWrites=false 添加到您的连接字符串

Cosmos DB:Gremlin API请求太大异常。如何重试通话

MongoDB 错误:无法使用 limit=0 的可重试写入

无法使用 pySpark 从 Databricks 在 Cosmos DB/documentDB 中写入数据帧

来自 Databricks Notebook 的 COSMOS DB 写入问题

将托管标识与 Cosmos Db Table Api 一起使用