©
This document uses PHP Chinese website manual Release
SQL 优化器可以强行指定连接池中特定的链接。可以给定插件一个优化器去使用特定的服务器连接, 这样可以解决由于链接切换引起的链接状态变化问题。
SQL hints 是基于 SQL 语句的。因为 SQL 注释会被 SQL 执行器忽略, 他并不会妨碍 MySQL 服务器、MySQL proxy 或者任何防火墙的工作。
插件支持 SQL hints, MYSQLND_MS_MASTER_SWITCH
hints
可以指定语句在 master 上运行, MYSQLND_MS_SLAVE_SWITCH
可以指定在 slave 上运行, MYSQLND_MS_LAST_USED_SWITCH
可以指定语句在上一条语句执行的 slave 上运行。
插件会扫描语句的内容,查询是否有 SQL hints。他只能在语句的开头被识别。
Example #1 配置一个 master 和一个 slave 的插件
{ "myapp": { "master": { "master_0": { "host": "localhost", "socket": "\/tmp\/mysql.sock" } }, "slave": { "slave_0": { "host": "192.168.2.27", "port": "3306" } } } }
Example #2 SQL hints 禁止连接切换
<?php
$mysqli = new mysqli ( "myapp" , "username" , "password" , "database" );
if ( mysqli_connect_errno ())
die( sprintf ( "[%d] %s\n" , mysqli_connect_errno (), mysqli_connect_error ()));
if (! $mysqli -> query ( "SET @myrole='master'" )) {
printf ( "[%d] %s\n" , $mysqli -> errno , $mysqli -> error );
}
if (!( $res = $mysqli -> query ( sprintf ( "SELECT @myrole AS _role" , MYSQLND_MS_LAST_USED_SWITCH )))) {
printf ( "[%d] %s\n" , $mysqli -> errno , $mysqli -> error );
} else {
$row = $res -> fetch_assoc ();
$res -> close ();
printf ( "@myrole = '%s'\n" , $row [ '_role' ]);
}
$mysqli -> close ();
?>
以上例程会输出:
@myrole = 'master'
上面的范例使用 MYSQLND_MS_LASTER_USED_SWITCH
来防止在 master
和 slave 之间进行切换,即使运行了 SELECT 开头的语句。
SQL hints 也可以用于在 master 上运行 SELECT 语句。 这经常发生于 slave 中的数据落后于 master,但是希望获取当前数据的时候。
在 1.2.0 版本中,引入了服务级别的概念,用于处理即时数据获取的问题。 使用服务级别,可以降低对这个问题的关注,替代 SQL hints 的使用。 可以在服务级别和一致性的章节中找到更多的说明。
Example #3 与同步延迟斗争
<?php
$mysqli = new mysqli ( "myapp" , "username" , "password" , "database" );
if (! $mysqli )
die( sprintf ( "[%d] %s\n" , mysqli_connect_errno (), mysqli_connect_error ()));
if (! $mysqli -> query ( sprintf ( "SELECT critical_data FROM important_table" , MYSQLND_MS_MASTER_SWITCH ))) {
printf ( "[%d] %s\n" , $mysqli -> errno , $mysqli -> error );
}
?>
在使用中,slave 中应该有同样的表单。当没有给定 SQL hints 的时候,插件在发送
CREATE INSERT 语句到 master 服务器。
可以通过设定 MYSQLND_MS_SLAVE_SWITCH
来让这些语句在
slave 中运行。例如建立一个临时表单:
Example #4 Table creation on a slave
<?php
$mysqli = new mysqli ( "myapp" , "username" , "password" , "database" );
if (! $mysqli )
die( sprintf ( "[%d] %s\n" , mysqli_connect_errno (), mysqli_connect_error ()));
if (! $mysqli -> query ( sprintf ( "CREATE TABLE slave_reporting(id INT)" , MYSQLND_MS_SLAVE_SWITCH ))) {
printf ( "[%d] %s\n" , $mysqli -> errno , $mysqli -> error );
}
if (! $mysqli -> query ( sprintf ( "INSERT INTO slave_reporting(id) VALUES (1), (2), (3)" , MYSQLND_MS_LAST_USED_SWITCH ))) {
printf ( "[%d] %s\n" , $mysqli -> errno , $mysqli -> error );
}
if ( $res = $mysqli -> query ( sprintf ( "SELECT COUNT(*) AS _num FROM slave_reporting" , MYSQLND_MS_LAST_USED_SWITCH ))) {
$row = $res -> fetch_assoc ();
$res -> close ();
printf ( "There are %d rows in the table 'slave_reporting'" , $row [ '_num' ]);
} else {
printf ( "[%d] %s\n" , $mysqli -> errno , $mysqli -> error );
}
$mysqli -> close ();
?>
SQL hint MYSQLND_MS_LAST_USED
禁止切换连接,
他将使用上一次使用的链接。