Golang数据库Xorm引擎调优

XORM引擎

创建

在xorm里面,可以同时存在多个Orm引擎,一个Orm引擎称为Engine,一个Engine一般只对应一个数据库。Engine通过调用xorm.NewEngine生成,如:

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/xormplus/xorm"
)

var engine *xorm.Engine

func main() {
    var err error
    engine, err = xorm.NewEngine("mysql", "root:123@/test?charset=utf8")
}

or

import (
    _ "github.com/mattn/go-sqlite3"
    "github.com/xormplus/xorm"
)

var engine *xorm.Engine

func main() {
    var err error
    engine, err = xorm.NewEngine("sqlite3", "./test.db")
}

您也可以针对特定数据库及数据库驱动使用类似下面的快捷方式创建引擎

engine, err = xorm.NewPostgreSQL(dataSourceName)
engine, err = xorm.NewSqlite3(dataSourceName)

一般情况下如果只操作一个数据库,只需要创建一个engine即可。engine是GoRutine安全的。

创建完成engine之后,并没有立即连接数据库,此时可以通过engine.Ping()来进行数据库的连接测试是否可以连接到数据库。另外对于某些数据库有连接超时设置的,可以通过起一个定期Ping的Go程来保持连接鲜活。

对于有大量数据并且需要分区的应用,也可以根据规则来创建多个Engine,比如:

var err error
for i:=0;i<5;i++ {
    engines[i], err = xorm.NewEngine("sqlite3", fmt.Sprintf("./test%d.db", i))
}

engine可以通过engine.Close来手动关闭,但是一般情况下可以不用关闭,在程序退出时会自动关闭。

NewEngine传入的参数和sql.Open传入的参数完全相同,因此,在使用某个驱动前,请查看此驱动中关于传入参数的说明文档。以下为各个驱动的连接符对应的文档链接:

在engine创建完成后可以进行一些设置,如:

日志

日志是一个接口,通过设置日志,可以显示SQL,警告以及错误等,默认的显示级别为INFO。

  • engine.ShowSQL(true),则会在控制台打印出生成的SQL语句;
  • engine.Logger().SetLevel(core.LOG_DEBUG),则会在控制台打印调试及以上的信息;

如果希望将信息不仅打印到控制台,而是保存为文件,那么可以通过类似如下的代码实现,NewSimpleLogger(w io.Writer)接收一个io.Writer接口来将数据写入到对应的设施中。

f, err := os.Create("sql.log")
if err != nil {
    println(err.Error())
    return
}
engine.SetLogger(xorm.NewSimpleLogger(f))

当然,如果希望将日志记录到syslog中,也可以如下:

logWriter, err := syslog.New(syslog.LOG_DEBUG, "rest-xorm-example")
if err != nil {
	log.Fatalf("Fail to create xorm system logger: %v\n", err)
}

logger := xorm.NewSimpleLogger(logWriter)
logger.ShowSQL(true)
engine.SetLogger(logger)

连接池

engine内部支持连接池接口和对应的函数。

  • 如果需要设置连接池的空闲数大小,可以使用engine.SetMaxIdleConns()来实现。
  • 如果需要设置最大打开连接数,则可以使用engine.SetMaxOpenConns()来实现。

查看服务器设置

67服务器和70服务器配置一样,windows使用资源管理器查看,发现是24核心的

image-20210813163543893

查看数据库设置

查看最大连接数设置
show variables like 'max_connections';

image-20210813163924489

查看连接列表
show processlist;

image-20210813165028327

查看连接存活时长
show variables like 'wait_timeout';

这个wait_timeout的作用是,设置非交互连接(就是指那些连接池方式、非客户端方式连接的)的超时时间,默认是28800,就是8小时,超过这个时间,mysql服务器会主动切断那些已经连接的,但是状态是sleep的连接。

image-20210813163751489

SetMaxOpenConns(maxOpenConns)

连接池最多同时打开的连接数。

这个maxOpenConns理应要设置得比mysql服务器的max_connections值要小。

一般设置为: 服务器cpu核心数 * 2 + 服务器有效磁盘数。

可用show variables like ‘max_connections’; 查看服务器当前设置的最大连接数。

SetMaxIdleConns(maxIdleConns)

连接池里最大空闲连接数。必须要比maxOpenConns小;

