You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang+MySQL Cloud调用REST API重复出现Invalid Transaction错误排查

问题排查:创建房间API二次调用报「Invalid Transaction」错误

问题描述

首次调用创建房间的REST API时运行正常,但第二次调用时反复出现「Invalid Transaction」错误。

相关代码

Golang控制器代码

func (c ChatApiService) CreateRoom(ctx context.Context, room openapi.Room) (openapi.ImplResponse, error) {

    // Create the Room
    createRoom, err := service.CreateRoom(room, c.db)

    if err != nil {
        return openapi.ImplResponse{}, err
    }

    // Add users to the room
    if room.Users != nil && len(room.Users) > 0 {
        for _, userId := range room.Users {
            err := service.AssignUserToRoom(userId, createRoom.Id, models.RoomRoleMember, c.db)
            if err != nil {
                return openapi.ImplResponse{}, err
            }
        }
    }

    return openapi.ImplResponse{
        Code: 200,
        Body: createRoom,
    }, nil

}

Golang服务层函数代码

func CreateRoom(room openapi.Room, db *gorm.DB) (openapi.Room, error) {

    var roomType models.RoomType

    roomId := uuid.New().String()

    switch room.RoomType {
    case "ORGANIZATION":
        roomType = models.RoomTypeOrganization
    case "GROUP":
        roomType = models.RoomTypeGroup
    case "PRIVATE":
        roomType = models.RoomTypePrivate
    case "ADMIN":
        roomType = models.RoomTypeAdmin
    default:
        return openapi.Room{}, errors.New("Invalid Room Type")
    }

    // Create Room
    newRoom := models.Room{
        ID:         roomId,
        Title:      room.Title,
        RoomType:   roomType,
        CreatedBy:  room.CreatedBy,
        Status:     models.StatusActive,
        ModifiedAt: time.Now(),
        CreatedAt:  time.Now(),
    }

    logger.Logger.Info("Create Room", zap.Any("newRoom", newRoom))

    savedRoom := db.Create(&newRoom)
    if savedRoom.Error != nil {
        logger.Logger.Error("Error saving room", zap.Error(savedRoom.Error))
        return openapi.Room{}, savedRoom.Error
    }

    savedRoom.Commit()

    if room.RoomType == "ORGANIZATION" {
        err := CreateRoomOrganization(newRoom.ID, room, db)
        if err != nil {
            return openapi.Room{}, err
        }
    } else if room.RoomType == "GROUP" {
        err := CreateGroupRoom(newRoom.ID, room, db)
        if err != nil {
            return openapi.Room{}, err
        }
    } else if room.RoomType == "PRIVATE" {
        err := CreatePrivateRoom(newRoom.ID, room, db)
        if err != nil {
            return openapi.Room{}, err
        }
    } else if room.RoomType == "ADMIN" {
        err := CreateAdminRoom(newRoom.ID, room, db)
        if err != nil {
            return openapi.Room{}, err
        }
    } else {
        return openapi.Room{}, errors.New("invalid Room Type")
    }

    return dto.RoomDTO(newRoom), nil
} 

完整错误信息

