如何将查询记录到数据库驱动程序中?

huangapple go评论125阅读模式
英文:

How to log queries to database drivers?

问题

我正在尝试用Go语言编写一个简单的数据库应用程序,它可以访问多个数据服务器,包括MySQL、MSSQL和SqlLite3。我正在使用"database/sql"包来访问它们。

  1. db, err := sql.Open(driver, dataSourceName)
  2. result, err := db.Exec(
  3. "INSERT INTO users (name, age) VALUES (?, ?)",
  4. "gopher",
  5. 27,
  6. )

我需要将SQL查询记录到各个服务器上以进行调试和审计。我该如何实现这个功能?

英文:

I am trying to write a simple Database application in go which access multiple data servers, some MySQL, MSSQL and SqlLite3.
I am using the "database/sql" package to access them.

  1. db, err := sql.Open(driver, dataSourceName)
  2. result, err := db.Exec(
  3. "INSERT INTO users (name, age) VALUES (?, ?)",
  4. "gopher",
  5. 27,
  6. )

I need to log the SQL queries to the individual servers for debugging and auditing.
How can I achieve that?

答案1

得分: 1

假设您不想使用服务器的日志记录功能,显而易见的解决方案是将所有查询记录下来。

  1. db, err := sql.Open(driver, dataSourceName)
  2. log.Println(dataSourceName, "INSERT INTO users (name, age) VALUES (?, ?)", "gopher", 27)
  3. result, err := db.Exec(
  4. "INSERT INTO users (name, age) VALUES (?, ?)",
  5. "gopher",
  6. 27,
  7. )

这是您问题的基本解决方案。您可以通过以下多种方式进行改进:

  • 为您的查询创建一个专门的log.Logger,以便将其定向到特定的输出目标。
  • 在一个特殊的结构中包装上述的log.Loggersql.DB对象,以在执行查询时记录它们。

以下是一个简单的示例结构:

  1. type DB struct {
  2. db *sql.DB
  3. dsn string
  4. log *log.Logger
  5. }
  6. func NewDB(driver, dsn string, log *log.Logger) (*DB, error) {
  7. db, err := sql.Open(driver, dsn)
  8. if err != nil {
  9. return nil, err
  10. }
  11. return &DB{
  12. db: db,
  13. dsn: dsn,
  14. log: log,
  15. }, nil
  16. }
  17. func (d DB) Exec(query string, args ...interface{}) (sql.Result, error) {
  18. d.log.Println(d.dsn, query, args)
  19. return d.db.Exec(query, args...)
  20. }

下面是如何使用它的示例:

  1. l := log.New(os.Stdout, "[sql]", log.LstdFlags)
  2. db, _ := NewDB(driver, dataSourceName, l)
  3. result, _ := db.Exec(
  4. "INSERT INTO users (name, age) VALUES (?, ?)",
  5. "gopher",
  6. 27,
  7. )

显然,您可以通过添加错误报告、查询持续时间等来进一步完善这个设计。

英文:

Assuming that you don't want to use the servers logging facilities, the obvious solution would be to simply log all queries as they are made.

  1. db, err := sql.Open(driver, dataSourceName)
  2. log.Println(dataSourceName, "INSERT INTO users (name, age) VALUES (?, ?)", "gopher", 27)
  3. result, err := db.Exec(
  4. "INSERT INTO users (name, age) VALUES (?, ?)",
  5. "gopher",
  6. 27,
  7. )

This is the basic solution for your problem. You can refine it in multiple ways:

  • Create a log.Logger exclusively for your queries, so you can direct it to a particular output destination
  • Wrap the said log.Logger and the sql.DB objects in a special struct that will log queries as they are done

Here is a rough example of the said struct:

  1. type DB struct {
  2. db *sql.DB
  3. dsn string
  4. log *log.Logger
  5. }
  6. func NewDB(driver, dsn string, log *log.Logger) (*DB, error) {
  7. db, err := sql.Open(driver, dsn)
  8. if err != nil {
  9. return nil, err
  10. }
  11. return &DB {
  12. db: db,
  13. dsn: dsn,
  14. log: log,
  15. }
  16. }
  17. func (d DB) Exec(query string, args ...interface{}) (sql.Result, err) {
  18. d.log.Println(dsn, query, args)
  19. return d.db.Exec(query, args...)
  20. }

And how you would use it:

  1. l := log.New(os.Stdout, "[sql]", log.LstdFlags)
  2. db, _ := NewDB(driver, dataSourceName, l)
  3. result, _ := db.Exec(
  4. "INSERT INTO users (name, age) VALUES (?, ?)",
  5. "gopher",
  6. 27,
  7. )

Obviously, you can refined this design again, by adding error reporting, duration of the queries, etc.

答案2

得分: 0

现在有一种解决方案,可以在不使用添加日志的包装器的情况下解决这个问题。

sqldblogger 可以在不改变现有 sql.DB 代码的情况下实现这一点。

英文:

There is now a solution for that without having to wrap sql.DB with a wrapper that adds the logging.

sqldblogger facilitates this without needing to change existing sql.DB code.

huangapple
  • 本文由 发表于 2015年3月26日 11:15:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/29270501.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定