当一个golang程序在进行数据库事务时被终止时,它能回滚吗?

ipakzgxi  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(303)

假设mariadb兼容的数据库(aws aurora rds)具有默认设置,其中包括启用自动提交,如果lambda函数在执行一个需要5秒以上的事务的3秒后终止,例如。

tx, err := h.db.Begin()
  if err != nil {
      log.WithError(err).Error("failed to start transaction")
  }
  res, execErr := tx.Exec(fmt.Sprintf("UPDATE testtable SET val = %d WHERE id = 1; SELECT SLEEP(5.5);", time.Now().Unix()))
  if execErr != nil {
      log.WithError(err).Error("rolling back")
      err = tx.Rollback()
      if err != nil {
          log.WithError(err).Error("failed to roll back")
      }
  }
  if err := tx.Commit(); err != nil {
      log.WithError(err).Error("failed to commit")
  }

我们会假设结果是什么?交易不会被提交?
我正在使用go-mysql驱动程序v1.3.0-84-g6be42e0 btw。我还制作了一个视频来显示我的结果,但我不知道它是否正确,因为我不明白驱动程序是如何执行回滚的。

klh5stk1

klh5stk11#

如果您使用innodb表,请从https://dev.mysql.com/doc/internals/en/transactions-life-cycle.html:
当连接关闭时,将回滚当前的正常事务(如果有)。
这与go客户机、java客户机、php客户机或任何其他客户机的工作原理相同。
如果使用myisam表,就没有回滚。如果当前正在执行sql更新,它可能会更新某些行的子集,而保留其余行不变。您将得到一个状态不一致的表。非事务表没有acid行为。这就是为什么你不应该使用myisam。

kkbh8khc

kkbh8khc2#

事务sql不提交。我相信在<=5s超时时会发生什么:
开始交易
同步执行sql
mysqld检测到客户端通过tcp-fin断开连接
mysqld自动回滚,因为它看不到提交

一位golang mysql驱动程序维护人员的tweet回复:

mysqld在go客户端终止时接收tcp-fin包。
即使go客户端不干净地退出,os(linux内核等)也会发送tcp-fin或tcp-rst。这样mysqld就可以知道客户不在了。
-稻田直树(@甲烷)2018年12月4日

相关问题