如何从Go/MySQL中记录所有传出的SQL语句?

San*_*uja 7 mysql go sqlx

我正在使用带有sqlx的非框架Go堆栈,以及用于Web项目的MySQL.

我想记录所有传出的SQL语句以进行调试.是否有可能做到这一点?希望得到这样的输出(从Rails项目复制):

  User Load (94.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`login` = 'bondnewyork' LIMIT 1
  User Load (16.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`login` = 'mkovarik' LIMIT 1
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`login` = 'mkovarik' LIMIT 1
  User Load (0.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
  User Load (0.4ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
Run Code Online (Sandbox Code Playgroud)

Sir*_*ius 9

sqlx以以下接口的形式有一个非常有趣的抽象:

它们在整个库中用作表示将字符串用作SQL查询的功能的接口.

例如:

db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
if err != nil {
    log.Fatalln(err)
}

// exec the schema or fail; multi-statement Exec behavior varies between
// database drivers;  pq will exec them all, sqlite3 won't, ymmv
db.MustExec("CREATE TABLE person (first_name text)")
Run Code Online (Sandbox Code Playgroud)

最后一行实际上相当于:

sqlx.MustExec(db, "CREATE TABLE person (first_name text)")
Run Code Online (Sandbox Code Playgroud)

在哪里db用作Execer.

同样,这:

people := []Person{}
db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
Run Code Online (Sandbox Code Playgroud)

相当于:

sqlx.Select(db, &people, "SELECT * FROM person ORDER BY first_name ASC")
Run Code Online (Sandbox Code Playgroud)

在哪里db用作Queryer.

因此,如果您不想DB直接使用该类型,而是使用库的基础自由函数,则可以使用以下结构将您的db对象包装到执行日志记录的对象中:

type QueryLogger struct {
    queryer sqlx.Queryer
    logger  *log.Logger
}

func (p *QueryLogger) Query(query string, args ...interface{}) (*sql.Rows, error) {
    p.logger.Print(query, args...)
    return p.queryer.Query(query, args...)
}

func (p *QueryLogger) Queryx(query string, args ...interface{}) (*Rows, error) {
    p.logger.Print(query, args...)
    return p.queryer.Queryx(query, args...)
}

func (p *QueryLogger) QueryRowx(query string, args ...interface{}) *Row {
    p.logger.Print(query, args...)
    return p.queryer.QueryRowx(query, args...)
}
Run Code Online (Sandbox Code Playgroud)

当连接到您的数据库时:

db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
if err != nil {
    log.Fatalln(err)
}

ql := &QueryLogger{db, yourLogger}

sqlx.Select(ql, &people, "SELECT * FROM person ORDER BY first_name ASC")
Run Code Online (Sandbox Code Playgroud)

当然这仅在使用sqlx库的自由函数时才有效,因此如果您的代码使用sqlx.DB类型进行大量调用,这可能不够方便.