golang 按照某个字段分表
package db
import (
"fmt"
"github.com/fwhezfwhez/cmap"
"github.com/fwhezfwhez/errorx"
"github.com/garyburd/redigo/redis"
"github.com/jinzhu/gorm"
"strings"
"time"
)
var existTable = cmap.NewMapV2(nil, 2, 15*time.Second)
type table interface {
TableName() string
SourceTableName() string
}
var tmpl = `create table ${table_name} (like ${source_table_name} including all);`
func MustHaveTable(
engine *gorm.DB, // 提供数据查表是否创建,以及创表句柄
t table, // 提供表的源表名,和分表名
f func() redis.Conn, // 提供获取conn的方法,用于分布式环境创建唯一)
) (bool, error) {
created, exist := existTable.Get(t.TableName())
if exist && created == true {
return true, nil
}
if engine.HasTable(t) {
existTable.SetEx(t.TableName(), true, 60)
return true, nil
}
// 15秒内的并发下,只会有一条,走进创建语句
if !once(f(), fmt.Sprintf("%s:auto_create_%s:%s", config.Node.AppName, config.Node.Mode, t.TableName()), 15) {
return true, nil
}
sql := strings.ReplaceAll(tmpl, "${table_name}", t.TableName())
sql = strings.ReplaceAll(sql, "${source_table_name}", t.SourceTableName())
// do create
if e := engine.Exec(sql).Error; e != nil {
return false, errorx.Wrap(e)
}
existTable.SetEx(t.TableName(), true, 60)
return true, nil
}