Mysql连接无效(invalid connection)解决方案以及其他问题

1,505 阅读4分钟

1.Mysql连接无效(invalid connection)出现原因

a.SetConnMaxLifetime最大有效时间过大问题

首先查看mysql此配置的参数

show variables like 'wait_timeout

使用go gorm时其中SetConnMaxLifetime(d time.Duration)是用来设置连接池里每条连接关闭的时间,当d <= 0时,连接池里的连接永久重用,即永远都在连接池里,拿来就用,不管此连接是否真的有效(这里有问题,下面讲)。当d > 0时,到了时间d才会关闭连接,把连接移出连接池,但这并不是时间一到就关闭,因为当连接还在使用时会等连接完成之后,等下一个清理连接周期(周期为d)时会关闭连接,移出连接池。

Mysql为了防止空闲连接过多,超过了参数mysql_connection之后会拒绝新连接,mysql会自动关闭空闭连接超过wait_timeout参数的时间,会关闭使用中超过interactive_timeout参数的连接。

由于mysql会自动关闭超时连接,所以database/sql的SetSetMaxIdleConns()不能设置为永久有效,要不然连接已经被mysql关闭了,但还是拿着失效的连接使用就会报invalid connection。

解决的方案就是SetConnMaxLifetime()设置的时间小于wait_timeout就行,一般建议wait_timeout/2。

b.数据表(oceanbase)死锁导致该表数据插入和更新出现invalid connection,查询该表没问题** 出现的问题原因,使用一条alert语句添加某个字段,同时为其设置查询索引

ALTER TABLE questions 
ADD COLUMN dnb_status TINYINT(4) DEFAULT 0 COMMENT '入库状态:0-成功,1-外部url 2-识别失败',
ADD INDEX dnb_status_idx (dnb_status)

由于数据量比较大,alert语句更新很长,而且很可能造成了死锁,这么一条sql语句导致整张表数据所有的写入更新失败,严重影响了业务

临时解决办法,kill 掉该语句,然后找机会使用两个alter语句,分别创建

2.mysql报错

SaveImportSingleQuestion err: Error 1390 (HY000): Prepared statement contains too many placeholders**

使用gorm createinBatches() 代替save()

3.http报错超时,mysql 可能是连接池连接数不够

gorm使用处理

1.在 GORM(Go 语言的一个 ORM 库)中,以下查询方法在找不到任何记录时会返回 gorm.ErrRecordNotFound 错误:

First:当你使用 First 方法查询数据库,如果没有找到任何记录,GORM 会返回 gorm.ErrRecordNotFound 错误。
Take:当你使用 Take 方法查询数据库,如果没有找到任何记录,GORM 也会返回 gorm.ErrRecordNotFound 错误。
Last:当你使用 Last 方法查询数据库,如果没有找到任何记录,GORM 也会返回 gorm.ErrRecordNotFound 错误。

first就是按照主键排序取第条记录,last就是按照主键倒排,也就是取最后一条记录

这些方法都会返回 gorm.ErrRecordNotFound 错误,因为它们都期望至少找到一条记录。如果没有找到任何记录,那么就会返回这个错误。

Find:如果没有找到任何记录,在 GORM 中,Find 方法不会在没有找到记录时返回 gorm.ErrRecordNotFound 错误。它会返回一个空的结果集和一个 nil 错误。你可以通过检查结果集是否为空来判断是否找到了任何记录。
var users []User
result := db.Find(&users)
// users 变量现在包含了所有的用户,如果没有找到任何用户,users 就是一个空切片

获取特定的列:如果你只关心一个或几个特定的字段,而不是整个记录,你可以使用 Pluck 来只获取这些字段

Pluck() 
var ids []int
db.Model(&User{}).Pluck("id", &ids)

2.Take 和 First区别?
在 GORM(Go 语言的一个 ORM 库)中,Take 和 First 方法都用于从数据库中查询数据,但它们的行为有所不同:
First 方法:这个方法返回匹配查询条件的第一条记录。如果没有找到任何记录,GORM 会返回 gorm.ErrRecordNotFound 错误。此外,First 方法会自动为查询添加 ORDER BY 子句,按主键的升序排序。
Take 方法:这个方法也返回匹配查询条件的第一条记录。如果没有找到任何记录,GORM 会返回 gorm.ErrRecordNotFound 错误。但是,与 First 方法不同,Take 方法不会自动添加 ORDER BY 子句。
总的来说,First 和 Take 方法的主要区别在于,First 方法会自动为查询添加 ORDER BY 子句,按主键的升序排序,而 Take 方法不会。