mysql里面要把两个不同的数据库的操作规定到一个事务里面。
现在有两个数据库Db_A和Db_B。Db_A中有两个表Node和manager;Db_B中有两个表user和appkey_to_user。
现在接口的需求是:由于两个数据库中的四个表之间的一些字段是对应的,在进行删表和增表的时候,为了保证原子性,需要开启mysql中的事务操作。
问题是:能否用两个db,分别开两个事务进行操作,这样是否也可以保证原子性?(示例代码如下,用gorm操作数据库)
// 分别开启事务
db1 := Db_A.Begin()
db2 := Db_B.Begin()
if err := db1.Where("id=?", 1).First(&Node).Error; err != nil {
db1.Rollback()
db2.Rollback()
}
if err := db2.Where("id=?", 1).First(&User).Error; err != nil {
db1.Rollback()
db2.Rollback()
}
// 此处省略一些其他的crud操作
db1.Commit()
db2.Commit()
这种写法总感觉不符合“将整个操作统一起来的”的原子性要求。而且不清楚这样写能不能满足db1和db2的操作要么全部成功,要么直接回滚的需求?
像这种mysql里面,多表进行操作的事务,有没有更好的写法?
原生sql语句:多库事务的操作
set autocommit = 0;
update db1.t1 set c1='test' where id = 1 ;
select sleep(3);
update db2.t1 set c1='test' where id = 1;/*db2.t1表故意不要创建c1列制造错误*/
select sleep(3);
commit;
由于gorm没有提供官方的切换数据库函数,所以在进行多表操作时候可以先调用gorm提供的Exec()函数手动切换到另外一个数据库中,然后再进行操作,示例如下:
// 可以和上面的示例代码进行对比
db1 := Db_A.Begin()
if err := db1.Where("id=?", 1).First(&Node).Error; err != nil {
db1.Rollback()
}
// 只需要手动切换到Db_B数据库即可!
if err := db1.Exec("use DBNameOfDb_B").Where("id=?", 1).First(&User).Error; err != nil {
db1.Rollback()
}
// 此处省略一些其他的crud操作
db1.Commit()
以上就是我在使用gorm进行多表操作时的一些心得,由于作者能力有限,欢迎大家评论指正!