1

我们正在尝试使用 GO 创建一个连接到 ProxySQL 的 Web 应用程序,该应用程序将根据 ProxySQL 中设置的 MySQL 查询规则依次连接到各种 MySQL 数据库服务器。

我们可以通过 linux 中的命令行连接到 ProxySQL,一切都按预期工作:

    use database1;
    select id from users where user_id=1;
    use database2;
    select id from posts where user_id=1;

上述数据库位于物理上不同的服务器上。ProxySQL 中的规则知道如何路由它们。

连接到 ProxySQL 时,规则工作正常,我们连接到正确的数据库服务器,请求按预期处理。

当我们用 GO 和事务尝试相同的事情时,我们无法切换数据库,因为它返回数据库不存在。

数据库存在于后端服务器上,ProxySQL 会将流量定向到后端服务器。

无论出于何种原因,它都可以在命令行上运行,但不能在 GO 中运行

如果我们使用 GO 连接并在连接上指定数据库,然后断开连接并使用新的数据库连接重新连接,我们可以使其工作。

我们正在尝试使用连接池,这样我们就不会浪费时间打开和关闭连接。

    //open the connection to ProxySQL

    db, err = sql.Open("mysql", "user:password@tcp(x.x.x.x:6033)/")

    //The above only allows us to stay on the default database for the user

    //in order to access each of the databases we would need to open a
    //connection to database1 then open another connection to database2
    //which defeats the whole purpose of connection pooling.

    db, err = sql.Open("mysql", "user:password@tcp(x.x.x.x:6033)/database1")
    ... do something...

    db, err = sql.Open("mysql", "user:password@tcp(x.x.x.x:6033)/database2")
    ... do something ...



    //code below is an example of what is not working but works from
    //command line in linux. Results are not processed below because we
    //cannot get past the first error of no database
    tx, err := db.Begin()
    res, err := tx.Exec("use database1")
    res, err = tx.Exec("select id from users where user_id=1;")
    res, err = tx.Exec("use database2")
    res, err = tx.Exec("select id from posts where user_id=1;")
    tx.Commit()

ProxySQL 知道如何正确路由,但我们似乎无法让函数在 GOLANG 中正常工作

4

2 回答 2

0

由于我不完全了解 ProxySQL 如何禁用多路复用以及与 USE 语句的相互作用,事务在这里似乎不能很好地工作。

我使用 Connections 成功确保语句在正确的数据库上执行。

conn, err := db.Conn(ctx)
conn.Exec("use database1")
conn.Exec("select id from users where user_id=1;")
conn.Exec("use database2")
conn.Exec("select id from posts where user_id=1;")
conn.Close()
于 2020-10-23T17:56:25.070 回答
0

我从 golang 官方文档https://golang.google.cn/pkg/database/sql/#Tx.Exec中找到了一些信息:

func (*Tx) Exec
func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)
Exec executes a query that doesn't return rows. For example: an INSERT and UPDATE.

也许你应该使用另一种方法func (db *DB) Prepare(query string) (*Stmt, error),祝你好运。

于 2019-10-01T16:57:37.427 回答