"error":"invalid transaction; invalid transaction; invalid transaction; invalid transaction; invalid transaction; invalid transaction; invalid transaction","stacktrace":"bityagi/src/service.CreateRoom\n\t/Users/mabeloza/GolandProjects/patshala/backend/src/service/room_service.go:51\nbityagi/src/handlers.ChatApiService.CreateRoom\n\t/Users/mabeloza/GolandProjects/patshala/backend/src/handlers/room_handler.go:32\nbuild/code/spec/src.(*ChatAPIController).CreateRoom\n\t/Users/mabeloza/GolandProjects/patshala/backend/build/generated/src/api_chat.go:121\nnet/http.HandlerFunc.ServeHTTP\n\t/opt/homebrew/Cellar/go/1.22.0/libexec/src/net/http/server.go:2166\ngithub.com/go-chi/chi/v5.(*Mux).routeHTTP\n\t/Users/mabeloza/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.10/mux.go:444\nnet/http.HandlerFunc.ServeHTTP\n\t/opt/homebrew/Cellar/go/1.22.0/libexec/src/net/http/server.go:2166\ngithub.com/go-chi/cors.(*Cors).Handler-fm.(*Cors).Handler.func1\n\t/Users/mabeloza/go/pkg/mod/github.com/go-chi/cors@v1.2.1/cors.go:228\nnet/http.HandlerFunc.ServeHTTP\n\t/opt/homebrew/Cellar/go/1.22.0/libexec/src/net/http/server.go:2166\ngithub.com/go-chi/chi/v5/middleware.init.0.RequestLogger.func1.1\n\t/Users/mabeloza/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.10/middleware/logger.go:54\nnet/http.HandlerFunc.ServeHTTP\n\t/opt/homebrew/Cellar/go/1.22.0/libexec/src/net/http/server.go:2166\ngithub.com/go-chi/chi/v5.(*Mux).ServeHTTP\n\t/Users/mabeloza/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.10/mux.go:90\nnet/http.serverHandler.ServeHTTP\n\t/opt/homebrew/Cellar/go/1.22.0/libexec/src/net/http/server.go:3137\nnet/http.(*conn).serve\n\t/opt/homebrew/Cellar/go/1.22.0/libexec/src/net/http/server.go:2039"}

日志信息

{"level":"info","ts":1716237267.974571,"caller":"service/room_service.go:47","msg":"Create Room","newRoom":{"id":"21758551-f470-4532-92c9-2f857ff0e989","title":"Johnny & Jane","description":{"String":"","Valid":false},"image_url":{"String":"","Valid":false},"room_type":"PRIVATE","last_message":{"String":"","Valid":false},"status":"ACTIVE","created_by":"814caa91-3494-46ba-8316-f3ae0d11a34c","created_at":"2024-05-20T15:34:27.974549-05:00","modified_at":"2024-05-20T15:34:27.974549-05:00"}}
{"level":"error","ts":1716237267.974646,"caller":"service/room_service.go:51","msg":"Error saving room","error":"invalid transaction; invalid transaction; invalid transaction; invalid transaction; invalid transaction; invalid transaction; invalid transaction","stacktrace":"bityagi/src/service.CreateRoom\n\t/Users/mabeloza/Golan

问题原因分析

核心问题在于服务层代码中手动调用了savedRoom.Commit():

  • GORM的db.Create()操作在非事务环境下会自动执行提交,无需手动调用Commit。
  • 第一次调用时,手动Commit会导致当前DB连接的事务状态被异常修改;第二次复用同一个DB连接时,连接处于无效事务状态,因此触发「Invalid Transaction」错误。

解决方案

快速修复

直接删除服务层代码中的savedRoom.Commit()行即可:

// 移除这行无效的手动提交代码
// savedRoom.Commit()

事务化改造(可选)

如果需要对创建房间及后续关联操作(如CreateRoomOrganization等)开启原子性事务,应使用GORM的事务API手动管理:

func CreateRoom(room openapi.Room, db *gorm.DB) (openapi.Room, error) {
    // ... 其他类型转换、对象初始化代码 ...

    // 开启事务
    tx := db.Begin()
    defer func() {
        if r := recover(); r != nil {
            tx.Rollback()
        }
    }()

    // 事务内创建房间
    if err := tx.Create(&newRoom).Error; err != nil {
        tx.Rollback()
        logger.Logger.Error("Error saving room", zap.Error(err))
        return openapi.Room{}, err
    }

    // 事务内执行后续关联操作,需传入tx而非原始db
    if room.RoomType == "ORGANIZATION" {
        err := CreateRoomOrganization(newRoom.ID, room, tx)
        if err != nil {
            tx.Rollback()
            return openapi.Room{}, err
        }
    }
    // ... 其他房间类型分支代码 ...

    // 提交事务
    if err := tx.Commit().Error; err != nil {
        return openapi.Room{}, err
    }

    return dto.RoomDTO(newRoom), nil
}

内容的提问来源于stack exchange,提问作者Mabel Oza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 19:34:52