SetConnMaxIdleTime(maxIdleTime)(xorm里面没有这个,哈哈)

连接池里面的连接最大空闲时长。

当连接持续空闲时长达到maxIdleTime后,该连接就会被关闭并从连接池移除,哪怕当前空闲连接数已经小于SetMaxIdleConns(maxIdleConns)设置的值。

连接每次被使用后,持续空闲时长会被重置,从0开始从新计算;

用show processlist; 可用查看mysql服务器上的连接信息,Command表示连接的当前状态,Command为Sleep时表示休眠、空闲状态,Time表示此状态的已持续时长;
img

SetConnMaxLifetime(maxLifeTime)

连接池里面的连接最大存活时长。

maxLifeTime必须要比mysql服务器设置的wait_timeout小,否则会导致golang侧连接池依然保留已被mysql服务器关闭了的连接。

mysql服务器的wait_timeout默认是8 hour,可通过show variables like 'wait_timeout’查看。

最终配置

package datasource

import (
	_ "github.com/go-sql-driver/mysql" //不能忘记导入
	"github.com/go-xorm/xorm"
	"time"
	"xorm.io/core"
)

/**
 * 实例化数据库引擎方法:mysql的数据引擎
 */
func NewMysqlEngine(dbName string) *xorm.Engine {

	//数据库引擎
	dsName := "root:密码@tcp(127.0.0.1:3306)/" + dbName + "?charset=utf8"
	engine, err := xorm.NewEngine("mysql", dsName)

	//根据实体创建表
	//err = engine.CreateTables(new(model.Admin))

	//同步数据库结构:主要负责对数据结构实体同步更新到数据库表
	/**
	 * 自动检测和创建表,这个检测是根据表的名字
	 * 自动检测和新增表中的字段,这个检测是根据字段名,同时对表中多余的字段给出警告信息
	 * 自动检测,创建和删除索引和唯一索引,这个检测是根据索引的一个或多个字段名,而不根据索引名称。因此这里需要注意,如果在一个有大量数据的表中引入新的索引,数据库可能需要一定的时间来建立索引。
	 * 自动转换varchar字段类型到text字段类型,自动警告其它字段类型在模型和数据库之间不一致的情况。
	 * 自动警告字段的默认值,是否为空信息在模型和数据库之间不匹配的情况
	 */

	//Sync2是Sync的基础上优化的方法
	//err = engine.Sync2(
	//	new(models.Admin),
	//)
	if err != nil {
		panic(err.Error())
	}else{
		// 设定表及列映射规则
		engine.SetTableMapper(core.GonicMapper{})
		engine.SetColumnMapper(core.GonicMapper{})
	}

	//设置显示sql语句
	//engine.ShowSQL(true)
	// 设置连接池最大打开连接数(服务器核心数*2+有效磁盘数)
	engine.SetMaxOpenConns(50)
	// 设置连接池的空闲数大小
	engine.SetMaxIdleConns(5)
	// 设置空闲连接最大时长
	// engine.SetConnMaxIdleTime(600) xorm没有这个功能
	// 设置连接最大存活时长,必须小于mysql的wait_timeout
	// mysql wait_timeout单位是s,time.Duration 默认是纳秒,后面*1000000000,转化成s
	// 设置为4h
	engine.SetConnMaxLifetime(14400 *time.Second)
	// 或者
	// engine.SetConnMaxLifetime(4 *time.Hour)

	return engine
}

总结

golang里面的time.Duration的精细坑

上面参数的设置,类型是time.Duration

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
func (engine *Engine) SetConnMaxLifetime(d time.Duration) {
	engine.db.SetConnMaxLifetime(d)
}

然而python里面的time.sleep(60),单位直接就是s

golang正事不干,默认的是纳秒,笑了;查了下time.go源码

源码是这样写的

const (
	Nanosecond  Duration = 1
	Microsecond          = 1000 * Nanosecond
	Millisecond          = 1000 * Microsecond
	Second               = 1000 * Millisecond
	Minute               = 60 * Second
	Hour                 = 60 * Minute
)

也就是说下面两句是等价的

	timeTest(60* time.Second)
	timeTest(60000000000)

这个也是等价的

	engine.SetConnMaxLifetime(14400 *time.Second)
	engine.SetConnMaxLifetime(4 *time.Hour)
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