Gorm事务有error却不返回会发生什么
Gorm包是大家比较高频使用。正常的用法是,如果有失败返回error,整体rollback,如果不返回error则commit。下面是Transaction的源码:
1 | // Transaction start a transaction as a block, return error will rollback, otherwise to commit. Transaction executes an |
神奇用法
但如果我瞎搞呢?如果有error我仍然返回nil,会发生什么?
1 | err := db.Transaction(func(tx *gorm.DB) error { |
解释
这种情况下,本质看MySQL自身的设计。事务具有原子性,理论上应该要么全部成功,要么全部失败。但如果在一条语句失败后执行COMMIT
,MySQL 会尽力提交已成功执行的语句。例如:
1 | START TRANSACTION; |
在上述例子中,前两条INSERT
语句可能已经成功执行并修改了数据库,而第三条失败。执行COMMIT
后,前两条语句的修改会被永久保存到数据库中,而失败的语句不会回滚整个事务。
其实十分不建议这么用。数据库状态可能会出现部分操作生效,部分未生效的情况,破坏了事务的原子性。这可能导致数据不一致问题,例如业务逻辑上要求某些数据必须同时存在或不存在,但由于这种部分提交的情况,无法保证这种一致性。
MySQL表数据时间的记录时刻
假设数据库是这样的
1 | CREATE TABLE `conversation_new_message` ( |
起一个事务,按照下面的时间点执行,最终的创建时间是多少?是按照insert时刻的时间来的(不同记录不一样),还是按照真正落库的时间来的(不同记录一样)?
发现是按照真正写入的时间来的。其实也比较好理解,虽然我们没有直接赋值,但CURRENT_TIMESTAMP本身在记录创建的时候就已经设置好值了。