mysql 连接配置

一、什么是连接? 什么是连接池?

  • mysql连接‌
    如果你要使用程序进行一次mysql查询,mysql就会返回一个连接。或者你使用命令行mysql -u root -p123456主动发起一个mysql连接。

  • 连接池
    如果你使用完之后,希望这个连接不要断,把这个连接存起来,那么这些存起来的连接集合就是连接池

查询当前的连接mysqladmin -uroot -p123456 processlist,processlist指Show list of active threads in server。
在这里插入图片描述

二、连接的类型

通过MySQL 客户端连接db的是交互会话,通过jdbc等程序连接db的是非交互会话。

三、连接的状态

  • open
    当有连接处于任务期间(如执行查询、更新等操作)时,该连接即为open状态。SetMaxOpenConns可以配置允许同时处于open状态的连接数。
  • idle
    当连接完成任务后即处于空闲状态。SetMaxIdleConns可以配置允许空闲的数量。
    如果连接池中你允许的空闲数量为0,即每个连接都将是短连接。在完成任务后自动释放。
    如果连接池中你允许的空闲数量大于0,当连接完成任务后将继续存在连接池中。等下一次有任务过来时,将会返回连接池中的空闲连接去执行任务。

四、连接超时

  • wait_timeout
    MySQL服务器关闭非交互式连接前等待的秒数。
    当连接保持空闲状态超过一定时间没有任务处理,则该空闲连接将会过期。mysql默认是8h。
    使用root账号执行以下命令,并新开一个连接,连接的超时不受WAIT_TIMEOUT限制。因为这里是交互式会话连接所以不受影响。

    set global WAIT_TIMEOUT=3;
    

    但如果执行下面的命令,则立刻会对该会话的当前连接生效。但不作用于新返回的连接,原因不知。

    set session WAIT_TIMEOUT=3;
    

    在这里插入图片描述

  • MaxLifetime
    生命时长超时。指从连接创建开始到当前时间。

  • interactive_timeout
    MySQL服务器关闭交互式连接前等待的秒数。即交互式连接超时。当使用命令行进行连接时,从获得连接开始,默认8h。
    执行以下命令,并打开一个新连接,超过时间限制后进行访问,将会提示MySQL server has gone away

    set global INTERACTIVE_TIMEOUT=10;
    

    在这里插入图片描述

  • ReadTimeout
    在mysql命令行,从发送请求开始,超过一定时间仍未返回数据。主要和网络环境相关。

以上几个超时时间,有几个点需要注意

  1. wait_timeout是非交互式的超时时间,interactive_timeout是交互式的超时时间
  2. 服务端wait_timeout默认的超时时长是8h,如果允许连接池出现空闲连接,且code端不限制超时,则会出现连接超时不可用的异常。需在code端限制连接时间小于wait_timeout。即SetConnMaxLifetime<wait_timeout。

下面使用gorm进行测试WAIT_TIMEOUT

package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type People struct {
	Age  int
}

func main() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		fmt.Printf("%v", err)
		return
	}
	people := &People{}
	err = db.Table("people").First(people).Error
	fmt.Printf("%v %v", people, err)
}

  • 执行set global WAIT_TIMEOUT=3;
  • code执行到获取连接’db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})’,
  • 执行mysqladmin -uroot -p123456 processlist,可看见有code的db连接。
    在这里插入图片描述
  • 3秒后再执行mysqladmin -uroot -p123456 processlist,可以看见那个连接失效了。
  • 执行完剩余代码,没有err,但有以下提示。原来了的空闲连接失效了,最后重新返回了一个新的连接,并返回了数据。执行完查询语句时,可以通过命令查询当前连接,的确是出现了新的db连接。
    在这里插入图片描述

四、Golang 访问mysql

在database/sql 下,sql.DB 通过数据库驱动为我们提供管理底层数据库连接的打开和关闭操作,sql.DB 为我们管理数据库连接池。通过sql.DB获取到的连接,默认是一个长连接
需要注意的是,sql.DB表示操作数据库的抽象访问接口,而非一个数据库连接对象。它可以根据driver打开关闭数据库连接,管理连接池。正在使用的连接被标记为繁忙,用完后回到连接池等待下次使用。所以,如果你没有把连接释放回连接池,会导致过多连接使系统资源耗尽。

需要注意的点:

  1. sql.Open并不会立即建立一个数据库的网络连接, 也不会对数据库链接参数的合法性做检验, 它仅仅是初始化一个sql.DB对象. 当真正进行第一次数据库查询操作时, 此时才会真正建立网络连接;
  2. sql.DB表示操作数据库的抽象接口的对象,但不是所谓的数据库连接对象,sql.DB对象只有当需要使用时才会创建连接,如果想立即验证连接,需要用Ping()方法;
  3. sql.Open返回的sql.DB对象是协程并发安全的.
  4. sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close。比较好的做法是,为每个不同的datastore建一个DB对象,保持这些对象Open。如果需要短连接,那么把DB作为参数传入function,而不要在function中Open, Close。

连接配置方式:

  • DB.SetMaxOpenConns(1),设置允许open的连接数量,如果设置为0,认为是1。
  • DB.SetMaxIdleConns(1),设置允许空闲的连接,如果设置为0,则认为全为短连接,使用完后自动释放。
package main

import (
	"database/sql"
	"errors"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	_ = testDB()
}

func getDB() *sql.DB {
	var DBTemp *sql.DB
	var dataBase = "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True"

	var err error
	DBTemp, err = sql.Open("mysql", dataBase)
	if err != nil {
		log.Fatalln("open db fail:", err)
	}

	DBTemp.SetMaxOpenConns(1)
	DBTemp.SetMaxIdleConns(1)
	return DBTemp
}

func testDB() error {

	DB := getDB()
	defer DB.Close()
	rows, err := DB.Query("select * from people")
	if err != nil {
		return err
	}
	defer rows.Close()
	//字典类型
	//构造scanArgs、values两个数组,scanArgs的每个值指向values相应值的地址
	columns, _ := rows.Columns()
	scanArgs := make([]interface{}, len(columns))
	values := make([]sql.RawBytes, len(columns))
	for i := range values {
		scanArgs[i] = &values[i]
	}

	//最后得到的map
	results := make(map[int]map[string]string)
	i := 0
	for rows.Next() {
		//将行数据保存到record字典
		err = rows.Scan(scanArgs...)
		if err != nil {
			return errors.New("结果组装失败,原因:\n" + err.Error())
		}
		row := make(map[string]string)
		for k, v := range values {
			key := columns[k]
			row[key] = string(v)
		}
		results[i] = row
		i++

	}
	return nil
}

参考
MySQL连接池与超时设定
配置 sql.DB 获得更好的性能
golang操作mysql使用总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值