Skip to main content

Use MongoDB Transaction on Localhost

note

這個問題不是只有在 NestJs 才會發生, 只是剛好使用的是 NestJs 所以寫在這

在撰寫功能的時候會希望一連串的 db 操作全部正確後才完成, 中途如果有錯誤發生就要全部回復到原本的狀態, 來確保資料的完整性和可靠性, 這時候就需要使用 Transaction 來達成這個需求, 當一個 Transaction 執行時, 要不就全部執行成功, 要不就全部 rollback 到原始狀態, 以確保 db 的一致性, ex:

service.ts
import { InjectConnection } from '@nestjs/mongoose';
import mongoose from 'mongoose';
// ...

@Injectable()
export class SomeService {
constructor(
@InjectConnection(dbConnectionName.MAIN)
private readonly connection: mongoose.Connection
// ...
) {}

async someFunction() {
const session = await this.connection.startSession();
try {
session.startTransaction();
// do something
await session.commitTransaction().then(() => session.endSession());
} catch (error) {
await session.abortTransaction().then(() => session.endSession());
return throwValidationError(error);
}
}
}

而在 localhost 的環境中 db 剛好又是直接連本機端的話 (mongodb://127.0.0.1:27017) 就可能會遇到 Transaction numbers are only allowed on a replica set member or mongos 的錯誤, 這是因為 Transaction 的功能僅在 replica set 模式下或 sharded cluster 上支援, 所以在本機端需要額外啟用 replica set 模式

Windows

windows 安裝的版本為 V7.0

  1. 打開 MongoDB 安裝路徑中的 mongod.cfg 檔案,通常位於:

    C:\Program Files\MongoDB\Server\7.0\bin\mongod.cfg
  2. 在該文件中,找到或添加 replication 部分,並設置 replica set 名稱,例如 rs0

    # mongod.conf

    # for documentation of all options, see:
    # http://docs.mongodb.org/manual/reference/configuration-options/

    # Where and how to store data.
    storage:
    dbPath: C:\Program Files\MongoDB\Server\7.0\data

    # where to write logging data.
    systemLog:
    destination: file
    logAppend: true
    path: C:\Program Files\MongoDB\Server\7.0\log\mongod.log

    # network interfaces
    net:
    port: 27017
    bindIp: 127.0.0.1


    #processManagement:

    #security:

    #operationProfiling:

    #replication:

    #sharding:

    ## Enterprise-Only Options:

    #auditLog:

    # 新增 replication 部分
    replication:
    replSetName: "rs0"
  3. 關閉已經啟動的 mongodb, 並重新使用執行以下指令啟動

    mongod --config "C:\Program Files\MongoDB\Server\7.0\bin\mongod.cfg"
  4. 執行 mongosh 進入 mongo shell

    mongosh
  5. 成功進入後執行初始化 replica set 的指令

    rs.initiate()

最後再重新啟動 api server 就可以正常使用 transaction 的功能了

Mac

macOS 版本為 Sequoia, mongod.conf 的位置在 /opt/homebrew/etc/ 底下

步驟跟上面一樣, 先關閉後再重新啟動

brew services stop mongodb-community

指定 config 並重新啟動

mongod --config /opt/homebrew/etc/mongod.conf --fork

--fork 可以讓 mongod 在背景執行

可以使用 ps aux | grep mongod 來確認是否有啟動成功

如果 config 正常, 可以再使用 brew services 來啟動, 並且以後開機自動啟動

brew services restart mongodb-community

可以使用 brew services list 來確認是否有啟動成功, 如果有需要, 可以使用 ps aux | grep mongod 找到 pid 後使用 kill -9 <pid>pkill -SIGTERM mongod 先完整關閉後再重新啟動

第一次啟動成功後一樣使用 mongosh 進入執行初始化 replica set 的指令

mongosh
rs.initiate()