mysql - 当 Golang 程序在进行数据库事务时终止时,它可以回滚吗?
问题描述
假设 MariaDB 兼容数据库 (AWS Aurora RDS) 具有默认设置,其中包括启用自动提交,如果 Lambda 函数在执行需要超过五秒的事务三秒后终止,例如
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 顺便说一句。我还制作了一个视频来展示我的结果,但我想知道它是否正确,因为我不明白驱动程序如何执行回滚。
解决方案
事务 SQL 不提交。我相信 <= 5s 超时会发生什么:
- 开始交易
- 同步执行 SQL
- MySQLd 通过TCP FIN检测到客户端断开连接
- MySQLd 自动回滚,因为它没有看到 Commit
来自Golang MySQL 驱动程序维护者之一的推文回复:
当 Go 客户端终止时,mysqld 收到 TCP FIN 数据包。即使 Go 客户端不干净地退出,操作系统(Linux 内核等)也会发送 TCP FIN 或 TCP RST。所以mysqld可以知道客户端已经消失了。— INADA Naoki (@methane) 2018 年 12 月 4 日
推荐阅读
- r - 使用编码在 R 中调度脚本
- javascript - 用锚标记替换字符串的多个部分
- javascript - 如何为 AWS CloudFormation 堆栈和资源实施区域特定配置
- database - 使用 go-pg 从 Postgres 中检索虚拟列
- python - Django:如何根据 order_id 获取 order_detail_data
- perl - Perl 证书认证
- c# - 如何减少大量 combobox.selecteditem 属性的样板代码
- c# - C# 仅从 localhost 访问自托管 WCF 登录页面
- ruby - 使用 IRB.conf 设置自定义 .irbrc 的路径
- swift - AVAudioPCMBuffer 只能获取带有静态/白噪声的音频