// NewQueryEngine creates a new QueryEngine. // This is a singleton class. // You must call this only once. func NewQueryEngine(config Config) *QueryEngine { qe := &QueryEngine{} qe.schemaInfo = NewSchemaInfo(config.QueryCacheSize, time.Duration(config.SchemaReloadTime*1e9), time.Duration(config.IdleTimeout*1e9)) mysqlStats = stats.NewTimings("Mysql") // Pools qe.cachePool = NewCachePool("Rowcache", config.RowCache, time.Duration(config.QueryTimeout*1e9), time.Duration(config.IdleTimeout*1e9)) qe.connPool = dbconnpool.NewConnectionPool("ConnPool", config.PoolSize, time.Duration(config.IdleTimeout*1e9)) qe.streamConnPool = dbconnpool.NewConnectionPool("StreamConnPool", config.StreamPoolSize, time.Duration(config.IdleTimeout*1e9)) qe.txPool = dbconnpool.NewConnectionPool("TransactionPool", config.TransactionCap, time.Duration(config.IdleTimeout*1e9)) // connections in pool has to be > transactionCap // Services qe.activeTxPool = NewActiveTxPool("ActiveTransactionPool", time.Duration(config.TransactionTimeout*1e9)) qe.connKiller = NewConnectionKiller(1, time.Duration(config.IdleTimeout*1e9)) qe.activePool = NewActivePool("ActivePool", time.Duration(config.QueryTimeout*1e9), qe.connKiller) qe.consolidator = NewConsolidator() qe.invalidator = NewRowcacheInvalidator(qe) qe.streamQList = NewQueryList(qe.connKiller) // Vars qe.spotCheckFreq = sync2.AtomicInt64(config.SpotCheckRatio * SPOT_CHECK_MULTIPLIER) if config.StrictMode { qe.strictMode.Set(1) } qe.strictTableAcl = config.StrictTableAcl qe.maxResultSize = sync2.AtomicInt64(config.MaxResultSize) qe.streamBufferSize = sync2.AtomicInt64(config.StreamBufferSize) // loggers qe.accessCheckerLogger = logutil.NewThrottledLogger("accessChecker", 1*time.Second) // Stats stats.Publish("MaxResultSize", stats.IntFunc(qe.maxResultSize.Get)) stats.Publish("StreamBufferSize", stats.IntFunc(qe.streamBufferSize.Get)) queryStats = stats.NewTimings("Queries") QPSRates = stats.NewRates("QPS", queryStats, 15, 60*time.Second) waitStats = stats.NewTimings("Waits") killStats = stats.NewCounters("Kills") infoErrors = stats.NewCounters("InfoErrors") errorStats = stats.NewCounters("Errors") internalErrors = stats.NewCounters("InternalErrors") resultStats = stats.NewHistogram("Results", resultBuckets) stats.Publish("RowcacheSpotCheckRatio", stats.FloatFunc(func() float64 { return float64(qe.spotCheckFreq.Get()) / SPOT_CHECK_MULTIPLIER })) spotCheckCount = stats.NewInt("RowcacheSpotCheckCount") return qe }
// NewMysqld creates a Mysqld object based on the provided configuration // and connection parameters. func NewMysqld(config *Mycnf, dba, allprivs, app, repl *sqldb.ConnParams, enablePublishStats bool) *Mysqld { noParams := sqldb.ConnParams{} if *dba == noParams { dba.UnixSocket = config.SocketFile } // create and open the connection pool for dba access dbaMysqlStatsName := "" dbaPoolName := "" if enablePublishStats { dbaMysqlStatsName = "MysqlDba" dbaPoolName = "DbaConnPool" } dbaMysqlStats := stats.NewTimings(dbaMysqlStatsName) dbaPool := dbconnpool.NewConnectionPool(dbaPoolName, *dbaPoolSize, *dbaIdleTimeout) dbaPool.Open(dbconnpool.DBConnectionCreator(dba, dbaMysqlStats)) // create and open the connection pool for allprivs access allprivsMysqlStatsName := "" if enablePublishStats { allprivsMysqlStatsName = "MysqlAllPrivs" } allprivsMysqlStats := stats.NewTimings(allprivsMysqlStatsName) // create and open the connection pool for app access appMysqlStatsName := "" appPoolName := "" if enablePublishStats { appMysqlStatsName = "MysqlApp" appPoolName = "AppConnPool" } appMysqlStats := stats.NewTimings(appMysqlStatsName) appPool := dbconnpool.NewConnectionPool(appPoolName, *appPoolSize, *appIdleTimeout) appPool.Open(dbconnpool.DBConnectionCreator(app, appMysqlStats)) return &Mysqld{ config: config, dba: dba, allprivs: allprivs, dbApp: app, dbaPool: dbaPool, appPool: appPool, replParams: repl, dbaMysqlStats: dbaMysqlStats, allprivsMysqlStats: allprivsMysqlStats, tabletDir: path.Dir(config.DataDir), } }
func NewSchemaInfo(queryCacheSize int, reloadTime time.Duration, idleTimeout time.Duration) *SchemaInfo { si := &SchemaInfo{ queries: cache.NewLRUCache(int64(queryCacheSize)), rules: NewQueryRules(), connPool: dbconnpool.NewConnectionPool("", 2, idleTimeout), ticks: timer.NewTimer(reloadTime), } stats.Publish("QueryCacheLength", stats.IntFunc(si.queries.Length)) stats.Publish("QueryCacheSize", stats.IntFunc(si.queries.Size)) stats.Publish("QueryCacheCapacity", stats.IntFunc(si.queries.Capacity)) stats.Publish("QueryCacheOldest", stats.StringFunc(func() string { return fmt.Sprintf("%v", si.queries.Oldest()) })) stats.Publish("SchemaReloadTime", stats.DurationFunc(si.ticks.Interval)) _ = stats.NewMultiCountersFunc("TableStats", []string{"Table", "Stats"}, si.getTableStats) _ = stats.NewMultiCountersFunc("TableInvalidations", []string{"Table"}, si.getTableInvalidations) _ = stats.NewMultiCountersFunc("QueryCounts", []string{"Table", "Plan"}, si.getQueryCount) _ = stats.NewMultiCountersFunc("QueryTimesNs", []string{"Table", "Plan"}, si.getQueryTime) _ = stats.NewMultiCountersFunc("QueryRowCounts", []string{"Table", "Plan"}, si.getQueryRowCount) _ = stats.NewMultiCountersFunc("QueryErrorCounts", []string{"Table", "Plan"}, si.getQueryErrorCount) http.Handle("/debug/query_plans", si) http.Handle("/debug/query_stats", si) http.Handle("/debug/table_stats", si) http.Handle("/debug/schema", si) return si }
// NewConnPool creates a new ConnPool. The name is used // to publish stats only. func NewConnPool( name string, capacity int, idleTimeout time.Duration, enablePublishStats bool, queryServiceStats *QueryServiceStats, checker MySQLChecker) *ConnPool { cp := &ConnPool{ capacity: capacity, idleTimeout: idleTimeout, dbaPool: dbconnpool.NewConnectionPool("", 1, idleTimeout), queryServiceStats: queryServiceStats, checker: checker, } if name == "" { return cp } if enablePublishStats { stats.Publish(name+"Capacity", stats.IntFunc(cp.Capacity)) stats.Publish(name+"Available", stats.IntFunc(cp.Available)) stats.Publish(name+"MaxCap", stats.IntFunc(cp.MaxCap)) stats.Publish(name+"WaitCount", stats.IntFunc(cp.WaitCount)) stats.Publish(name+"WaitTime", stats.DurationFunc(cp.WaitTime)) stats.Publish(name+"IdleTimeout", stats.DurationFunc(cp.IdleTimeout)) } return cp }
// NewMysqld creates a Mysqld object based on the provided configuration // and connection parameters. // dbaName and appName are the base for stats exports, use 'Dba' and 'App', except in tests func NewMysqld(dbaName, appName string, config *Mycnf, dba, app, repl *sqldb.ConnParams) *Mysqld { if *dba == dbconfigs.DefaultDBConfigs.Dba { dba.UnixSocket = config.SocketFile } // create and open the connection pool for dba access dbaMysqlStatsName := "" dbaPoolName := "" if dbaName != "" { dbaMysqlStatsName = "Mysql" + dbaName dbaPoolName = dbaName + "ConnPool" } dbaMysqlStats := stats.NewTimings(dbaMysqlStatsName) dbaPool := dbconnpool.NewConnectionPool(dbaPoolName, *dbaPoolSize, *dbaIdleTimeout) dbaPool.Open(dbconnpool.DBConnectionCreator(dba, dbaMysqlStats)) // create and open the connection pool for app access appMysqlStatsName := "" appPoolName := "" if appName != "" { appMysqlStatsName = "Mysql" + appName appPoolName = appName + "ConnPool" } appMysqlStats := stats.NewTimings(appMysqlStatsName) appPool := dbconnpool.NewConnectionPool(appPoolName, *appPoolSize, *appIdleTimeout) appPool.Open(dbconnpool.DBConnectionCreator(app, appMysqlStats)) return &Mysqld{ config: config, dba: dba, dbApp: app, dbaPool: dbaPool, appPool: appPool, replParams: repl, dbaMysqlStats: dbaMysqlStats, TabletDir: TabletDir(config.ServerID), SnapshotDir: SnapshotDir(config.ServerID), } }
func NewTxPool(name string, capacity int, timeout, poolTimeout, idleTimeout time.Duration) *TxPool { axp := &TxPool{ pool: dbconnpool.NewConnectionPool(name, capacity, idleTimeout), activePool: pools.NewNumbered(), lastId: sync2.AtomicInt64(time.Now().UnixNano()), timeout: sync2.AtomicDuration(timeout), poolTimeout: sync2.AtomicDuration(poolTimeout), ticks: timer.NewTimer(timeout / 10), txStats: stats.NewTimings("Transactions"), } // Careful: pool also exports name+"xxx" vars, // but we know it doesn't export Timeout. stats.Publish(name+"Timeout", stats.DurationFunc(axp.timeout.Get)) stats.Publish(name+"PoolTimeout", stats.DurationFunc(axp.poolTimeout.Get)) return axp }
// NewMysqld creates a Mysqld object based on the provided configuration // and connection parameters. // name is the base for stats exports, use 'Dba', except in tests func NewMysqld(name string, config *Mycnf, dba, repl *mysql.ConnectionParams) *Mysqld { if *dba == dbconfigs.DefaultDBConfigs.Dba { dba.UnixSocket = config.SocketFile } // create and open the connection pool for dba access mysqlStats := stats.NewTimings("Mysql" + name) dbaPool := dbconnpool.NewConnectionPool(name+"ConnPool", *dbaPoolSize, *dbaIdleTimeout) dbaPool.Open(dbconnpool.DBConnectionCreator(dba, mysqlStats)) return &Mysqld{ config: config, dba: dba, dbaPool: dbaPool, replParams: repl, TabletDir: TabletDir(config.ServerId), SnapshotDir: SnapshotDir(config.ServerId), } }
// NewConnectionKiller creates a new ConnectionKiller func NewConnectionKiller(poolSize int, idleTimeout time.Duration) *ConnectionKiller { return &ConnectionKiller{ connPool: dbconnpool.NewConnectionPool("ConnKiller", poolSize, idleTimeout), } }