mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-25 05:18:56 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@327386 c90b9560-bf6c-de11-be94-00142212c4b1
2794 lines
101 KiB
XML
Executable file
2794 lines
101 KiB
XML
Executable file
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
|
|
<chapter xml:id="mysqlnd-ms.setup" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
&reftitle.setup;
|
|
|
|
<section xml:id="mysqlnd-ms.requirements">
|
|
&reftitle.required;
|
|
<para>
|
|
<literal>PHP 5.3.6</literal> or newer.
|
|
Some advanced functionality requires <literal>PHP 5.4.0</literal> or newer.
|
|
</para>
|
|
<para>
|
|
The <literal>mysqlnd_ms</literal> replication and load balancing
|
|
plugin supports all PHP applications and all available PHP MySQL extensions
|
|
(<link linkend="ref.mysqli">mysqli</link>,
|
|
<link linkend="ref.mysql">mysql</link>,
|
|
<link linkend="ref.pdo-mysql">PDO_MYSQL</link>).
|
|
The PHP MySQL extension must be configured to use
|
|
<link linkend="book.mysqlnd">mysqlnd</link> in order to be able
|
|
to use the <literal>mysqlnd_ms</literal> plugin for
|
|
<link linkend="book.mysqlnd">mysqlnd</link>.
|
|
</para>
|
|
</section>
|
|
|
|
&reference.mysqlnd-ms.configure;
|
|
&reference.mysqlnd-ms.ini;
|
|
|
|
<section xml:id="mysqlnd-ms.plugin-ini-json">
|
|
<title xmlns="http://docbook.org/ns/docbook">Plugin configuration file (>=1.1.x)</title>
|
|
<note>
|
|
<title>Changelog: Feature was added in PECL/mysqlnd_ms 1.1.0-beta</title>
|
|
<para>
|
|
The below description applies to PECL/mysqlnd_ms >= 1.1.0-beta.
|
|
It is not valid for prior versions.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
The plugin uses its own configuration file. The configuration file
|
|
holds information about the MySQL replication master server,
|
|
the MySQL replication slave servers, the server pick (load balancing) policy,
|
|
the failover strategy, and the use of lazy connections.
|
|
</para>
|
|
<para>
|
|
The plugin loads its configuration file at the beginning of a web request.
|
|
It is then cached in memory and used for the duration of the web request.
|
|
This way, there is no need to restart PHP after deploying the configuration
|
|
file. Configuration file changes will become active almost instantly.
|
|
</para>
|
|
<para>
|
|
The PHP configuration directive
|
|
<link linkend="ini.mysqlnd-ms.ini-file"><literal>mysqlnd_ms.ini_file</literal></link>
|
|
is used to set the plugins configuration file. Please note, that
|
|
the PHP configuration directive may not be evaluated for every web request.
|
|
Therefore, changing the plugins configuration file name or location may
|
|
require a PHP restart. However, no restart is required to read changes if
|
|
an already existing plugin configuration file is updated.
|
|
</para>
|
|
<para>
|
|
Using and parsing <acronym>JSON</acronym> is efficient, and using <acronym>JSON</acronym>
|
|
makes it easier to express hierarchical data structures than the standard
|
|
<filename>php.ini</filename> format.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Converting a PHP array (hash) into JSON format</title>
|
|
<para>
|
|
Or alternatively, a developer may be more familiar with the PHP <type>array</type>
|
|
syntax, and prefer it. This example demonstrates how a developer might convert a
|
|
PHP array to <acronym>JSON</acronym>.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$config = array(
|
|
"myapp" => array(
|
|
"master" => array(
|
|
"master_0" => array(
|
|
"host" => "localhost",
|
|
"socket" => "/tmp/mysql.sock",
|
|
),
|
|
),
|
|
"slave" => array(),
|
|
),
|
|
);
|
|
|
|
file_put_contents("mysqlnd_ms.ini", json_encode($config, JSON_PRETTY_PRINT));
|
|
printf("mysqlnd_ms.ini file created...\n");
|
|
printf("Dumping file contents...\n");
|
|
printf("%s\n", str_repeat("-", 80));
|
|
echo file_get_contents("mysqlnd_ms.ini");
|
|
printf("\n%s\n", str_repeat("-", 80));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
mysqlnd_ms.ini file created...
|
|
Dumping file contents...
|
|
--------------------------------------------------------------------------------
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost",
|
|
"socket": "\/tmp\/mysql.sock"
|
|
}
|
|
},
|
|
"slave": [
|
|
|
|
]
|
|
}
|
|
}
|
|
--------------------------------------------------------------------------------
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
A plugin configuration file consists of one or more sections. Sections
|
|
are represented by the top-level object properties of the
|
|
object encoded in the <acronym>JSON</acronym> file. Sections could also
|
|
be called <emphasis>configuration names</emphasis>.
|
|
</para>
|
|
<para>
|
|
Applications reference sections by their name. Applications use section names
|
|
as the host (server) parameter to the various connect methods of the
|
|
<link linkend="ref.mysqli">mysqli</link>,
|
|
<link linkend="ref.mysql">mysql</link> and
|
|
<link linkend="ref.pdo-mysql">PDO_MYSQL</link> extensions. Upon connect,
|
|
the <link linkend="book.mysqlnd">mysqlnd</link> plugin compares the hostname
|
|
with all of the section names from the plugin configuration file. If the hostname and
|
|
section name match, then the plugin will load the settings for that section.
|
|
</para>
|
|
<para xml:id="mysqlnd-ms.plugin-ini-json.using-section">
|
|
<example>
|
|
<title>Using section names example</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.2.27"
|
|
},
|
|
"slave_1": {
|
|
"host": "192.168.2.27",
|
|
"port": 3306
|
|
}
|
|
}
|
|
},
|
|
"localhost": {
|
|
"master": [
|
|
{
|
|
"host": "localhost",
|
|
"socket": "\/path\/to\/mysql.sock"
|
|
}
|
|
],
|
|
"slave": [
|
|
{
|
|
"host": "192.168.3.24",
|
|
"port": "3305"
|
|
},
|
|
{
|
|
"host": "192.168.3.65",
|
|
"port": "3309"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/* All of the following connections will be load balanced */
|
|
$mysqli = new mysqli("myapp", "username", "password", "database");
|
|
$pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
|
|
$mysql = mysql_connect("myapp", "username", "password");
|
|
|
|
$mysqli = new mysqli("localhost", "username", "password", "database");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Section names are strings. It is valid to use a section name such as
|
|
<literal>192.168.2.1</literal>, <literal>127.0.0.1</literal> or
|
|
<literal>localhost</literal>. If, for example, an application
|
|
connects to <literal>localhost</literal> and a plugin
|
|
configuration section <literal>localhost</literal> exists, the
|
|
semantics of the connect operation are changed. The application will
|
|
no longer only use the MySQL server running on the host
|
|
<literal>localhost</literal>, but the plugin will start to load balance
|
|
MySQL queries following the rules from the <literal>localhost</literal>
|
|
configuration section. This way you can load balance queries from
|
|
an application without changing the applications source code.
|
|
Please keep in mind, that such a configuration may not contribute
|
|
to overall readability of your applications source code. Using section names
|
|
that can be mixed up with host names should be seen as a last resort.
|
|
</para>
|
|
<para xml:id="mysqlnd-ms.plugin-ini-json.server-list-syntax">
|
|
Each configuration section contains, at a minimum, a list of master servers
|
|
and a list of slave servers. The master list is configured with the keyword
|
|
<literal>master</literal>, while the slave list is configured with the
|
|
<literal>slave</literal> keyword. Failing to provide a slave list will result
|
|
in a fatal <constant>E_ERROR</constant> level error, although a slave list
|
|
may be empty. It is possible to allow no slaves. However, this is only recommended
|
|
with synchronous clusters, please see also
|
|
<link linkend="mysqlnd-ms.supportedclusters">supported clusters</link>.
|
|
The main part of the documentation focusses on the use
|
|
of asynchronous MySQL replication clusters.
|
|
</para>
|
|
<para>
|
|
The master and slave server lists can be optionally indexed by symbolic
|
|
names for the servers they describe. Alternatively, an array of descriptions
|
|
for slave and master servers may be used.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>List of anonymous slaves</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
"slave": [
|
|
{
|
|
"host": "192.168.3.24",
|
|
"port": "3305"
|
|
},
|
|
{
|
|
"host": "192.168.3.65",
|
|
"port": "3309"
|
|
}
|
|
]
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
An anonymous server list is encoded by the <literal>JSON array</literal> type.
|
|
Optionally, symbolic names may be used for indexing the slave or master servers
|
|
of a server list, and done so using the <literal>JSON object</literal> type.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Master list using symbolic names</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
It is recommended to index the server lists with symbolic server names.
|
|
The alias names will be shown in error messages.
|
|
</para>
|
|
<para>
|
|
The order of servers is preserved and taken into account by mysqlnd_ms.
|
|
If, for example, you configure round robin load balancing strategy, the
|
|
first <literal>SELECT</literal> statement will be executed on the
|
|
slave that appears first in the slave server list.
|
|
</para>
|
|
<para>
|
|
A configured server can be described with the <literal>host</literal>,
|
|
<literal>port</literal>, <literal>socket</literal>, <literal>db</literal>,
|
|
<literal>user</literal>, <literal>password</literal> and <literal>connect_flags</literal>.
|
|
It is mandatory to set the database server host using the <literal>host</literal>
|
|
keyword. All other settings are optional.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Keywords to configure a server</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "db_server_host",
|
|
"port": "db_server_port",
|
|
"socket": "db_server_socket",
|
|
"db": "database_resp_schema",
|
|
"user": "user",
|
|
"password": "password",
|
|
"connect_flags": 0
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "db_server_host",
|
|
"port": "db_server_port",
|
|
"socket": "db_server_socket"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
If a setting is omitted, the plugin will use the value provided by the user
|
|
API call used to open a connection. Please, see the
|
|
<link linkend="mysqlnd-ms.plugin-ini-json.using-section">using section names example</link> above.
|
|
</para>
|
|
<para>
|
|
The configuration file format has been changed in version 1.1.0-beta to allow for
|
|
chained filters. Filters are responsible for filtering the configured list of
|
|
servers to identify a server for execution of a given statement.
|
|
Filters are configured with the <literal>filter</literal> keyword. Filters
|
|
are executed by mysqlnd_ms in the order of their appearance.
|
|
Defining filters is optional. A configuration section in the plugins
|
|
configuration file does not need to have a <literal>filters</literal> entry.
|
|
</para>
|
|
<para>
|
|
Filters replace the
|
|
<link linkend="ini.mysqlnd-ms-plugin-config.pick"><literal>pick[]</literal></link>
|
|
setting from prior versions. The new <literal>random</literal> and
|
|
<literal>roundrobin</literal> provide the same functionality.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>New <literal>roundrobin</literal> filter, old functionality</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
},
|
|
"slave_1": {
|
|
"host": "192.168.78.137",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": {
|
|
"roundrobin": [
|
|
|
|
]
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
The function
|
|
<function>mysqlnd_ms_set_user_pick_server</function>
|
|
has been removed. Setting a callback is now done with the <literal>user</literal>
|
|
filter. Some filters accept parameters. The <literal>user</literal> filter
|
|
requires and accepts a mandatory <literal>callback</literal> parameter
|
|
to set the callback previously set through the function <function>mysqlnd_ms_set_user_pick_server</function>.
|
|
<example>
|
|
<title>The <literal>user</literal> filter replaces <function>mysqlnd_ms_set_user_pick_server</function></title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
"filters": {
|
|
"user": {
|
|
"callback": "pick_server"
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Here is a short explanation of the configuration directives that can be used.
|
|
</para>
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.master">
|
|
<term>
|
|
<parameter>master</parameter>
|
|
<type>array or object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
List of MySQL replication master servers. The list of either
|
|
of the <literal>JSON type array</literal> to declare an anonymous list
|
|
of servers or of the <literal>JSON type object</literal>. Please,
|
|
see <link linkend="mysqlnd-ms.plugin-ini-json.server-list-syntax">above</link>
|
|
for examples.
|
|
</para>
|
|
<para>
|
|
Setting at least one master server is mandatory. The plugin will issue an
|
|
error of type <literal>E_ERROR</literal> if the user has failed to
|
|
provide a master server list for a configuration section.
|
|
The fatal error may read
|
|
<literal>(mysqlnd_ms) Section [master] doesn't exist for host
|
|
[name_of_a_config_section] in %s on line %d</literal>.
|
|
</para>
|
|
<para>
|
|
A server is described with
|
|
the <literal>host</literal>, <literal>port</literal>,
|
|
<literal>socket</literal>, <literal>db</literal>,
|
|
<literal>user</literal>, <literal>password</literal> and
|
|
<literal>connect_flags</literal>. It is mandatory to
|
|
provide at a value for <literal>host</literal>. If any of the
|
|
other values is not given, it will be taken from the user
|
|
API connect call, please, see also:
|
|
<link linkend="mysqlnd-ms.plugin-ini-json.using-section">using section names example</link>.
|
|
</para>
|
|
<para xml:id="mysqlnd-ms.plugin-ini-json.server-config-keywords">
|
|
Table of server configuration keywords.
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Keyword</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>host</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Database server host. This is a mandatory setting.
|
|
Failing to provide, will cause an error of type <literal>E_RECOVERABLE_ERROR</literal>
|
|
when the plugin tries to connect to the server. The error message may
|
|
read <literal>(mysqlnd_ms) Cannot find [host] in
|
|
[%s] section in config in %s on line %d</literal>.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>port</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Database server TCP/IP port.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>socket</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Database server Unix domain socket.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>db</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Database (schemata).
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>user</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
MySQL database user.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>password</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
MySQL database user password.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>connect_flags</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Connection flags.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
<para>
|
|
The plugin supports using only one master server. An experimental
|
|
setting exists to enable multi-master support. The details are
|
|
not documented. The setting is meant for development only.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.slave">
|
|
<term>
|
|
<parameter>slave</parameter>
|
|
<type>array or object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
List of one or more MySQL replication slave servers. The syntax is
|
|
identical to setting master servers, please, see
|
|
<link linkend="ini.mysqlnd-ms-plugin-config-v2.master"><literal>master</literal></link>
|
|
above for details.
|
|
</para>
|
|
<para>
|
|
The plugin supports using one or more slave servers.
|
|
</para>
|
|
<para>
|
|
Setting a list of slave servers is mandatory. The plugin will report
|
|
an error of the type <literal>E_ERROR</literal> if <literal>slave</literal>
|
|
is not given for a configuration section. The fatal error message may read
|
|
<literal>(mysqlnd_ms) Section [slave] doesn't exist for host [%s] in %s on line %d</literal>.
|
|
Note, that it is valid to use an empty slave server list.
|
|
The error has been introduced to prevent accidently setting no slaves by
|
|
forgetting about the <literal>slave</literal> setting.
|
|
A master-only setup is still possible using an empty slave server list.
|
|
</para>
|
|
<para>
|
|
If an empty slave list is configured and an attempt is made to
|
|
execute a statement on a slave the plugin may emit a warning like
|
|
<literal>mysqlnd_ms) Couldn't find the appropriate slave connection.
|
|
0 slaves to choose from.</literal> upon statement execution.
|
|
It is possible that another warning follows such as
|
|
<literal>(mysqlnd_ms) No connection selected by the last filter</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.gtid">
|
|
<term>
|
|
<parameter>global_transaction_id_injection</parameter>
|
|
<type>array or object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Global transaction identifier configuration related to both
|
|
the use of the server built-in global transaction ID feature and
|
|
the client-side emulation.
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Keyword</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>fetch_last_gtid</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SQL statement for accessing the latest global transaction identifier.
|
|
The SQL statement is run if the plugin needs to know the most recent
|
|
global transaction identifier. This can be the case, for example, when checking
|
|
MySQL Replication slave status.
|
|
Also used with <function>mysqlnd_ms_get_last_gtid</function>.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>check_for_gtid</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
SQL statement for checking if a replica has replicated
|
|
all transactions up to and including ones searched for. The
|
|
SQL statement is run when searching for replicas which can offer
|
|
a higher level of consistency than eventual consistency.
|
|
The statement must contain a placeholder <literal>#GTID</literal>
|
|
which is to be replaced with the global transaction identifier searched
|
|
for by the plugin. Please, check the
|
|
<link linkend="mysqlnd-ms.quickstart.gtid">quickstart</link> for examples.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>report_errors</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Whether to emit an error of type warning if an issue occurs while
|
|
executing any of the configured SQL statements.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>on_commit</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Client-side global transaction ID emulation only. SQL statement
|
|
to run when a transaction finished to update the global transaction
|
|
identifier sequence number on the master. Please, see the
|
|
<link linkend="mysqlnd-ms.quickstart.gtid">quickstart</link> for examples.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>wait_for_gtid_timeout</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Instructs the plugin to wait up to <literal>wait_for_gtid_timeout</literal>
|
|
seconds for a slave to catch up when searching for slaves that can
|
|
deliver session consistency. The setting limits the time spend for
|
|
polling the slave status. If polling the status takes very long, the total
|
|
clock time spend waiting may exceed <literal>wait_for_gtid_timeout</literal>.
|
|
The plugin calls <literal>sleep(1)</literal> to sleep one second between
|
|
each two polls.
|
|
</para>
|
|
<para>
|
|
The setting can be used both with the plugins client-side emulation
|
|
and the server-side global transaction identifier feature of MySQL 5.6.
|
|
</para>
|
|
<para>
|
|
Waiting for a slave to replicate a certain GTID needed for session
|
|
consistency also means throttling the client. By throttling the
|
|
client the write load on the master is reduced indirectly. A
|
|
primary copy based replication system, such as MySQL Replication,
|
|
is given more time to reach a consistent state. This can be desired,
|
|
for example, to increase the number of data copies for
|
|
high availability considerations or to prevent the master from being
|
|
overloaded.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.4.0.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filters">
|
|
<term>
|
|
<parameter>filters</parameter>
|
|
<type>object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
List of filters. A filter is responsible to filter the list of available
|
|
servers for executing a given statement. Filters can be chained.
|
|
The <literal>random</literal> and <literal>roundrobin</literal> filter
|
|
replace the
|
|
<link linkend="ini.mysqlnd-ms-plugin-config.pick"><literal>pick[]</literal></link>
|
|
directive used in prior version to select a load balancing policy.
|
|
The <literal>user</literal> filter replaces the
|
|
<function>mysqlnd_ms_set_user_pick_server</function> function.
|
|
</para>
|
|
<para>
|
|
Filters may accept parameters to refine their actions.
|
|
</para>
|
|
<para>
|
|
If no load balancing policy is set, the plugin will default to
|
|
<literal>random_once</literal>. The <literal>random_once</literal>
|
|
policy picks a random slave server when running the first read-only
|
|
statement. The slave server will be used for all read-only
|
|
statements until the PHP script execution ends. No load balancing
|
|
policy is set and thus, defaulting takes place,
|
|
if neither the <literal>random</literal> nor the
|
|
<literal>roundrobin</literal> are part of a configuration section.
|
|
</para>
|
|
<para>
|
|
If a filter chain is configured so that a filter which output no
|
|
more than once server is used as input for a filter which should be given
|
|
more than one server as input, the plugin may emit a warning upon
|
|
opening a connection. The warning may read: <literal>(mysqlnd_ms) Error while creating
|
|
filter '%s' . Non-multi filter '%s' already created.
|
|
Stopping in %s on line %d</literal>. Futhermore an error of
|
|
the error code <literal>2000</literal>, the sql state <literal>HY000</literal>
|
|
and an error message similar to the warning may be set on the connection
|
|
handle.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Invalid filter sequence</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": [
|
|
"roundrobin",
|
|
"random"
|
|
]
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$link = new mysqli("myapp", "root", "", "test");
|
|
printf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
|
|
$link->query("SELECT 1 FROM DUAL");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
PHP Warning: mysqli::mysqli(): (HY000/2000): (mysqlnd_ms) Error while creating filter 'random' . Non-multi filter 'roundrobin' already created. Stopping in filter_warning.php on line 1
|
|
[2000] (mysqlnd_ms) Error while creating filter 'random' . Non-multi filter 'roundrobin' already created. Stopping
|
|
PHP Warning: mysqli::query(): Couldn't fetch mysqli in filter_warning.php on line 3
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filter-random">
|
|
<term>
|
|
Filter: <parameter>random</parameter>
|
|
<type>object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The <literal>random</literal> filter features the random and random once
|
|
load balancing policies, set through the
|
|
<link linkend="ini.mysqlnd-ms-plugin-config.pick"><literal>pick[]</literal></link>
|
|
directive in older versions.
|
|
</para>
|
|
<para>
|
|
The random policy will pick a random server whenever
|
|
a read-only statement is to be executed. The random once strategy
|
|
picks a random slave server once and continues using the slave for the
|
|
rest of the PHP web request. Random once is a default,
|
|
if load balancing is not configured through a filter.
|
|
</para>
|
|
<para>
|
|
If the <literal>random</literal> filter is not given any arguments, it
|
|
stands for random load balancing policy.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Random load balancing with <literal>random</literal> filter</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
},
|
|
"slave_1": {
|
|
"host": "192.168.78.137",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": [
|
|
"random"
|
|
]
|
|
}
|
|
}
|
|
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Optionally, the <literal>sticky</literal> argument can be passed to the
|
|
filter. If the parameter <literal>sticky</literal> is set to the string
|
|
<literal>1</literal>, the filter follows the random once
|
|
load balancing strategy.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Random once load balancing with <literal>random</literal> filter</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"filters": {
|
|
"random": {
|
|
"sticky": "1"
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Both the <literal>random</literal> and <literal>roundrobin</literal>
|
|
filters support setting a priority, a weight for a server, since
|
|
PECL/mysqlnd_ms 1.4.0. If the <literal>weight</literal> argument is
|
|
passed to the filter, it must assign a weight for all servers. Servers
|
|
must be given an alias name in the <literal>slave</literal> respectively
|
|
<literal>master</literal> server lists. The alias must be used
|
|
to reference servers for assigning a priority with <literal>weight</literal>.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Referencing error</title>
|
|
<screen>
|
|
<![CDATA[
|
|
[E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Unknown server 'slave3' in 'random' filter configuration. Stopping in %s on line %d
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Using a wrong alias name with <literal>weight</literal> may result in
|
|
an error similar to the shown above.
|
|
</para>
|
|
<para>
|
|
If <literal>weight</literal> is omitted, the default weight of
|
|
all servers is one.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Assigning a <literal>weight</literal> for load balancing</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master1":{
|
|
"host":"localhost",
|
|
"socket":"\/var\/run\/mysql\/mysql.sock"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave1": {
|
|
"host":"192.168.2.28",
|
|
"port":3306
|
|
},
|
|
"slave2": {
|
|
"host":"192.168.2.29",
|
|
"port":3306
|
|
},
|
|
"slave3": {
|
|
"host":"192.0.43.10",
|
|
"port":3306
|
|
},
|
|
},
|
|
"filters": {
|
|
"random": {
|
|
"weights": {
|
|
"slave1":8,
|
|
"slave2":4,
|
|
"slave3":1,
|
|
"master1":1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
At the average a server assigned a weight of two will be selected twice
|
|
as often as a server assigned a weight of one. Different weights can be
|
|
assigned to reflect differently sized machines, to prefer co-located slaves
|
|
which have a low network latency or, to configure a standby failover server.
|
|
In the latter case, you may want to assign the standby server a very low
|
|
weight in relation to the other servers. For example, given the
|
|
configuration above <literal>slave3</literal> will get only some eight
|
|
percent of the requests in the average. As long as <literal>slave1</literal>
|
|
and <literal>slave2</literal> are running, it will be used sparsely,
|
|
similar to a standby failover server. Upon failure of <literal>slave1</literal>
|
|
and <literal>slave2</literal>, the usage of <literal>slave3</literal>
|
|
increases. Please, check the notes on failover before using
|
|
<literal>weight</literal> this way.
|
|
</para>
|
|
<para>
|
|
Valid weight values range from 1 to 65535.
|
|
</para>
|
|
<para>
|
|
Unknown arguments are ignored by the filter. No warning or error is given.
|
|
</para>
|
|
<para>
|
|
The filter expects one or more servers as input. Outputs one server.
|
|
A filter sequence such as
|
|
<literal>random</literal>, <literal>roundrobin</literal> may
|
|
cause a warning and an error message to be set on the connection
|
|
handle when executing a statement.
|
|
</para>
|
|
<para>
|
|
List of filter arguments.
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Keyword</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>sticky</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Enables or disabled random once load
|
|
balancing policy. See above.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>weight</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Assigns a load balancing weight/priority to
|
|
a server. Please, see above for a description.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.4.0.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filter-roundrobin">
|
|
<term>
|
|
Filter: <parameter>roundrobin</parameter>
|
|
<type>object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
If using the <literal>roundrobin</literal> filter, the plugin
|
|
iterates over the list of configured slave servers to pick a server
|
|
for statement execution. If the plugin reaches the end of the list,
|
|
it wraps around to the beginning of the list and picks the first
|
|
configured slave server.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title><literal>roundrobin</literal> filter</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": [
|
|
"roundrobin"
|
|
]
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Expects one or more servers as input. Outputs one server.
|
|
A filter sequence such as
|
|
<literal>roundrobin</literal>, <literal>random</literal> may
|
|
cause a warning and an error message to be set on the connection
|
|
handle when executing a statement.
|
|
</para>
|
|
<para>
|
|
List of filter arguments.
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Keyword</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>weight</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Assigns a load balancing weight/priority to
|
|
a server. Please, find a description
|
|
<link linkend="ini.mysqlnd-ms-plugin-config-v2.filter-random">above</link>.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.4.0.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filter-user">
|
|
<term>
|
|
Filter: <parameter>user</parameter>
|
|
<type>object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The <literal>user</literal> replaces
|
|
<function>mysqlnd_ms_set_user_pick_server</function> function,
|
|
which was removed in 1.1.0-beta. The filter sets a callback for user-defined
|
|
read/write splitting and server selection.
|
|
</para>
|
|
<para>
|
|
The plugins built-in read/write query split mechanism decisions can be
|
|
overwritten in two ways. The easiest way is to prepend a 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 chooses 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>
|
|
<para>
|
|
<example>
|
|
<title>Setting a callback</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": {
|
|
"user": {
|
|
"callback": "pick_server"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
The callback is supposed to return a 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 emit an error of the type <literal>E_RECOVERABLE_ERROR</literal>
|
|
The error may read like
|
|
<literal> (mysqlnd_ms) User filter callback has returned an unknown server.
|
|
The server 'server that is not in master or slave list' can neither be found
|
|
in the master list nor in the slave list</literal>.
|
|
If the application catches the error to ignore it, follow up errors
|
|
may be set on the connection handle, for example,
|
|
<literal>(mysqlnd_ms) No connection selected by the last filter</literal> with
|
|
the error code <literal>2000</literal> and the sqlstate <literal>HY000</literal>.
|
|
Furthermore a warning may be emitted.
|
|
</para>
|
|
<para>
|
|
Referencing a non-existing function as a callback will result
|
|
in any error of the type <literal>E_RECOVERABLE_ERROR</literal> whenever
|
|
the plugin tries to callback function. The error message may reads like:
|
|
<literal>(mysqlnd_ms) Specified callback (pick_server) is
|
|
not a valid callback</literal>. If the application catches the error to
|
|
ignore it, follow up errors may be set on the connection handle, for example,
|
|
<literal>(mysqlnd_ms) Specified callback (pick_server) is
|
|
not a valid callback</literal> with the error code <literal>2000</literal>
|
|
and the sqlstate <literal>HY000</literal>. Furthermore a warning
|
|
may be emitted.
|
|
</para>
|
|
<para>
|
|
The following parameters are passed from the plugin to the callback.
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Parameter</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>connected_host</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
URI of the currently connected database server.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>query</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Query string of the statement for which a server needs
|
|
to be picked.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>masters</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
List of master servers to choose from. Note, that the list of master
|
|
servers may not be identical to the list of configured master
|
|
servers if the filter is not the first in the filter chain.
|
|
Previously run filters may have reduced the master
|
|
list already.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>slaves</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
List of slave servers to choose from. Note, that the list of master
|
|
servers may not be identical to the list of configured master
|
|
servers if the filter is not the first in the filter chain.
|
|
Previously run filters may have reduced the master
|
|
list already.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>last_used_connection</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
URI of the server of the connection used to execute the previous
|
|
statement on.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>in_transaction</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Boolean flag indicating whether the statement is
|
|
part of an open transaction. If autocommit mode is turned
|
|
off, this will be set to &true;. Otherwise
|
|
it is set to &false;.
|
|
</para>
|
|
<para>
|
|
Transaction detection is based on monitoring the
|
|
mysqlnd library call <literal>set_autocommit</literal>.
|
|
Monitoring is not possible before PHP 5.4.0. Please, see
|
|
<link linkend="mysqlnd-ms.pooling">connection pooling and switching</link>
|
|
concepts discussion for further details.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
<para>
|
|
<example>
|
|
<title>Using a callback</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.2.27",
|
|
"port": "3306"
|
|
},
|
|
"slave_1": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": {
|
|
"user": {
|
|
"callback": "pick_server"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function pick_server($connected, $query, $masters, $slaves, $last_used_connection, $in_transaction)
|
|
{
|
|
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 = $masters[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_connection;
|
|
break;
|
|
}
|
|
|
|
printf("... ret = '%s'\n", $ret);
|
|
return $ret;
|
|
}
|
|
|
|
$mysqli = new mysqli("myapp", "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>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filter-user-multi">
|
|
<term>
|
|
Filter: <parameter>user_multi</parameter>
|
|
<type>object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The <literal>user_multi</literal> differs from the <literal>user</literal>
|
|
only in one aspect. Otherwise, their syntax is identical.
|
|
The <literal>user</literal> filter must pick
|
|
and return exactly one node for statement execution. A filter chain
|
|
usually ends with a filter that emits only one node. The filter chain
|
|
shall reduce the list of candidates for statement execution down to
|
|
one. This, only one node left, is the case after the <literal>user</literal>
|
|
filter has been run.
|
|
</para>
|
|
<para>
|
|
The <literal>user_multi</literal> filter is a multi filter. It returns a
|
|
list of slave and a list of master servers. This list needs further filtering
|
|
to identify exactly one node for statement execution. A multi filter is typically
|
|
placed at the top of the filter chain. The <literal>quality_of_service</literal>
|
|
filter is another example of a multi filter.
|
|
</para>
|
|
<para>
|
|
The return value of the callback set for <literal>user_multi</literal> must
|
|
be an an array with two elements. The first element holds a list of selected master
|
|
servers. The second element contains a list of selected slave servers. The
|
|
lists shall contain the keys of the slave and master servers as found in
|
|
the slave and master lists passed to the callback. The below example returns
|
|
random master and slave lists extracted from the functions input.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Returning random masters and slaves</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function pick_server($connected, $query, $masters, $slaves, $last_used_connection, $in_transaction)
|
|
{
|
|
$picked_masters = array()
|
|
foreach ($masters as $key => $value) {
|
|
if (mt_rand(0, 2) > 1)
|
|
$picked_masters[] = $key;
|
|
}
|
|
$picked_slaves = array()
|
|
foreach ($slaves as $key => $value) {
|
|
if (mt_rand(0, 2) > 1)
|
|
$picked_slaves[] = $key;
|
|
}
|
|
return array($picked_masters, $picked_slaves);
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
The plugin will issue an
|
|
error of type <literal>E_RECOVERABLE</literal> if the callback fails to return
|
|
a server list. The error may read <literal>(mysqlnd_ms) User multi
|
|
filter callback has not returned a list of servers to use.
|
|
The callback must return an array in %s on line %d</literal>. In case the
|
|
server list is not empty but has invalid servers key/ids in it, an error
|
|
of type <literal>E_RECOVERABLE</literal> will the thrown with an
|
|
error message like <literal>(mysqlnd_ms) User multi filter callback
|
|
has returned an invalid list of servers to use.
|
|
Server id is negative in %s on line %d</literal>, or similar.
|
|
</para>
|
|
<para>
|
|
Whether an error is emitted in case of an empty slave or master list
|
|
depends on the configuration. If an empty master list is returned
|
|
for a write operation, it is likely that the plugin will emit a
|
|
warning that may read <literal>(mysqlnd_ms) Couldn't find the appropriate
|
|
master connection. 0 masters to choose from. Something is wrong in %s on line %d</literal>.
|
|
Typically a follow up error of type <literal>E_ERROR</literal> will happen.
|
|
In case of a read operation and an empty slave list the behavior depends
|
|
on the fail over configuration. If fail over to master is enabled, no
|
|
error should appear. If fail over to master is deactivated the plugin will
|
|
emit a warning that may read <literal>(mysqlnd_ms) Couldn't find the appropriate
|
|
slave connection. 0 slaves to choose from. Something is wrong in %s on line %d</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filter-qos">
|
|
<term>
|
|
Filter: <parameter>quality_of_service</parameter>
|
|
<type>object</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The <literal>quality_of_service</literal> identifies cluster nodes
|
|
capable of delivering a certain quality of service. It is a multi filter
|
|
which returns zero, one or multiple of its input servers. Thus, it
|
|
must be followed by other filters to reduce the number of candidates
|
|
down to one for statement execution.
|
|
</para>
|
|
<para>
|
|
The <literal>quality_of_service</literal> filter has been introduced in 1.2.0-alpha.
|
|
In the 1.2 series the filters focus is on the consistency aspect of
|
|
service quality. Different types of clusters offer different
|
|
default data consistencies. For example, an asynchronous MySQL
|
|
replication slave offers eventual consistency. The slave may not
|
|
be able to deliver requested data because it has not replicated the write,
|
|
it may serve stale database because its lagging behind or it may serve
|
|
current information. Often, this is acceptable. In some cases
|
|
higher consistency levels are needed for the application to work correct.
|
|
In those cases, the <literal>quality_of_service</literal> can filter out cluster nodes
|
|
which cannot deliver the necessary quality of service.
|
|
</para>
|
|
<para>
|
|
The <literal>quality_of_service</literal> filter can be replaced or created
|
|
at runtime. A successful call to
|
|
<function>mysqlnd_ms_set_qos</function>
|
|
removes all existing <literal>qos</literal> filter entries from the
|
|
filter list and installs a new one at the very beginning. All settings
|
|
that can be made through
|
|
<function>mysqlnd_ms_set_qos</function>
|
|
can also be in the plugins configuration file. However, use of the function
|
|
is by far the most common use case. Instead of setting session consistency and
|
|
strong consistency service levels in the plugins configuration file it is
|
|
recommended to define only masters and no slaves. Both service levels will
|
|
force the use of masters only. Using an empty slave list shortens the
|
|
configuration file, thus improving readability. The only service level for which
|
|
there is a case of defining in the plugins configuration file is the combination
|
|
of eventual consistency and maximum slave lag.
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Keyword</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>eventual_consistency</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Request eventual consistency. Allows the use of all
|
|
master and slave servers. Data returned may or may not be current.
|
|
</para>
|
|
<para>
|
|
Eventual consistency accepts an optional <literal>age</literal>
|
|
parameter. If <literal>age</literal> is given the plugin considers
|
|
only slaves for reading for which MySQL replication reports
|
|
a slave lag less or equal to <literal>age</literal>.
|
|
The replication lag is measure using <literal>SHOW SLAVE STATUS</literal>.
|
|
If the plugin fails to fetch the replication lag, the slave tested
|
|
is skipped. Implementation details and tips are given in the
|
|
<link linkend="mysqlnd-ms.qos-consistency">quality of service concepts section</link>.
|
|
</para>
|
|
<para>
|
|
Please note, if a filter chain
|
|
generates an empty slave list and the PHP configuration directive
|
|
<literal>mysqlnd_ms.multi_master=0</literal> is used, the plugin may
|
|
emit a warning.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Global limit on slave lag</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.2.27",
|
|
"port": "3306"
|
|
},
|
|
"slave_1": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"filters": {
|
|
"quality_of_service": {
|
|
"eventual_consistency": {
|
|
"age":123
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>session_consistency</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Request session consistency (read your writes). Allows use of all masters
|
|
and all slaves which are in sync with the master.
|
|
If no further parameters are given slaves are filtered out
|
|
as there is no reliable way to test if a slave has caught up
|
|
to the master or is lagging behind. Please note, if a filter chain
|
|
generates an empty slave list and the PHP configuration directive
|
|
<literal>mysqlnd_ms.multi_master=0</literal> is used, the plugin may
|
|
emit a warning.
|
|
</para>
|
|
<para>
|
|
Session consistency temporarily requested using
|
|
<function>mysqlnd_ms_set_qos</function> is a valuable alternative
|
|
to using <literal>master_on_write</literal>.
|
|
<literal>master_on_write</literal> is likely to send more statements
|
|
to the master than needed. The application may be able to continue
|
|
operation at a lower consistency level after it has done
|
|
some critical reads.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.1.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>strong_consistency</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Request strong consistency. Only masters will be used.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.2.0.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.failover">
|
|
<term>
|
|
<parameter>failover</parameter>
|
|
Up to and including 1.3.x: <type>string</type>.
|
|
Since 1.4.0: <type>object</type>.
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Failover policy. Supported policies:
|
|
<literal>disabled</literal> (default), <literal>master</literal>,
|
|
<literal>loop_before_master</literal> (Since 1.4.0).
|
|
</para>
|
|
<para>
|
|
If no failover policy is set, the plugin will not do any
|
|
automatic failover (<literal>failover=disabled</literal>). Whenever
|
|
the plugin fails to connect a server it will emit a warning and
|
|
set the connections error code and message. Thereafter it is up to
|
|
the application to handle the error and, for example, resent the
|
|
last statement to trigger the selection of another server.
|
|
</para>
|
|
<para>
|
|
Please note, the automatic failover logic is applied when opening
|
|
connections only. Once a connection has been opened no automatic attempts
|
|
are made to reopen it in case of an error. If, for example, the server
|
|
a connection is connected to is shut down and the user attempts to
|
|
run a statement on the connection, no automatic failover
|
|
will be tried. Instead, an error will be reported.
|
|
</para>
|
|
<para>
|
|
If using <literal>failover=master</literal> the plugin will implicitly
|
|
failover to a master, if available. Please check the
|
|
concepts documentation to learn about potential
|
|
pitfalls and risks of using <literal>failover=master</literal>.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Optional master failover when failing to connect to slave (PECL/mysqlnd_ms < 1.4.0)</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"failover": "master"
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Since PECL/mysqlnd_ms 1.4.0 the failover configuration keyword refers to an
|
|
object.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>New syntax since 1.4.0</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"failover": {"strategy": "master" }
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<informaltable>
|
|
<tgroup cols="3">
|
|
<colspec colwidth="1*"/>
|
|
<colspec colwidth="7*"/>
|
|
<colspec colwidth="2*"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Keyword</entry>
|
|
<entry>Description</entry>
|
|
<entry>Version</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>
|
|
<literal>strategy</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Failover policy. Possible values:
|
|
<literal>disabled</literal> (default), <literal>master</literal>,
|
|
<literal>loop_before_master</literal>
|
|
</para>
|
|
<para>
|
|
A value of <literal>disabled</literal> disables automatic failover.
|
|
</para>
|
|
<para>
|
|
Setting <literal>master</literal> instructs the plugin to try
|
|
to connect to a master in case of a slave connection error. If the
|
|
master connection attempt fails, the plugin exists the failover
|
|
loop and returns an error to the user.
|
|
</para>
|
|
<para>
|
|
If using <literal>loop_before_master</literal> and a slave request
|
|
is made, the plugin tries to connect to other slaves before failing
|
|
over to a master. If multiple master are given and multi master is enabled,
|
|
the plugin also loops over the list of masters and attempts to connect
|
|
before returning an error to the user.
|
|
</para>
|
|
</entry>
|
|
<entry>Since 1.4.0.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>remember_failed</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Remember failures for the duration of a web request. Default:
|
|
<literal>false</literal>.
|
|
</para>
|
|
<para>
|
|
If set to <literal>true</literal> the plugin will remember failed
|
|
hosts and skip the hosts in all future load balancing made for
|
|
the duration of the current web request.
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
Since 1.4.0. Experimental feature. The feature is only available together
|
|
with the <literal>random</literal> and <literal>roundrobin</literal>
|
|
load balancing filter. The behavior and syntax is likely to change
|
|
in the future.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>
|
|
<literal>max_retries</literal>
|
|
</entry>
|
|
<entry>
|
|
<para>
|
|
Maximum number of connection attempts before skipping host.
|
|
Default: <literal>0</literal> (no limit).
|
|
</para>
|
|
<para>
|
|
The setting is used to prevent hosts from being dropped of the
|
|
host list upon the first failure. If set to <literal>n > 0</literal>,
|
|
the plugin will keep the node in the node list even after a failed
|
|
connection attempt. The node will not be removed immediately from the slave respectively
|
|
master lists after the first connection failure but instead be tried to
|
|
connect to up to <literal>n</literal> times in future load balancing rounds
|
|
before being removed.
|
|
</para>
|
|
</entry>
|
|
<entry>
|
|
Since 1.4.0. Experimental feature. The feature is only available together
|
|
with the <literal>random</literal> and <literal>roundrobin</literal>
|
|
load balancing filter. The behavior and syntax is likely to change
|
|
in the future.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
<para>
|
|
Setting <literal>failover</literal> to any other value but
|
|
<literal>disabled</literal>, <literal>master</literal> or
|
|
<literal>loop_before_master</literal>
|
|
will not emit any warning or error.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.lazy-connections">
|
|
<term>
|
|
<parameter>lazy_connections</parameter>
|
|
<type>bool</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Controls the use of lazy connections. Lazy connections
|
|
are connections which are not opened before the client sends the first
|
|
connection. Lazy connections are a default.
|
|
</para>
|
|
<para>
|
|
It is strongly recommended to use lazy connections.
|
|
Lazy connections help to keep the number of open connections low.
|
|
If you disable lazy connections and, for example, configure one MySQL
|
|
replication master server and two MySQL replication slaves, the
|
|
plugin will open three connections upon the first call to a
|
|
connect function although the application might use the master
|
|
connection only.
|
|
</para>
|
|
<para>
|
|
Lazy connections bare a risk if you make heavy use of actions
|
|
which change the state of a connection. The plugin does not dispatch
|
|
all state changing actions to all connections from the connection pool.
|
|
The few dispatched actions are applied to already opened connections
|
|
only. Lazy connections opened in the future are not affected.
|
|
Only some settings are "remembered" and applied when lazy
|
|
connections are opened.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Disabling lazy connection</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"lazy_connections": 0
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Please, see also <literal>server_charset</literal> to overcome potential
|
|
problems with string escaping and servers using different default
|
|
charsets.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.server-charset">
|
|
<term>
|
|
<parameter>server_charset</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The setting has been introduced in 1.4.0. It is recommended to set it
|
|
if using lazy connections.
|
|
</para>
|
|
<para>
|
|
The <literal>server_charset</literal> setting serves two purposes. It
|
|
acts as a fallback charset to be used for string escaping done before
|
|
a connection has been established and it helps to avoid escaping pitfalls
|
|
in heterogeneous environments which servers using different default charsets.
|
|
</para>
|
|
<para>
|
|
String escaping takes a connections charset into account. String escaping
|
|
is not possible before a connection has been opened and the connections
|
|
charset is known. The use of lazy connections delays the actual opening
|
|
of connections until a statement is send.
|
|
</para>
|
|
<para>
|
|
An application using lazy connections may attempt to escape a string
|
|
before sending a statement. In fact, this should be a common case as
|
|
the statement string may contain the string that is to be escaped.
|
|
However, due to the lazy connection feature no connection has been opened
|
|
yet and escaping fails. The plugin may report an error of the type
|
|
<literal>E_WARNING</literal> and a message like <literal>(mysqlnd_ms)
|
|
string escaping doesn't work without established connection.
|
|
Possible solution is to add server_charset to your configuration</literal>
|
|
to inform you of the pitfall.
|
|
</para>
|
|
<para>
|
|
Setting <literal>server_charset</literal> makes the plugin use
|
|
the given charset for string escaping done on lazy connection handles
|
|
before establishing a network connection to MySQL. Furthermore, the
|
|
plugin will enforce the use of the charset when the connection is
|
|
established.
|
|
</para>
|
|
<para>
|
|
Enforcing the use of the configured charset used for escaping is done
|
|
to prevent tapping into the pitfall of using a different charset for
|
|
escaping than used later for the connection. This has the additional
|
|
benefit of removing the need to align the charset configuration of all
|
|
servers used. No matter what the default charset on any of the servers is,
|
|
the plugin will set the configured one as a default.
|
|
</para>
|
|
<para>
|
|
The plugin does not stop the user from changing the charset at any time
|
|
using the <function>set_charset</function> call or corresponding SQL statements.
|
|
Please, note that the use of SQL is not recommended as it cannot be monitored
|
|
by the plugin. The user can, for example, change the charset on a
|
|
lazy connection handle after escaping a string and before the actual connection
|
|
is opened. The charset set by the user will be used for any subsequent escaping
|
|
before the connection is established. The connection will be established
|
|
using the configured charset, no matter what the server charset is or
|
|
what the user has set before. Once a connection has been opened,
|
|
<literal>set_charset</literal> is of no meaning anymore.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>String escaping on a lazy connection handle</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"lazy_connections": 1,
|
|
"server_charset" : "utf8"
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$mysqli = new mysqli("myapp", "username", "password", "database");
|
|
$mysqli->real_escape("this will be escaped using the server_charset setting - utf8");
|
|
$mysqli->set_charset("latin1");
|
|
$mysqli->real_escape("this will be escaped using latin1");
|
|
/* server_charset implicitly set - utf8 connection */
|
|
$mysqli->query("SELECT 'This connection will be set to server_charset upon establishing' AS _msg FROM DUAL");
|
|
/* latin1 used from now on */
|
|
$mysqli->set_charset("latin1");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.master-on-write">
|
|
<term>
|
|
<parameter>master_on_write</parameter>
|
|
<type>bool</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
If set, the plugin will use the master server only after the
|
|
first statement has been executed on the master. Applications
|
|
can still send statements to the slaves using SQL hints to
|
|
overrule the automatic decision.
|
|
</para>
|
|
<para>
|
|
The setting may help with replication lag. If an application runs
|
|
an <literal>INSERT</literal> the plugin will, by default, use the
|
|
master to execute all following statements, including
|
|
<literal>SELECT</literal> statements. This helps to avoid problems
|
|
with reads from slaves which have not replicated the
|
|
<literal>INSERT</literal> yet.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Master on write for consistent reads</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"master_on_write": 1
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Please, note the <literal>quality_of_service</literal> filter introduced
|
|
in version 1.2.0-alpha. It gives finer control, for example, for achieving read-your-writes
|
|
and, it offers additional functionality introducing
|
|
<link linkend="mysqlnd-ms.qos-consistency">service levels</link>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.trx-stickiness">
|
|
<term>
|
|
<parameter>trx_stickiness</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Transaction stickiness policy. Supported policies:
|
|
<literal>disabled</literal> (default), <literal>master</literal>.
|
|
</para>
|
|
<para>
|
|
The setting requires 5.4.0 or newer. If used with PHP older than 5.4.0,
|
|
the plugin will emit a warning like
|
|
<literal>(mysqlnd_ms) trx_stickiness strategy is not supported before PHP 5.3.99</literal>.
|
|
</para>
|
|
<para>
|
|
If no transaction stickiness policy is set or,
|
|
if setting <literal>trx_stickiness=disabled</literal>,
|
|
the plugin is not transaction aware. Thus, the plugin may load balance
|
|
connections and switch connections in the middle of a transaction.
|
|
The plugin is not transaction safe. SQL hints must be used
|
|
avoid connection switches during a transaction.
|
|
</para>
|
|
<para>
|
|
As of PHP 5.4.0 the mysqlnd library allows the plugin to monitor
|
|
the <literal>autocommit</literal> mode set by calls to the
|
|
libraries <literal>set_autocommit()</literal> function.
|
|
If setting <literal>set_stickiness=master</literal> and
|
|
<literal>autocommit</literal> gets disabled by a PHP MySQL extension
|
|
invoking the <literal>mysqlnd</literal> library internal
|
|
function call <literal>set_autocommit()</literal>, the plugin is made
|
|
aware of the begin of a transaction. Then, the plugin stops load balancing
|
|
and directs all statements to the master server until
|
|
<literal>autocommit</literal> is enabled. Thus, no SQL hints are required.
|
|
</para>
|
|
<para>
|
|
An example of a PHP MySQL API function calling the <literal>mysqlnd</literal>
|
|
library internal function call <literal>set_autocommit()</literal> is
|
|
<function>mysqli_autocommit</function>.
|
|
</para>
|
|
<para>
|
|
Although setting <literal>ser_stickiness=master</literal>, the plugin
|
|
cannot be made aware of <literal>autocommit</literal> mode changes caused
|
|
by SQL statements such as <literal>SET AUTOCOMMIT=0</literal>.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Using master to execute transactions</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
{
|
|
"myapp": {
|
|
"master": {
|
|
"master_0": {
|
|
"host": "localhost"
|
|
}
|
|
},
|
|
"slave": {
|
|
"slave_0": {
|
|
"host": "192.168.78.136",
|
|
"port": "3306"
|
|
}
|
|
},
|
|
"trx_stickiness": "master"
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</section>
|
|
|
|
<section xml:id="mysqlnd-ms.plugin-ini-v1">
|
|
<title xmlns="http://docbook.org/ns/docbook">Plugin configuration file (<= 1.0.x)</title>
|
|
<note>
|
|
<para>
|
|
The below description applies to PECL/mysqlnd_ms < 1.1.0-beta.
|
|
It is not valid for later versions.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
The plugin is using its own configuration file. The configuration file
|
|
holds information on the MySQL replication master server,
|
|
the MySQL replication slave servers, the server pick (load balancing) policy,
|
|
the failover strategy and the use of lazy connections.
|
|
</para>
|
|
<para>
|
|
The PHP configuration directive
|
|
<link linkend="ini.mysqlnd-ms.ini-file"><literal>mysqlnd_ms.ini_file</literal></link>
|
|
is used to set the plugins configuration file.
|
|
</para>
|
|
<para>
|
|
The configuration file mimics standard the <literal>php.ini</literal> format.
|
|
It consists of one or more sections. Every section defines its own unit
|
|
of settings. There is no global section for setting defaults.
|
|
</para>
|
|
<para>
|
|
Applications reference sections by their name. Applications use section names
|
|
as the host (server) parameter to the various connect methods of the
|
|
<link linkend="ref.mysqli">mysqli</link>,
|
|
<link linkend="ref.mysql">mysql</link> and
|
|
<link linkend="ref.pdo-mysql">PDO_MYSQL</link> extensions. Upon connect
|
|
the <link linkend="book.mysqlnd">mysqlnd</link> plugin compares the hostname
|
|
with all section names from the plugin configuration file. If hostname and
|
|
section name match, the plugin will load the sections settings.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Using section names example</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
[myapp]
|
|
master[] = localhost
|
|
slave[] = 192.168.2.27
|
|
slave[] = 192.168.2.28:3306
|
|
[localhost]
|
|
master[] = localhost:/tmp/mysql/mysql.sock
|
|
slave[] = 192.168.3.24:3305
|
|
slave[] = 192.168.3.65:3309
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/* All of the following connections will be load balanced */
|
|
$mysqli = new mysqli("myapp", "username", "password", "database");
|
|
$pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
|
|
$mysql = mysql_connect("myapp", "username", "password");
|
|
|
|
$mysqli = new mysqli("localhost", "username", "password", "database");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Section names are strings. It is valid to use a section name such as
|
|
<literal>192.168.2.1</literal>, <literal>127.0.0.1</literal> or
|
|
<literal>localhost</literal>. If, for example, an application
|
|
connects to <literal>localhost</literal> and a plugin
|
|
configuration section <literal>[localhost]</literal> exists, the
|
|
semantics of the connect operation are changed. The application will
|
|
no longer only use the MySQL server running on the host
|
|
<literal>localhost</literal> but the plugin will start to load balance
|
|
MySQL queries following the rules from the <literal>[localhost]</literal>
|
|
configuration section. This way you can load balance queries from
|
|
an application without changing the applications source code.
|
|
</para>
|
|
<para>
|
|
The <literal>master[]</literal>, <literal>slave[]</literal>
|
|
and <literal>pick[]</literal> configuration directives use a list-like syntax.
|
|
Configuration directives supporting list-like syntax may appear multiple
|
|
times in a configuration section. The plugin maintains the order in
|
|
which entries appear when interpreting them. For example,
|
|
the below example shows two <literal>slave[]</literal> configuration
|
|
directives in the configuration section <literal>[myapp]</literal>.
|
|
If doing round-robin load balancing for read-only queries, the plugin
|
|
will send the first read-only query to the MySQL server
|
|
<literal>mysql_slave_1</literal> because it is the first in the list.
|
|
The second read-only query will be send to the MySQL server
|
|
<literal>mysql_slave_2</literal> because it is the second in the list.
|
|
Configuration directives supporting list-like syntax result are ordered
|
|
from top to bottom in accordance to their appearance within a configuration
|
|
section.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>List-like syntax</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
[myapp]
|
|
master[] = mysql_master_server
|
|
slave[] = mysql_slave_1
|
|
slave[] = mysql_slave_2
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Here is a short explanation of the configuration directives that can be used.
|
|
</para>
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.master">
|
|
<term>
|
|
<parameter>master[]</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
URI of a MySQL replication master server. The URI follows the syntax
|
|
<literal>hostname[:port|unix_domain_socket]</literal>.
|
|
</para>
|
|
<para>
|
|
The plugin supports using only one master server.
|
|
</para>
|
|
<para>
|
|
Setting a master server is mandatory. The plugin will report a
|
|
warning upon connect if the user has failed to provide a master
|
|
server for a configuration section.
|
|
The warning may read
|
|
<literal>(mysqlnd_ms) Cannot find master section in config</literal>.
|
|
Furthermore the plugin may set an error code for the connection handle such as
|
|
<literal>HY000/2000 (CR_UNKNOWN_ERROR)</literal>. The corresponding error
|
|
message depends on your language settings.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.slave">
|
|
<term>
|
|
<parameter>slave[]</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
URI of one or more MySQL replication slave servers. The URI follows the syntax
|
|
<literal>hostname[:port|unix_domain_socket]</literal>.
|
|
</para>
|
|
<para>
|
|
The plugin supports using one or more slave servers.
|
|
</para>
|
|
<para>
|
|
Setting a slave server is mandatory. The plugin will report a
|
|
warning upon connect if the user has failed to provide at least one slave
|
|
server for a configuration section. The warning may read
|
|
<literal>(mysqlnd_ms) Cannot find slaves section in config</literal>.
|
|
Furthermore the plugin may set an error code for the connection handle such as
|
|
<literal>HY000/2000 (CR_UNKNOWN_ERROR)</literal>. The corresponding error
|
|
message depends on your language settings.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.pick">
|
|
<term>
|
|
<parameter>pick[]</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Load balancing (server picking) policy. Supported policies:
|
|
<literal>random</literal>, <literal>random_once</literal> (default),
|
|
<literal>roundrobin</literal>, <literal>user</literal>.
|
|
</para>
|
|
<para>
|
|
If no load balancing policy is set, the plugin will default to
|
|
<literal>random_once</literal>. The <literal>random_once</literal>
|
|
policy picks a random slave server when running the first read-only
|
|
statement. The slave server will be used for all read-only
|
|
statements until the PHP script execution ends.
|
|
</para>
|
|
<para>
|
|
The <literal>random</literal> policy will pick a random server whenever
|
|
a read-only statement is to be executed.
|
|
</para>
|
|
<para>
|
|
If using
|
|
<literal>roundrobin</literal> the plugin iterates over the list of
|
|
configured slave servers to pick a server for statement execution.
|
|
If the plugin reaches the end of the list, it wraps around to the beginning
|
|
of the list and picks the first configured slave server.
|
|
</para>
|
|
<para>
|
|
Setting more than one load balancing policy for a configuration
|
|
section makes only sense in conjunction with <literal>user</literal>
|
|
and <function>mysqlnd_ms_set_user_pick_server</function>. If the
|
|
user defined callback fails to pick a server, the plugin falls
|
|
back to the second configured load balancing policy.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.failover">
|
|
<term>
|
|
<parameter>failover</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Failover policy. Supported policies:
|
|
<literal>disabled</literal> (default), <literal>master</literal>.
|
|
</para>
|
|
<para>
|
|
If no failover policy is set, the plugin will not do any
|
|
automatic failover (<literal>failover=disabled</literal>). Whenever
|
|
the plugin fails to connect a server it will emit a warning and
|
|
set the connections error code and message. Thereafter it is up to
|
|
the application to handle the error and, for example, resent the
|
|
last statement to trigger the selection of another server.
|
|
</para>
|
|
<para>
|
|
If using <literal>failover=master</literal> the plugin will implicitly
|
|
failover to a slave, if available. Please check the
|
|
concepts documentation to learn about potential
|
|
pitfalls and risks of using <literal>failover=master</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.lazy-connections">
|
|
<term>
|
|
<parameter>lazy_connections</parameter>
|
|
<type>bool</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Controls the use of lazy connections. Lazy connections
|
|
are connections which are not opened before the client sends the first
|
|
connection.
|
|
</para>
|
|
<para>
|
|
It is strongly recommended to use lazy connections.
|
|
Lazy connections help to keep the number of open connections low.
|
|
If you disable lazy connections and, for example, configure one MySQL
|
|
replication master server and two MySQL replication slaves, the
|
|
plugin will open three connections upon the first call to a
|
|
connect function although the application might use the master
|
|
connection only.
|
|
</para>
|
|
<para>
|
|
Lazy connections bare a risk if you make heavy use of actions
|
|
which change the state of a connection. The plugin does not dispatch
|
|
all state changing actions to all connections from the connection pool.
|
|
The few dispatched actions are applied to already opened connections
|
|
only. Lazy connections opened in the future are not affected.
|
|
If, for example, the connection character set is changed using a
|
|
PHP MySQL API call, the plugin will change the character set of all
|
|
currently opened connection. It will not remember the character set
|
|
change to apply it on lazy connections opened in the future. As a
|
|
result the internal connection pool would hold connections using
|
|
different character sets. This is not desired. Remember that character
|
|
sets are taken into account for escaping.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.master-on-write">
|
|
<term>
|
|
<parameter>master_on_write</parameter>
|
|
<type>bool</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
If set, the plugin will use the master server only after the
|
|
first statement has been executed on the master. Applications
|
|
can still send statements to the slaves using SQL hints to
|
|
overrule the automatic decision.
|
|
</para>
|
|
<para>
|
|
The setting may help with replication lag. If an application runs
|
|
an <literal>INSERT</literal> the plugin will, by default, use the
|
|
master to execute all following statements, including
|
|
<literal>SELECT</literal> statements. This helps to avoid problems
|
|
with reads from slaves which have not replicated the
|
|
<literal>INSERT</literal> yet.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config.trx-stickiness">
|
|
<term>
|
|
<parameter>trx_stickiness</parameter>
|
|
<type>string</type>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Transaction stickiness policy. Supported policies:
|
|
<literal>disabled</literal> (default), <literal>master</literal>.
|
|
</para>
|
|
<para>
|
|
Experimental feature.
|
|
</para>
|
|
<para>
|
|
The setting requires 5.4.0 or newer. If used with PHP older than 5.4.0,
|
|
the plugin will emit a warning like
|
|
<literal>(mysqlnd_ms) trx_stickiness strategy is not supported before PHP 5.3.99</literal>.
|
|
</para>
|
|
<para>
|
|
If no transaction stickiness policy is set or,
|
|
if setting <literal>trx_stickiness=disabled</literal>,
|
|
the plugin is not transaction aware. Thus, the plugin may load balance
|
|
connections and switch connections in the middle of a transaction.
|
|
The plugin is not transaction safe. SQL hints must be used
|
|
avoid connection switches during a transaction.
|
|
</para>
|
|
<para>
|
|
As of PHP 5.4.0 the mysqlnd library allows the plugin to monitor
|
|
the <literal>autocommit</literal> mode set by calls to the
|
|
libraries <literal>trx_autocommit()</literal> function.
|
|
If setting <literal>trx_stickiness=master</literal> and
|
|
<literal>autocommit</literal> gets disabled by a PHP MySQL extension
|
|
invoking the <literal>mysqlnd</literal> library internal
|
|
function call <literal>trx_autocommit()</literal>, the plugin is made
|
|
aware of the begin of a transaction. Then, the plugin stops load balancing
|
|
and directs all statements to the master server until
|
|
<literal>autocommit</literal> is enabled. Thus, no SQL hints are required.
|
|
</para>
|
|
<para>
|
|
An example of a PHP MySQL API function calling the <literal>mysqlnd</literal>
|
|
library internal function call <literal>trx_autocommit()</literal> is
|
|
<function>mysqli_autocommit</function>.
|
|
</para>
|
|
<para>
|
|
Although setting <literal>trx_stickiness=master</literal>, the plugin
|
|
cannot be made aware of <literal>autocommit</literal> mode changes caused
|
|
by SQL statements such as <literal>SET AUTOCOMMIT=0</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</section>
|
|
|
|
<section xml:id="mysqlnd-ms.testing">
|
|
<title xmlns="http://docbook.org/ns/docbook">Testing</title>
|
|
<note>
|
|
<para>
|
|
The section applies to mysqlnd_ms 1.1.0 or newer, not the 1.0 series.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
The PECL/mysqlnd_ms test suite is in the <filename>tests/</filename>
|
|
directory of the source distribution. The test suite consists of standard
|
|
phpt tests, which are described on the PHP Quality Assurance Teams website.
|
|
</para>
|
|
<para>
|
|
Running the tests requires setting up one to four MySQL servers. Some tests don't
|
|
connect to MySQL at all. Others require one server for testing. Some require
|
|
two distinct servers. In some cases two servers are used to emulate a
|
|
replication setup. In other cases a master and a slave of an existing MySQL replication
|
|
setup are required for testing. The tests will try to detect how many servers
|
|
and what kind of servers are given. If the required servers are not found, the
|
|
test will be skipped automatically.
|
|
</para>
|
|
<para>
|
|
Before running the tests, edit <filename>tests/config.inc</filename> to
|
|
configure the MySQL servers to be used for testing.
|
|
</para>
|
|
<para>
|
|
The most basic configuration is as follows.
|
|
<programlisting>
|
|
<![CDATA[
|
|
putenv("MYSQL_TEST_HOST=localhost");
|
|
putenv("MYSQL_TEST_PORT=3306");
|
|
putenv("MYSQL_TEST_USER=root");
|
|
putenv("MYSQL_TEST_PASSWD=");
|
|
putenv("MYSQL_TEST_DB=test");
|
|
putenv("MYSQL_TEST_ENGINE=MyISAM");
|
|
putenv("MYSQL_TEST_SOCKET=");
|
|
|
|
putenv("MYSQL_TEST_SKIP_CONNECT_FAILURE=1");
|
|
putenv("MYSQL_TEST_CONNECT_FLAGS=0");
|
|
putenv("MYSQL_TEST_EXPERIMENTAL=0");
|
|
|
|
/* replication cluster emulation */
|
|
putenv("MYSQL_TEST_EMULATED_MASTER_HOST=". getenv("MYSQL_TEST_HOST"));
|
|
putenv("MYSQL_TEST_EMULATED_SLAVE_HOST=". getenv("MYSQL_TEST_HOST"));
|
|
|
|
/* real replication cluster */
|
|
putenv("MYSQL_TEST_MASTER_HOST=". getenv("MYSQL_TEST_EMULATED_MASTER_HOST"));
|
|
putenv("MYSQL_TEST_SLAVE_HOST=". getenv("MYSQL_TEST_EMULATED_SLAVE_HOST"));
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
<literal>MYSQL_TEST_HOST</literal>, <literal>MYSQL_TEST_PORT</literal> and
|
|
<literal>MYSQL_TEST_SOCKET</literal> define the hostname,
|
|
TCP/IP port and Unix domain socket of the default database server.
|
|
<literal>MYSQL_TEST_USER</literal> and <literal>MYSQL_TEST_PASSWD</literal>
|
|
contain the user and password needed to connect to the database/schema
|
|
configured with <literal>MYSQL_TEST_DB</literal>. All configured
|
|
servers must have the same database user configured to give access to
|
|
the test database.
|
|
</para>
|
|
<para>
|
|
Using <literal>host</literal>, <literal>host:port</literal> or <literal>host:/path/to/socket</literal>
|
|
syntax one can set an alternate host, host and port or host and socket for any
|
|
of the servers.
|
|
<programlisting>
|
|
<![CDATA[
|
|
putenv("MYSQL_TEST_SLAVE_HOST=192.168.78.136:3307"));
|
|
putenv("MYSQL_TEST_MASTER_HOST=myserver_hostname:/path/to/socket"));
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
</section>
|
|
|
|
<section xml:id="mysqlnd-ms.debugging">
|
|
<title xmlns="http://docbook.org/ns/docbook">Debugging and Tracing</title>
|
|
<para>
|
|
The mysqlnd debug log can be used to debug and trace the actitivities of
|
|
PECL/mysqlnd_ms. As a mysqlnd PECL/mysqlnd_ms adds trace information to the
|
|
mysqlnd library debug file. Please, see the
|
|
<link linkend="mysqlnd.debug"><literal>mysqlnd.debug</literal></link>
|
|
PHP configuration directive documentation for a detailed description
|
|
on how to configure the debug log.
|
|
</para>
|
|
<para>
|
|
Configuration setting example to activate the debug log:
|
|
<programlisting>
|
|
<![CDATA[
|
|
mysqlnd.debug=d:t:x:O,/tmp/mysqlnd.trace
|
|
]]>
|
|
</programlisting>
|
|
<note>
|
|
<para>
|
|
This feature is only available with a debug build of PHP. Works
|
|
on Microsoft Windows if using a debug build of PHP and PHP was
|
|
built using Microsoft Visual C version 9 and above.
|
|
</para>
|
|
</note>
|
|
</para>
|
|
<para>
|
|
The debug log shows mysqlnd library and PECL/mysqlnd_ms plugin function calls,
|
|
similar to a trace log. Mysqlnd library calls are usually prefixed with
|
|
<literal>mysqlnd_</literal>. PECL/mysqlnd internal calls begin with
|
|
<literal>mysqlnd_ms</literal>.
|
|
</para>
|
|
<para>
|
|
Example excerpt from the debug log (connect):
|
|
<programlisting>
|
|
<![CDATA[
|
|
[...]
|
|
>mysqlnd_connect
|
|
| info : host=myapp user=root db=test port=3306 flags=131072
|
|
| >mysqlnd_ms::connect
|
|
| | >mysqlnd_ms_config_json_section_exists
|
|
| | | info : section=[myapp] len=[5]
|
|
| | | >mysqlnd_ms_config_json_sub_section_exists
|
|
| | | | info : section=[myapp] len=[5]
|
|
| | | | info : ret=1
|
|
| | | <mysqlnd_ms_config_json_sub_section_exists
|
|
| | | info : ret=1
|
|
| | <mysqlnd_ms_config_json_section_exists
|
|
[...]
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
The debug log is not only useful for plugin developers but also to find the
|
|
cause of user errors. For example, if your application does not do proper
|
|
error handling and fails to record error messages, checking the debug
|
|
and trace log may help finding the cause. Use of the debug log
|
|
to debug application issues should be considered only if no other
|
|
option is available. Writing the debug log to disk is a slow
|
|
operation and may have negative impact on the application
|
|
performance.
|
|
</para>
|
|
<para>
|
|
Example excerpt from the debug log (connection failure):
|
|
<programlisting>
|
|
<![CDATA[
|
|
[...]
|
|
| | | | | | | info : adding error [Access denied for user 'root'@'localhost' (using password: YES)] to the list
|
|
| | | | | | | info : PACKET_FREE(0)
|
|
| | | | | | | info : PACKET_FREE(0x7f3ef6323f50)
|
|
| | | | | | | info : PACKET_FREE(0x7f3ef6324080)
|
|
| | | | | | <mysqlnd_auth_handshake
|
|
| | | | | | info : switch_to_auth_protocol=n/a
|
|
| | | | | | info : conn->error_info.error_no = 1045
|
|
| | | | | <mysqlnd_connect_run_authentication
|
|
| | | | | info : PACKET_FREE(0x7f3ef63236d8)
|
|
| | | | | >mysqlnd_conn::free_contents
|
|
| | | | | | >mysqlnd_net::free_contents
|
|
| | | | | | <mysqlnd_net::free_contents
|
|
| | | | | | info : Freeing memory of members
|
|
| | | | | | info : scheme=unix:///tmp/mysql.sock
|
|
| | | | | | >mysqlnd_error_list_pdtor
|
|
| | | | | | <mysqlnd_error_list_pdtor
|
|
| | | | | <mysqlnd_conn::free_contents
|
|
| | | | <mysqlnd_conn::connect
|
|
[...]
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
The trace log can also be used to verify correct behaviour
|
|
of PECL/mysqlnd_ms itself, for example, to check which server has been
|
|
selected for query execution and why.
|
|
</para>
|
|
<para>
|
|
Example excerpt from the debug log (plugin decision):
|
|
<programlisting>
|
|
<![CDATA[
|
|
[...]
|
|
>mysqlnd_ms::query
|
|
| info : query=DROP TABLE IF EXISTS test
|
|
| >_mysqlnd_plugin_get_plugin_connection_data
|
|
| | info : plugin_id=5
|
|
| <_mysqlnd_plugin_get_plugin_connection_data
|
|
| >mysqlnd_ms_pick_server_ex
|
|
| | info : conn_data=0x7fb6a7d3e5a0 *conn_data=0x7fb6a7d410d0
|
|
| | >mysqlnd_ms_select_servers_all
|
|
| | <mysqlnd_ms_select_servers_all
|
|
| | >mysqlnd_ms_choose_connection_rr
|
|
| | | >mysqlnd_ms_query_is_select
|
|
[...]
|
|
| | | <mysqlnd_ms_query_is_select
|
|
[...]
|
|
| | | info : Init the master context
|
|
| | | info : list(0x7fb6a7d3f598) has 1
|
|
| | | info : Using master connection
|
|
| | | >mysqlnd_ms_advanced_connect
|
|
| | | | >mysqlnd_conn::connect
|
|
| | | | | info : host=localhost user=root db=test port=3306 flags=131072 persistent=0 state=0
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
In this case the statement <literal>DROP TABLE IF EXISTS test</literal> has been
|
|
executed. Note that the statement string is shown in the log file. You may want
|
|
to take measures to restrict access to the log for security considerations.
|
|
</para>
|
|
<para>
|
|
The statement has been load balanced using round robin policy,
|
|
as you can easily guess from the functions name <literal>>mysqlnd_ms_choose_connection_rr</literal>.
|
|
It has been sent to a master server running on
|
|
<literal>host=localhost user=root db=test port=3306 flags=131072 persistent=0 state=0</literal>.
|
|
</para>
|
|
</section>
|
|
|
|
<section xml:id="mysqlnd-ms.monitoring">
|
|
<title xmlns="http://docbook.org/ns/docbook">Monitoring</title>
|
|
<para>
|
|
Plugin activity can be monitored using the mysqlnd trace log,
|
|
mysqlnd statistics, mysqlnd_ms plugin statistics and external PHP debugging tools.
|
|
Use of the trace log should be limited to debugging. It is recommended
|
|
to use the plugins statistics for monitoring.
|
|
</para>
|
|
<para>
|
|
Writing a trace log is a slow operation. If using an external PHP debugging tool,
|
|
please refer to the vendors manual about its performance impact and the
|
|
type of information collected. In many cases, external debugging tools will
|
|
provide call stacks. Often, a call stack or a trace log is more difficult to interpret
|
|
than the statistics provided by the plugin.
|
|
</para>
|
|
<para>
|
|
Plugin statistics tell how often which kind of cluster node has been used (slave or master),
|
|
why the node was used, if lazy connections have been used and if global transaction
|
|
ID injection has been performed. The monitoring information provided enables
|
|
user to verify plugin decisions and to plan their cluster resources based on usage pattern.
|
|
The function <function>mysqlnd_ms_get_stats</function>
|
|
is used to access the statistics. Please, see the functions description for a list
|
|
of available statistics.
|
|
</para>
|
|
<para>
|
|
Statistics are collected on a per PHP process basis. Their scope is a PHP process.
|
|
Depending on the PHP deployment model a process may serve one or multiple web requests.
|
|
If using CGI model, a PHP process serves one web request. If using FastCGI or
|
|
pre-fork web server models, a PHP process usually serves multiple web requests.
|
|
The same is the case with a threaded web server. Please, note that threads running
|
|
in parallel can update the statistics in parallel. Thus, if using a threaded PHP
|
|
deployment model, statistics can be changed by more than one script at a time. A
|
|
script cannot rely on the fact that it sees only its own changes to statistics.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Verify plugin activity in a non-threaded deployment model</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
mysqlnd_ms.enable=1
|
|
mysqlnd_ms.collect_statistics=1
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/* Load balanced following "myapp" section rules from the plugins config file (not shown) */
|
|
$mysqli = new mysqli("myapp", "username", "password", "database");
|
|
if (mysqli_connect_errno())
|
|
/* Of course, your error handling is nicer... */
|
|
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
|
|
|
$stats_before = mysqlnd_ms_get_stats();
|
|
if ($res = $mysqli->query("SELECT 'Read request' FROM DUAL")) {
|
|
var_dump($res->fetch_all());
|
|
}
|
|
$stats_after = mysqlnd_ms_get_stats();
|
|
if ($stats_after['use_slave'] <= $stats_before['use_slave']) {
|
|
echo "According to the statistics the read request has not been run on a slave!";
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Statistics are aggregated for all plugin activities and all connections handled by
|
|
the plugin. It is not possible to tell how much a certain connection handle has
|
|
contributed to the overall statistics.
|
|
</para>
|
|
<para>
|
|
Utilizing PHPs <function>register_shutdown_function</function> function or the
|
|
<literal>auto_append_file</literal> PHP configuration directive it is
|
|
easily possible to dump statistics into, for example, a log file when a script
|
|
finishes. Instead of using a log file it is also possible to send the statistics
|
|
to an external monitoring tool for recording and display.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Recording statistics during shutdown</title>
|
|
<programlisting role="ini">
|
|
<![CDATA[
|
|
mysqlnd_ms.enable=1
|
|
mysqlnd_ms.collect_statistics=1
|
|
error_log=/tmp/php_errors.log
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function check_stats() {
|
|
$msg = str_repeat("-", 80) . "\n";
|
|
$msg .= var_export(mysqlnd_ms_get_stats(), true) . "\n";
|
|
$msg .= str_repeat("-", 80) . "\n";
|
|
error_log($msg);
|
|
}
|
|
register_shutdown_function("check_stats");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</section>
|
|
|
|
</chapter>
|
|
|
|
<!-- 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
|
|
-->
|