记一次gorm事务及调试解决mysql死锁 |
您所在的位置:网站首页 › 数据库死锁问题解决 › 记一次gorm事务及调试解决mysql死锁 |
前言
之前使用mysql和postgresql是通过sqlc包来使用,这一次使用gorm,还是遇到了很多问题,在此记录以下。 版本问题gorm大版本更新之后,驱动的引入及实际的用法和老版本会有一些区别,特别是事务、锁的使用以及配置项的修改。 新版本gorm数据库链接方式以及包的名称和老版本相比均有改变,如下: 老版本: import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) db, err := gorm.Open("mysql", "root:xxxx@(127.0.0.1:3306)/db01?&parseTime=True&loc=Local")而新版本: import ( "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/schema" ) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})老版本的配置项通过db.xx的形式修改: db.LogMode(true) db.DB().SetMaxIdleConns(10) db.DB().SetMaxOpenConns(100) db.SingularTable(true)而新版本均通过&gorm.Config{}字段进行修改: db, err = gorm.Open(mysql.Open(dbLink), &gorm.Config{ SkipDefaultTransaction: true, //开启事务 NamingStrategy: schema.NamingStrategy{ SingularTable: true, },forupdate的用法改变: 最开始依旧使用老版本的用法来使用,但是一直不成功,然后使用debug打印sql语句,发现生成的sql语句并没有for update相关操作,再去查找资料,发现老版本写法不生效,更换为新的写法。 老版本: result := tx.Debug().Set("gorm:query_option", "FOR UPDATE").First(&user1, arg.FromUserID)新版本: result = tx.Debug().Clauses(clause.Locking{Strength: "UPDATE"}).First(&user2, arg.ToUserID) 数据库死锁的排查解决:在一个类似于转账的场景,为了保证转账的一致性,在相关的接口中使用了事务来保证转账成功,在最后测试同一个账户有人转出,有人转入时出现死锁; 根据网上查询以及一位大佬博文(http://t.csdn.cn/nAzEf)的思路下,在终端还原了死锁场景。 分别开启两个事务,按照顺序进行update操作:在执行第4步即事务2中的第二条操作时,出现死锁。 事务1: 1 update user set collection_coins = collection_coins - 10 where id = 1537973755; 3 update user set collection_coins = collection_coins + 10 where id = 1338725819; 等待获取锁 事务2: 2 update user set collection_coins = collection_coins - 10 where id = 1338725819; 4 update user set collection_coins = collection_coins + 10 where id = 1537973755;查询相关锁的表,能看到在发生死锁的上一步: 分别运行以下两个语句: select * from information_schema.innodb_locks; select * from information_schema.innodb_lock_waits;
可以看到 解决办法则是: 调换4个语句的执行顺序; 如果按照1-4-3-2的顺序来进行则不会造成死锁。 因为在执行1后,事务1获得锁1,此时事务2执行4,事务2请求锁1,此时事务2阻塞; 事务1再执行3,获得锁2;此时事务1执行完毕,commit释放锁1和锁2,事务2获得锁1,语句4执行成功,再执行语句2成功,则不会发生死锁。 换到代码中则是对执行顺序进行排列,利用id为数字格式,可以比大小,则按照大小进行排列即可; |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |