【问题标题】:Issue getting the read/write split to work with PHP mysqlnd_ms让读/写拆分与 PHP mysqlnd_ms 一起使用的问题
【发布时间】:2012-11-18 18:19:53
【问题描述】:

我正在尝试设置 PHP mysqlnd_ms 扩展,但遇到了一些问题。到目前为止,这是我所做的:

-compiled PHP from source while enabling mysqlnd

-已安装mysqlnd_ms(如果我运行pecl info mysqlnd_ms,我会得到有关mysqlnd_ms 插件的信息):

$ sudo pecl install mysqlnd_ms

-修改PHP.ini(然后重新启动):

mysqlnd_ms.enable=1
mysqlnd_ms.disable_rw_split=0 ; for good measure
mysqlnd_ms.config_file=mysqlnd_ms_config.ini

-创建 mysqlnd_ms_config.ini 并包含以下内容 (which is given as example in the official doc)

{
    "myapp": {
        "master": {
            "master_0": {
                "host": "127.0.0.1",
                "port": "3306"
            }
        },
        "slave": {
            "slave_0": {
                "host": "localhost",
                "socket": "\/var\/run\/mysqld\/mysqld.sock"
            }
        }
    }
}

According to the documentation:

插件在配置的 MySQL 上执行只读语句 slaves,以及 MySQL master 上的所有其他查询。声明是 如果它们以 SELECT 开头,则视为只读,SQL 提示 /ms=slave/,或者如果选择了一个从属来运行前一个 查询,查询以 SQL 提示 /ms=last_used/ 开始。在所有 其他情况,查询将被发送到 MySQL 复制主服务器 服务器

所以此时我希望我的 SELECT 语句被发送到 slave 和其他语句(例如 UPDATE)被发送到 master

我写了一个小脚本来测试设置:

$socket = '/var/run/mysqld/mysqld.sock';
$dbname = 'mysqlnsmstest';
$user = 'root';
$pass = 'root';

$mysql = new PDO("mysql:unix_socket=$socket;dbname=$dbname", $user, $pass);

$result = $mysql->query('SELECT * FROM mytable');
foreach($result as $row) {
    print_r($row);
}

$count = $mysql->exec("UPDATE mytable SET field='test' WHERE id=2");
echo "Nb rows affected: $count\n";

查询已正确执行但是它们都被发送到slave(我知道这一点,因为如果我用$ tcpdump -ni any port 3306 嗅探流量,我看不到任何东西,而如果我在3306 上进行手动查询,它们确实会出现在tcpdump 中)。

使用 /*ms=slave*//*ms=master*/ 等 cmets 没有区别。 general_log 确实表明没有任何其他 cmets 可以混淆 mysqlns_ms

121118 19:14:40    36 Connect   root@localhost on mysqlnsmstest
           36 Query /*ms=slave*/SELECT * FROM mytable
           36 Query /*ms=master*/UPDATE mytable SET field='test' WHERE id=2
           36 Quit  

我尝试使用非环回 IP(例如我的 10.0.0.56 本地)通过网络“强制”连接,但没有任何区别。

$pdo->getAttribute(PDO::ATTR_CLIENT_VERSION) 给了我"mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39,这表明mysqlnd 正在被使用。

为了使读/写分离起作用,我缺少什么(欢迎提出任何建议)?

更新:
我找到了比 tcpdump 更好的方法来检查 read/write split 是否有效:

print_r(mysqlnd_ms_get_last_used_connection($pdo));
Array
(
    [scheme] => unix:///var/run/mysqld/mysqld.sock
    [host_info] => Localhost via UNIX socket
    [host] => 
    [port] => 3306
    [socket_or_pipe] => /var/run/mysqld/mysqld.sock
    [thread_id] => 48
    [last_message] => Rows matched: 1  Changed: 0  Warnings: 0
    [errno] => 0
    [error] => 
    [sqlstate] => 00000
)

【问题讨论】:

    标签: php mysql pdo split read-write


    【解决方案1】:

    请确保在尝试建立连接时参考定义服务器的 PECL/mysqlnd_ms 文档部分。您应该将部分名称(在您的示例中为“myapp”)作为主机传递给您要使用的 PHP MySQL API 的连接函数。像这样的:

    $pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
    

    或者,在你的情况下是这样的:

    $mysql = new PDO("mysql:host=myapp;dbname=$dbname", $user, $pass);
    

    不要使用:

    $mysql = new PDO("mysql:unix_socket=$socket;dbname=$dbname", $user, $pass);
    

    这将连接到正在侦听套接字 $socket 的服务器。

    【讨论】:

    • PDO 对此不满意,因为它试图将 myapp 解析为主机名 (PDO::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known)。 ini_get 确实给了我上面提到的设置及其正确的值,包括包含 myapp 键的配置文件,如上所示。
    • 它确实有效 :) 我的配置文件有问题 (Unknown: (mysqlnd_ms) Failed to open server list config file [mysqlnd_ms_config.ini] in Unknown on line 0)。已修复,现在可以正常工作了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 2023-03-15
    • 2011-09-04
    • 2015-03-19
    • 2021-03-16
    • 2013-12-28
    • 1970-01-01
    相关资源
    最近更新 更多