Go语言 在发送请求时发布关系被卡住

uurity8g  于 2023-04-27  发布在  Go
关注(0)|答案(1)|浏览(163)

moment of hit post API概述:

这是我的代码

func (s StudentServiceImpl) Create(ctx context.Context, request web.StudentCreateRequest) web.StudentResponse {
    err := s.Validate.Struct(request)
    helper.PanicIfError(err)

    tx, err := s.DB.Begin()
    helper.PanicIfError(err)
    defer helper.CommitOrRollback(tx)

    major, isExistMajor := s.MajorService.FindByMajorName(ctx, request.Major)
    //fmt.Println(isExistMajor)
    if isExistMajor == false {
        major = s.MajorService.Create(ctx, request.Major)
    }

    student := domain.Student{
        Name:      request.Name,
        Age:       request.Age,
        Gender:    request.Gender,
        CreatedAt: time.DateTime,
        Major:     major,
    }

    student = s.StudentRepository.Save(ctx, tx, student)
    studentId := student.Id

    hobbies := s.HobbyService.Creates(ctx, request.Hobbies)
    fmt.Println(hobbies, studentId)
    for i := 0; i < len(hobbies); i++ {
        // todo this below service bug stuck in sending request...
        //s.HobbyService.CreateStudentHobby(ctx, studentId, hobbies[i].Id)
    }
    return helper.ToStudentResponse(student)
}

怎么了,请帮帮我!链接我的仓库https://github.com/antoniusbunwiijaya/student-api-go/blob/master/service/student_service_impl.go#L39

axr492tv

axr492tv1#

这是由死锁引起的。
如果你在数据库中执行show engine innodb status;,你会看到类似这样的东西:

---TRANSACTION 64, ACTIVE 5 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1128, 1 row lock(s), undo log entries 1
MariaDB thread id 10, OS thread handle 140285377406528, query id 171 172.17.0.1 root Update
insert into student_hobbies(student_id, hobby_id) values(?,?)
------- TRX HAS BEEN WAITING 4891799 ns FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6 page no 3 n bits 8 index PRIMARY of table `student_api_go`.`students` trx id 64 lock mode S locks rec but not gap waiting

下面是(StudentServiceImpl).Create的调用序列:
1.它启动外部事务。
1.它将记录插入表students
1.它调用(HobbyServiceImpl).CreateStudentHobby。该函数的序列为:
3.1)它启动内部事务。
3.2)它试图将一条记录插入到student_hobbies表中。这里,由于外键约束(FOREIGN KEY (student_id) REFERENCES students(id)),它要求在students表上设置一个记录锁。
3.3)提交或回滚内部事务。
1.提交或回滚外部事务。
步骤3.2无法完成,因为外部事务尚未结束;但是外部事务直到第4步才能结束。所以这里是死锁。
解决这类问题的一个简单解决方案是在设计中引入Unit of Work pattern。简单地说,对于用户操作,您为所有涉及的服务创建单个事务(而不是让每个服务创建自己的事务)。
例如,(StudentServiceImpl).Create可以是工作单元的条目。它负责管理事务并将事务传递给它调用的服务。我已经创建了a pull request,它使用此解决方案来解决这个问题。查看更多细节。
请注意,这并不是最好的解决方案。事务是有成本的,请谨慎使用。也许您只是需要事务来执行一些关键操作。例如,您真的需要事务来执行简单的查询吗?请参阅这里的示例,其中在事务中执行简单的查询。

相关问题