误用gorm引起的一宗血案
现象
某服务A从晚上6点开始,监控一直出现mysql调用延迟超高,http接口500飙升  
原因
经查发现是一条全局update整张表的sql引起的,全局lock表
最小化
使用下面操作进行最小化
建库 create databses test;
建表 CREATE TABLE `Record` ( `id`  BIGINT NOT NULL, `count` BIGINT NOT NULL, PRIMARY KEY(`id`) ) ENGINE = InnoDB;
插入一条数据 CREATE TABLE `Record` ( `id`  BIGINT NOT NULL, `count` BIGINT NOT NULL, PRIMARY KEY(`id`) ) ENGINE = InnoDB;
代码如下:
package main
import (  
        "bufio"
        "github.com/jinzhu/gorm"
        _ "github.com/jinzhu/gorm/dialects/mysql"
        "log"
        "os"
)
type Record struct {  
        Id    int64 `gorm:"column:id;type:bigint;primary_key",db:"id"`
        Count int64 `gorm:"column:count;type:bigint",db:"count"`
}
func (Record) TableName() string {  
        return "Record"
}
func main() {  
        var bio *bufio.Reader
        var db *gorm.DB
        var err error
        log.Printf("############# main")
        bio = bufio.NewReader(os.Stdin)
        bio.ReadString('\n')
        // 连接数据库
        db, err = gorm.Open("mysql", "root:123456@/test?charset=utf8&parseTime=True&loc=Local")
        if err != nil {
                panic("db link failed")
        }
        defer db.Close()
        log.Printf("db link")
        bio = bufio.NewReader(os.Stdin)
        bio.ReadString('\n')
        // 查找数据
        var record Record
        queryResult := db.Where("id = ?", 20).Find(&record)
        if queryResult.RecordNotFound() {
                log.Printf("Not found")
                return
        }
        log.Printf("############ pass NOTFOUND")
        bio = bufio.NewReader(os.Stdin)
        bio.ReadString('\n')
        //if queryResult.Error != nil {
        //      log.Fatalf("Error %s ", queryResult.Error)
        //      return
        //}
        log.Printf("search ok ")
        // 更新数据
        if err = db.Model(&record).UpdateColumn("count", record.Count+1).Error; err != nil {
                panic(err)
        }
        log.Printf("update ok ")
}
复现步骤,就是 
1.运行程序,连接db 
2.关闭数据库 
3.回车继续程序,程序执行到查询id = 20,这时候db连接是有错误的,但是找到数据、非RecordNotFound的错误都是返回true 
4.开启数据库 
5.回车继续程序,程序执行到更新数据库的数据,传入record主键id是一个空,导致会更新全表,并且覆盖所有count = 1    
幸好表很大,导致超时,该类操作的数据都被回滚了