gorm高并发插入时正确链接tidb的方式是什么

【 TiDB 使用环境】生产环境 /测试/ Poc
【 TiDB 版本】
【复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面
【附件:截图/日志/监控】
// GetTiDBClient returns a gorm.DB client for the specified database.
func GetTiDBClient(database string) (*gorm.DB, error) {

// Check if the client already exists
if db, exists := clientmap[database]; exists {
	return db, nil
}
return createNewClient(database)

}

// createNewClient creates a new gorm.DB client and stores it in the map.
func createNewClient(database string) (*gorm.DB, error) {
dsn, s := getDSN(database)
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: s,
DSNConfig: dsn,
}), &gorm.Config{})
if err != nil {
log.Error(“Tidb error”, log.MessageField, “Failed to get client, error %s”, err.Error())
return nil, err
}
// Store the new connection in the map
sqlDB, _ := db.DB()
sqlDB.SetConnMaxIdleTime(time.Hour * 2)
sqlDB.SetConnMaxLifetime(time.Hour * 2)
mu.Lock()
clientmap[database] = db
mu.Unlock()
go func() {
for {
time.Sleep(time.Minute * 119)
mu.Lock()
delete(clientmap, database)
mu.Unlock()
break
}
return
}()
return db, nil
}
这是目前应用的链接方法,每次获取链接时将存在map中的链接返回,链接过期后重新获取新的链接放到map中,在这种方式下50个并发插入使用的都是map中的同一个库的链接,这样不会造成插入线程排队吗

gorm.DB对象本身就是个连接池,获取到的是不同的连接,可以通过数据库会话查一下

是不需要放到map中,只需要配置gorm的连接数就行了吗

如果database变量都是同一个数据源的话就不需要用map包一层

用这个方法50个并发一秒只能插入160条数据,用py和java同样环境能插入上千条,我怀疑是不是一直复用同一个数据库链接并发排队了

发一下完整代码看看

func GetDB(database string, collection string) (MongoOrGorm, error) {
if c.MongoOrTiDB == 0 {
client, err := GetClient()
if err != nil {
return MongoOrGorm{}, err
}
db := client.Database(database).Collection(collection)
if db != nil {
return MongoOrGorm{
gorm: nil,
mongos: db,
dbname: “”,
}, nil
} else {
return MongoOrGorm{}, GetDataBaseError
}
} else {
tidb, err := GetTiDBClient(database)
if err != nil {
return MongoOrGorm{}, GetDataBaseError
}
return MongoOrGorm{
gorm: tidb,
mongos: nil,
dbname: “" + collection + "”,
}, nil
}
}

func getDSN(database string) (a *sls.Config, string2 string) {
caCert, _ := ioutil.ReadFile(“/home/gdas/conf/tidb/certificates/root.crt”)
clientCert, _ := tls.LoadX509KeyPair(“/home/gdas/conf/tidb/certificates/client.crt”, “/home/gdas/conf/tidb/certificates/client.key”)
// 设置 TLS 配置
tlsConfig := tls.Config{}
tlsConfig.RootCAs = x509.NewCertPool()
tlsConfig.RootCAs.AppendCertsFromPEM(caCert)
tlsConfig.Certificates = tls.Certificate{clientCert}
err := sls.RegisterTLSConfig(“custom”, &tlsConfig)
if err != nil {
return nil, “”
}
config := sls.Config{
User: c.TiDBUser,
Passwd: c.TiDBPassword,
Net: “tcp”,
Addr: c.TiDBHost + “:” + c.TiDBPort,
DBName: database,
AllowNativePasswords: true,
TLS: &tlsConfig,
ParseTime: true,
}
tidbHost := c.TiDBHost
tidbPort := c.TiDBPort
tidbUser := c.TiDBUser
tidbPassword := c.TiDBPassword
tidbDBName := database
useSSL := “true”
return &config, fmt.Sprintf(“%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&tls=%s&parseTime=True&tls=custom”,
tidbUser, tidbPassword, tidbHost, tidbPort, tidbDBName, useSSL)
}

很多常见的数据库驱动诸如go里的sql.DB这种,一个DB对象表示的就是一个连接池,不是连接,如hoho所说你只要为这个DB设置好连接池属性即可,不用自己维护连接池,看下对应驱动的文档看看默认几个连接,放大看看;再到数据库里看看跑的时候有几个连接活动即可。

看下50个并发写入是怎么实现的

mu.Lock()
delete(clientmap, database)
mu.Unlock() 这个代码还需要你自己去维护连接池?

batch insert 效率不会更高么,并发要结合起来用吧