php-doc-en/reference/mysqlnd_ms/functions/mysqlnd-ms-set-user-pick-server.xml

248 lines
7.6 KiB
XML
Raw Normal View History

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xml:id="function.mysqlnd-ms-set-user-pick-server" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<refnamediv>
<refname>mysqlnd_ms_set_user_pick_server</refname>
<refpurpose>Sets a callback for user-defined read/write splitting</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<type>bool</type>
<methodname>mysqlnd_ms_set_user_pick_server</methodname>
<methodparam><type>string</type><parameter>function</parameter></methodparam>
</methodsynopsis>
<para>
Sets a callback for user-defined read/write splitting. The plugin will
call the callback only if <literal>pick[]=user</literal> is the default
rule for server picking in the relevant section of the plugins configuration
file.
</para>
<para>
The plugins built-in read/write query split mechanism decisions can be
overwritten in two ways. The easiest way is to prepend the query string
with the SQL hints <constant>MYSQLND_MS_MASTER_SWITCH</constant>,
<constant>MYSQLND_MS_SLAVE_SWITCH</constant> or
<constant>MYSQLND_MS_LAST_USED_SWITCH</constant>. Using SQL hints one can
control, for example, whether a query shall be send to the MySQL replication
master server or one of the slave servers. By help of SQL hints it is
not possible to pick a certain slave server for query execution.
</para>
<para>
Full control on server selection can be gained using a callback function.
Use of a callback is recommended to expert users only because the callback
has to cover all cases otherwise handled by the plugin.
</para>
<para>
The plugin will invoke the callback function for selecting a server from the
lists of configured master and slave servers. The callback function
inspects the query to run and picks a server for query execution by returning
the hosts URI, as found in the master and slave list.
</para>
<para>
If the lazy connections are enabled and the callback choses a slave server for
which no connection has been established so far and establishing the connection
to the slave fails, the plugin will return an error upon the next action
on the failed connection, for example, when running a query. It is the
responsibility of the application developer to handle the error. For example,
the application can re-run the query to trigger a new server selection and
callback invocation. If so, the callback must make sure to select
a different slave, or check slave availability, before returning to
the plugin to prevent an endless loop.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<variablelist>
<varlistentry>
<term><parameter>function</parameter></term>
<listitem>
<para>
The function to be called. Class methods may also be invoked
statically using this function by passing
<literal>array($classname, $methodname)</literal> to this parameter.
Additionally class methods of an object instance may be called by passing
<literal>array($objectinstance, $methodname)</literal> to this parameter.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
Host to run the query on. The host URI is to be taken from the
master and slave connection lists passed to the callback function.
If callback returns a value neither found in the master nor in the slave
connection lists the plugin will fallback to the second pick method configured
via the <literal>pick[]</literal> setting in the plugin configuration file.
If not second pick method is given, the plugin falls back to the build-in
default pick method for server selection.
</para>
</refsect1>
<refsect1>
&reftitle.notes;
<note>
<para>
<function>mysqlnd_ms_set_user_pick_server</function> is available
with PECL mysqlnd_ms &lt; 1.1.0. It has been replaced by the
<literal>user</literal> filter. Please, check the
<link linkend="mysqlnd-ms.changes_one_one">Change History</link>
for upgrade notes.
</para>
</note>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title><function>mysqlnd_ms_set_user_pick_server</function> example</title>
<programlisting role="ini">
<![CDATA[
[myapp]
master[] = localhost
slave[] = 192.168.2.27:3306
slave[] = 192.168.78.136:3306
pick[] = user
]]>
</programlisting>
<programlisting role="php">
<![CDATA[
<?php
function pick_server($connected, $query, $master, $slaves, $last_used)
{
static $slave_idx = 0;
static $num_slaves = NULL;
if (is_null($num_slaves))
$num_slaves = count($slaves);
/* default: fallback to the plugins build-in logic */
$ret = NULL;
printf("User has connected to '%s'...\n", $connected);
printf("... deciding where to run '%s'\n", $query);
$where = mysqlnd_ms_query_is_select($query);
switch ($where)
{
case MYSQLND_MS_QUERY_USE_MASTER:
printf("... using master\n");
$ret = $master[0];
break;
case MYSQLND_MS_QUERY_USE_SLAVE:
/* SELECT or SQL hint for using slave */
if (stristr($query, "FROM table_on_slave_a_only"))
{
/* a table which is only on the first configured slave */
printf("... access to table available only on slave A detected\n");
$ret = $slaves[0];
}
else
{
/* round robin */
printf("... some read-only query for a slave\n");
$ret = $slaves[$slave_idx++ % $num_slaves];
}
break;
case MYSQLND_MS_QUERY_LAST_USED:
printf("... using last used server\n");
$ret = $last_used;
break;
}
printf("... ret = '%s'\n", $ret);
return $ret;
}
mysqlnd_ms_set_user_pick_server("pick_server");
$mysqli = new mysqli("myapp", "root", "root", "test");
if (!($res = $mysqli->query("SELECT 1 FROM DUAL")))
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
else
$res->close();
if (!($res = $mysqli->query("SELECT 2 FROM DUAL")))
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
else
$res->close();
if (!($res = $mysqli->query("SELECT * FROM table_on_slave_a_only")))
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
else
$res->close();
$mysqli->close();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
User has connected to 'myapp'...
... deciding where to run 'SELECT 1 FROM DUAL'
... some read-only query for a slave
... ret = 'tcp://192.168.2.27:3306'
User has connected to 'myapp'...
... deciding where to run 'SELECT 2 FROM DUAL'
... some read-only query for a slave
... ret = 'tcp://192.168.78.136:3306'
User has connected to 'myapp'...
... deciding where to run 'SELECT * FROM table_on_slave_a_only'
... access to table available only on slave A detected
... ret = 'tcp://192.168.2.27:3306'
]]>
</screen>
</example>
</para>
</refsect1>
<refsect1 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member>
<function>mysqlnd_ms_query_is_select</function>
</member>
<member>
<link linkend="mysqlnd-ms.filter">Filter concept</link>
</member>
<member>
<link linkend="ini.mysqlnd-ms-plugin-config-v2.filter_user"><literal>user</literal></link> filter
</member>
</simplelist>
</para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->