Go语言 对查询结果执行更新时出现“conn忙碌”错误

yqyhoc1h  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(101)

我想选择数据,同时最后登录数据将在当前日期和时间发生变化。
这是我的代码和错误是2023/08/18 15:07:21连接忙碌我已经尝试更新当前日期在许多位置和仍然相同的错误.我已经试着有更多的延迟关闭和仍然相同的错误。我在数据库中的连接是好的,因为我的一些代码是工程和选择是工作,但更新当前日期不是。

// SELECT MEMBER
func SearcMember(c *fiber.Ctx) error {

    var request Models.Request
    if err := c.BodyParser(&request); err != nil {
        return err
    }

    rows, err := DBConnection.GetDB().Query(ctx, "SELECT id, login, firstname, mi, lastname, email, passwd, institution, area, internet, level, lastlogin, region, loginToken, staffId, mobileNumber, userStat, isLogin FROM members WHERE login = $1 AND passwd = $2", request.Login, request.Password)
    if err != nil {
        log.Println(err)
        return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
    }
    defer rows.Close()

    var Members []Models.SelectMembers

    for rows.Next() {
        var Member Models.SelectMembers
        var Institution sql.NullString
        var Area sql.NullString
        var Internet sql.NullString
        var Level sql.NullInt32
        var LastLogin sql.NullString
        var Region sql.NullInt32
        var LoginToken sql.NullString
        var StaffID sql.NullString
        var UserStatus sql.NullInt32
        var ISLogin sql.NullInt32

        err := rows.Scan(&Member.MembersID, &Member.LogIn, &Member.FullName.FirstName, &Member.FullName.MiddleName, &Member.FullName.LastName, &Member.Email, &Member.Password, &Institution, &Area, &Internet, &Level, &LastLogin, &Region, &LoginToken, &StaffID, &Member.MobileNumber, &UserStatus, &ISLogin)

        if err != nil {
            log.Println(err)
            continue
        }
        Member.Institution = Institution.String
        Member.Area = Area.String
        Member.Internet = Internet.String
        Member.Level = int(Level.Int32)
        Member.LastLogin = LastLogin.String
        Member.LoginToken = LoginToken.String
        Member.Region = int(Region.Int32)
        Member.StaffID = StaffID.String
        Member.UserStatus = int(UserStatus.Int32)
        Member.ISLogin = int(ISLogin.Int32)

        Member.Name = fmt.Sprintf("%s %s %s", Member.FullName.FirstName, Member.FullName.MiddleName, Member.FullName.LastName)
        Members = append(Members, Member)

        defer rows.Close()
        // Update the LastLogin field with the current date and time
        if LastLogin.Valid {
            currentTime := time.Now().Format("2006-01-02 15:04:05")
            // Update the lastlogin field in the database
            _, updateErr := DBConnection.GetDB().Exec(ctx, "UPDATE members SET lastlogin = $1 WHERE id = $2", currentTime, Member.MembersID)
            log.Print("Nababasa")
            if updateErr != nil {
                log.Println(updateErr)
            }
        }
    }

    return c.Status(fiber.StatusCreated).JSON(Members)
}

这是我的数据库连接

package DBConnection

import (
    "context"
    "log"

    "github.com/jackc/pgx/v4"
)

var db *pgx.Conn
var ctx = context.Background()

func InitDB() {

    conn, err := pgx.Connect(ctx, "postgres://postgres:12345@localhost:5432/crd_audit?sslmode=disable")
    if err != nil {
        log.Fatalf("Unable to connect to database: %v", err)
    }
    
    db = conn
}

func GetDB() *pgx.Conn {
    return db
}

我想选择数据,同时最后登录数据将在当前日期和时间发生变化。

lqfhib0f

lqfhib0f1#

根据PGX标准:
由pgx.Connect()返回的 *pgx.Conn表示单个连接,并且不是并发安全的。这完全适用于上面这样的简单命令行示例。
所以这是一个单一的连接,你不能在一个连接上同时运行两个命令。当您执行以下操作时,您正在执行此操作(因此出现conn busy错误):
1.运行查询以从members中选择数据
1.对于每个结果:

  1. ExecUPDATE members(这需要额外的连接)
    1.关闭初始select查询
    你可以通过重构你的代码来解决这个问题,这样只需要一个连接。有几种方法可以做到这一点,但最简单的是使用QueryRow(正如我所期望的那样,您将有数据库约束来防止重复的login值,因为重复的值是不好的!)。或者(在需要多个结果的情况下),您可以:
    1.在members上运行select并获取所有结果(完成后运行rows.Close())。
    1.循环通过Members切片,为每个切片运行更新(UPDATE members)。
    • 这是因为您看起来(基于fibre的使用)正在编写服务器,并且可能需要处理并发请求(例如,您可能同时收到两个登录请求)。

更好的解决方案是使用连接池。这将管理多个数据库连接,使您能够同时运行多个查询(与*pgx.Conn不同,并发使用也是安全的)。
这看起来像这样:

package DBConnection

import (
    "context"
    "log"

    "github.com/jackc/pgx/v5/pgxpool"
)

var db *pgxpool.Pool
var ctx = context.Background()

func InitDB() {
    dbpool, err := pgxpool.New(ctx, "postgres://postgres:12345@localhost:5432/crd_audit?sslmode=disable")
    if err != nil {
        log.Fatalf("Unable to connect to create pool: %v", err)
    }

    db = dbpool
}

func GetDB() *pgxpool.Pool {
    return db
}

相关问题