Skip to content

Instantly share code, notes, and snippets.

@abg
Created February 15, 2019 15:40
Show Gist options
  • Save abg/38bf98eacab751dce48ba1cd527cbdcf to your computer and use it in GitHub Desktop.
Save abg/38bf98eacab751dce48ba1cd527cbdcf to your computer and use it in GitHub Desktop.
Simple Test Harness to time querying the read_only status on a MySQL instance via various implementations
package main
import (
"database/sql"
"flag"
"log"
"os"
"time"
_ "github.com/go-sql-driver/mysql"
)
type PollFunc func(db *sql.DB) error
func showLikeReadOnly(db *sql.DB) error {
var (
sql = `SHOW GLOBAL VARIABLES LIKE 'read_only'`
unused string
readOnly string
)
return db.QueryRow(sql).Scan(&unused, &readOnly)
}
func showWhereReadOnly(db *sql.DB) error {
var (
sql = `SHOW GLOBAL VARIABLES WHERE Variable_name = 'read_only'`
unused string
readOnly string
)
return db.QueryRow(sql).Scan(&unused, &readOnly)
}
func selectReadOnly(db *sql.DB) error {
var (
sql = `SELECT @@read_only`
readOnly bool
)
return db.QueryRow(sql).Scan(&readOnly)
}
func selectPSReadOnly(db *sql.DB) error {
var (
sql = `SELECT VARIABLE_VALUE = 'ON' FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'read_only'`
readOnly bool
)
return db.QueryRow(sql).Scan(&readOnly)
}
func main() {
var (
implementation string
dsn string
interval time.Duration
maxTime time.Duration
)
flag.StringVar(&dsn, "dsn", "root@/", "Data source name (default: root@/)")
flag.StringVar(&implementation, "i", "show_var_like", "Implementation to run: show_var_like, show_var_where, select_var, select_ps")
flag.DurationVar(&interval, "I", time.Second, "Interval to run at (default: 1s)")
flag.DurationVar(&maxTime, "time", 5*time.Minute, "How long to run before stopping (default: 5m)")
flag.Parse()
var pollFunc PollFunc
var implNote string
switch implementation {
case "show_var_like":
pollFunc = showLikeReadOnly
implNote = "SHOW VARIABLES LIKE 'read_only'"
case "show_var_where":
pollFunc = showWhereReadOnly
implNote = "SHOW VARIABLES WHERE Variable_name = 'read_only'"
case "select_var":
pollFunc = selectReadOnly
implNote = "SELECT @@read_only"
case "select_ps":
pollFunc = selectPSReadOnly
implNote = "SELECT VARIABLE_NAME FROM performance_schema.global_variable WHERE Variable_name = 'read_only'"
default:
log.Fatal("Invalid implementation %v", implementation)
}
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
}
ticker := time.NewTicker(interval)
timer := time.NewTimer(maxTime)
for {
select {
case <-timer.C:
log.Println("Times up. Exiting")
os.Exit(0)
case <-ticker.C:
start := time.Now()
if err := pollFunc(db); err != nil {
log.Printf(`%s: %v (error: %v)`, implNote, time.Since(start).Seconds(), err)
} else {
log.Printf(`%s: %v`, implNote, time.Since(start).Seconds())
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment