只使用lru
This commit is contained in:
parent
618e8c1aa6
commit
3f922a78c8
8
gorm.go
8
gorm.go
@ -35,7 +35,9 @@ type Config struct {
|
|||||||
// PrepareStmt executes the given query in cached statement
|
// PrepareStmt executes the given query in cached statement
|
||||||
PrepareStmt bool
|
PrepareStmt bool
|
||||||
// PrepareStmt cache support LRU expired
|
// PrepareStmt cache support LRU expired
|
||||||
PrepareStmtLruConfig *PrepareStmtLruConfig
|
PrepareStmtMaxSize int
|
||||||
|
PrepareStmtTTL time.Duration
|
||||||
|
|
||||||
// DisableAutomaticPing
|
// DisableAutomaticPing
|
||||||
DisableAutomaticPing bool
|
DisableAutomaticPing bool
|
||||||
// DisableForeignKeyConstraintWhenMigrating
|
// DisableForeignKeyConstraintWhenMigrating
|
||||||
@ -204,7 +206,7 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.PrepareStmt {
|
if config.PrepareStmt {
|
||||||
preparedStmt := NewPreparedStmtDB(db.ConnPool, config.PrepareStmtLruConfig)
|
preparedStmt := NewPreparedStmtDB(db.ConnPool, config.PrepareStmtMaxSize, config.PrepareStmtTTL)
|
||||||
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
|
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
|
||||||
db.ConnPool = preparedStmt
|
db.ConnPool = preparedStmt
|
||||||
}
|
}
|
||||||
@ -275,7 +277,7 @@ func (db *DB) Session(config *Session) *DB {
|
|||||||
if v, ok := db.cacheStore.Load(preparedStmtDBKey); ok {
|
if v, ok := db.cacheStore.Load(preparedStmtDBKey); ok {
|
||||||
preparedStmt = v.(*PreparedStmtDB)
|
preparedStmt = v.(*PreparedStmtDB)
|
||||||
} else {
|
} else {
|
||||||
preparedStmt = NewPreparedStmtDB(db.ConnPool, db.Config.PrepareStmtLruConfig)
|
preparedStmt = NewPreparedStmtDB(db.ConnPool, db.Config.PrepareStmtMaxSize, db.Config.PrepareStmtTTL)
|
||||||
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
|
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package gorm
|
package lru
|
||||||
|
|
||||||
// golang -lru
|
// golang -lru
|
||||||
//https://github.com/hashicorp/golang-lru
|
//https://github.com/hashicorp/golang-lru
|
84
internal/store/stmt_store.go
Normal file
84
internal/store/stmt_store.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/internal/lru"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StmtStore interface {
|
||||||
|
Get(key string) (*gorm.Stmt, bool)
|
||||||
|
Set(key string, value *gorm.Stmt)
|
||||||
|
Delete(key string)
|
||||||
|
AllMap() map[string]*gorm.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
type DefaultStmtStore struct {
|
||||||
|
defaultStmt map[string]*gorm.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DefaultStmtStore) Init() *DefaultStmtStore {
|
||||||
|
s.defaultStmt = make(map[string]*gorm.Stmt)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DefaultStmtStore) AllMap() map[string]*gorm.Stmt {
|
||||||
|
return s.defaultStmt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DefaultStmtStore) Get(key string) (*gorm.Stmt, bool) {
|
||||||
|
stmt, ok := s.defaultStmt[key]
|
||||||
|
return stmt, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DefaultStmtStore) Set(key string, value *gorm.Stmt) {
|
||||||
|
s.defaultStmt[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DefaultStmtStore) Delete(key string) {
|
||||||
|
delete(s.defaultStmt, key)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
type LruStmtStore struct {
|
||||||
|
lru *lru.LRU[string, *gorm.Stmt]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LruStmtStore) NewLru(size int, ttl time.Duration) {
|
||||||
|
onEvicted := func(k string, v *gorm.Stmt) {
|
||||||
|
if v != nil {
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Print("close stmt err panic ")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if v != nil {
|
||||||
|
err := v.Close()
|
||||||
|
if err != nil {
|
||||||
|
//
|
||||||
|
fmt.Print("close stmt err: ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.lru = lru.NewLRU[string, *gorm.Stmt](size, onEvicted, ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LruStmtStore) AllMap() map[string]*gorm.Stmt {
|
||||||
|
return s.lru.KeyValues()
|
||||||
|
}
|
||||||
|
func (s *LruStmtStore) Get(key string) (*gorm.Stmt, bool) {
|
||||||
|
stmt, ok := s.lru.Get(key)
|
||||||
|
return stmt, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LruStmtStore) Set(key string, value *gorm.Stmt) {
|
||||||
|
s.lru.Add(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LruStmtStore) Delete(key string) {
|
||||||
|
s.lru.Remove(key)
|
||||||
|
}
|
134
prepare_stmt.go
134
prepare_stmt.go
@ -5,7 +5,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"gorm.io/gorm/internal/store"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -19,31 +19,52 @@ type Stmt struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PreparedStmtDB struct {
|
type PreparedStmtDB struct {
|
||||||
Stmts StmtStore
|
Stmts store.StmtStore
|
||||||
Mux *sync.RWMutex
|
Mux *sync.RWMutex
|
||||||
ConnPool
|
ConnPool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPrepareStmtCache(prepareStmtLruConfig *PrepareStmtLruConfig) *StmtStore {
|
const DEFAULT_MAX_SIZE = (1 << 63) - 1
|
||||||
var stmts StmtStore
|
const DEFAULT_TTL = time.Hour * 24
|
||||||
if prepareStmtLruConfig != nil && prepareStmtLruConfig.Open {
|
|
||||||
if prepareStmtLruConfig.Size <= 0 {
|
// newPrepareStmtCache creates a new statement cache with the specified maximum size and time-to-live (TTL).
|
||||||
panic("LRU prepareStmtLruConfig.Size must > 0")
|
// Parameters:
|
||||||
}
|
// - PrepareStmtMaxSize: An integer specifying the maximum number of prepared statements to cache.
|
||||||
lru := &LruStmtStore{}
|
// If this value is less than or equal to 0, the function will panic.
|
||||||
lru.NewLru(prepareStmtLruConfig.Size, prepareStmtLruConfig.TTL)
|
// - PrepareStmtTTL: A time.Duration specifying the TTL for cached statements.
|
||||||
stmts = lru
|
// If this value differs from the default TTL, it will be used instead.
|
||||||
} else {
|
//
|
||||||
defaultStmtStore := &DefaultStmtStore{}
|
// Returns:
|
||||||
stmts = defaultStmtStore.init()
|
// - A pointer to a store.StmtStore instance configured with the provided parameters.
|
||||||
|
//
|
||||||
|
// The function initializes an LRU (Least Recently Used) cache for prepared statements,
|
||||||
|
// using either the provided size and TTL or default values
|
||||||
|
func newPrepareStmtCache(PrepareStmtMaxSize int,
|
||||||
|
PrepareStmtTTL time.Duration) *store.StmtStore {
|
||||||
|
var lru_size = DEFAULT_MAX_SIZE
|
||||||
|
var lru_ttl = DEFAULT_TTL
|
||||||
|
var stmts store.StmtStore
|
||||||
|
if PrepareStmtMaxSize <= 0 {
|
||||||
|
panic("PrepareStmtMaxSize must > 0")
|
||||||
}
|
}
|
||||||
|
if PrepareStmtMaxSize != 0 {
|
||||||
|
lru_size = PrepareStmtMaxSize
|
||||||
|
}
|
||||||
|
if PrepareStmtTTL != DEFAULT_TTL {
|
||||||
|
lru_ttl = PrepareStmtTTL
|
||||||
|
}
|
||||||
|
lru := &store.LruStmtStore{}
|
||||||
|
lru.NewLru(lru_size, lru_ttl)
|
||||||
|
stmts = lru
|
||||||
return &stmts
|
return &stmts
|
||||||
}
|
}
|
||||||
func NewPreparedStmtDB(connPool ConnPool, prepareStmtLruConfig *PrepareStmtLruConfig) *PreparedStmtDB {
|
func NewPreparedStmtDB(connPool ConnPool, PrepareStmtMaxSize int,
|
||||||
|
PrepareStmtTTL time.Duration) *PreparedStmtDB {
|
||||||
return &PreparedStmtDB{
|
return &PreparedStmtDB{
|
||||||
ConnPool: connPool,
|
ConnPool: connPool,
|
||||||
Stmts: *newPrepareStmtCache(prepareStmtLruConfig),
|
Stmts: *newPrepareStmtCache(PrepareStmtMaxSize,
|
||||||
Mux: &sync.RWMutex{},
|
PrepareStmtTTL),
|
||||||
|
Mux: &sync.RWMutex{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +115,8 @@ func (sdb *PreparedStmtDB) Reset() {
|
|||||||
}
|
}
|
||||||
}(stmt)
|
}(stmt)
|
||||||
}
|
}
|
||||||
defaultStmt := &DefaultStmtStore{}
|
defaultStmt := newPrepareStmtCache(0, 0)
|
||||||
defaultStmt.init()
|
sdb.Stmts = *defaultStmt
|
||||||
sdb.Stmts = defaultStmt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *PreparedStmtDB) prepare(ctx context.Context, conn ConnPool, isTransaction bool, query string) (Stmt, error) {
|
func (db *PreparedStmtDB) prepare(ctx context.Context, conn ConnPool, isTransaction bool, query string) (Stmt, error) {
|
||||||
@ -303,77 +323,3 @@ func (tx *PreparedStmtTX) Ping() error {
|
|||||||
}
|
}
|
||||||
return conn.Ping()
|
return conn.Ping()
|
||||||
}
|
}
|
||||||
|
|
||||||
type StmtStore interface {
|
|
||||||
Get(key string) (*Stmt, bool)
|
|
||||||
Set(key string, value *Stmt)
|
|
||||||
Delete(key string)
|
|
||||||
AllMap() map[string]*Stmt
|
|
||||||
}
|
|
||||||
|
|
||||||
type DefaultStmtStore struct {
|
|
||||||
defaultStmt map[string]*Stmt
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DefaultStmtStore) init() *DefaultStmtStore {
|
|
||||||
s.defaultStmt = make(map[string]*Stmt)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DefaultStmtStore) AllMap() map[string]*Stmt {
|
|
||||||
return s.defaultStmt
|
|
||||||
}
|
|
||||||
func (s *DefaultStmtStore) Get(key string) (*Stmt, bool) {
|
|
||||||
stmt, ok := s.defaultStmt[key]
|
|
||||||
return stmt, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DefaultStmtStore) Set(key string, value *Stmt) {
|
|
||||||
s.defaultStmt[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DefaultStmtStore) Delete(key string) {
|
|
||||||
delete(s.defaultStmt, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
type LruStmtStore struct {
|
|
||||||
lru *LRU[string, *Stmt]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LruStmtStore) NewLru(size int, ttl time.Duration) {
|
|
||||||
onEvicted := func(k string, v *Stmt) {
|
|
||||||
if v != nil {
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
fmt.Print("close stmt err panic ")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if v != nil {
|
|
||||||
err := v.Close()
|
|
||||||
if err != nil {
|
|
||||||
//
|
|
||||||
fmt.Print("close stmt err: ", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.lru = NewLRU[string, *Stmt](size, onEvicted, ttl)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LruStmtStore) AllMap() map[string]*Stmt {
|
|
||||||
return s.lru.KeyValues()
|
|
||||||
}
|
|
||||||
func (s *LruStmtStore) Get(key string) (*Stmt, bool) {
|
|
||||||
stmt, ok := s.lru.Get(key)
|
|
||||||
return stmt, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LruStmtStore) Set(key string, value *Stmt) {
|
|
||||||
s.lru.Add(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LruStmtStore) Delete(key string) {
|
|
||||||
s.lru.Remove(key)
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user