将读/写拆分与PHP mysqlnd_ms一起使用的问题

Max*_*Max 5 php mysql pdo split read-write

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

- 启用时从源代码编译PHPmysqlnd

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

$ sudo pecl install mysqlnd_ms
Run Code Online (Sandbox Code Playgroud)

- 修改PHP.ini(并在之后重新启动):

mysqlnd_ms.enable=1
mysqlnd_ms.disable_rw_split=0 ; for good measure
mysqlnd_ms.config_file=mysqlnd_ms_config.ini
Run Code Online (Sandbox Code Playgroud)

- mysqlnd_ms_config.ini使用以下内容创建(在官方文档中作为示例提供)

{
    "myapp": {
        "master": {
            "master_0": {
                "host": "127.0.0.1",
                "port": "3306"
            }
        },
        "slave": {
            "slave_0": {
                "host": "localhost",
                "socket": "\/var\/run\/mysqld\/mysqld.sock"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

根据文件:

该插件在配置的MySQL从服务器上执行只读语句,在MySQL主服务器上执行所有其他查询.如果语句以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";
Run Code Online (Sandbox Code Playgroud)

查询被正确执行但是它们都被发送到了slave(我知道这是因为如果我嗅到流量而$ tcpdump -ni any port 3306我看不到任何东西,而如果我进行手动查询3306就会显示出来tcpdump).

使用诸如之类的评论/*ms=slave*//*ms=master*/没有任何区别.该general_log它只表示没有可能混淆任何其他意见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  
Run Code Online (Sandbox Code Playgroud)

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

$pdo->getAttribute(PDO::ATTR_CLIENT_VERSION)给我正在使用"mysqlnd 5.0.10 - 20111026 - $Id: b0b3b15c693b7f6aeb3aa66b646fee339f175e39哪些节目mysqlnd.

为了使读/写拆分工作(我欢迎任何建议),我缺少什么?

更新:
我找到了比tcpdump更好的方法来检查read/writesplit是否正常工作:

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
)
Run Code Online (Sandbox Code Playgroud)

小智 6

请确保在尝试建立连接时引用定义服务器的PECL/mysqlnd_ms文档部分.您应该在您的示例中传递节名称 - "myapp" - 作为您要使用的PHP MySQL API的connect函数的主机.像这样的东西:

$pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
Run Code Online (Sandbox Code Playgroud)

或者,在您的情况下,例如:

$mysql = new PDO("mysql:host=myapp;dbname=$dbname", $user, $pass);
Run Code Online (Sandbox Code Playgroud)

不使用:

$mysql = new PDO("mysql:unix_socket=$socket;dbname=$dbname", $user, $pass);
Run Code Online (Sandbox Code Playgroud)

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