mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 00:48:54 +00:00
Initial set of documentation for PECL/mysqlnd_ms. PECL/mysqlnd_ms is a replication and load balancing plugin for the mysqlnd library. It has been added to PECL some eight months ago as an example of a mysqlnd plugin. Meanwhile it is more than example code but almost really useful. The PECL extension is in alpha state. An alpha release should follow soon.
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@310315 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
parent
cc40e134d2
commit
1d9e890195
12 changed files with 2651 additions and 0 deletions
211
reference/mysqlnd_ms/book.xml
Executable file
211
reference/mysqlnd_ms/book.xml
Executable file
|
@ -0,0 +1,211 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<book xml:id="book.mysqlnd-ms" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Mysqlnd replication and load balancing plugin</title>
|
||||
<titleabbrev>mysqlnd_ms</titleabbrev>
|
||||
|
||||
<preface xml:id="intro.mysqlnd-ms">
|
||||
&reftitle.intro;
|
||||
<para>
|
||||
The mysqlnd replication and load balancing plugin (<literal>mysqlnd_ms</literal>)
|
||||
adds easy to use MySQL replication support to all PHP MySQL extensions that use
|
||||
<link linkend="book.mysqlnd">mysqlnd</link>.
|
||||
</para>
|
||||
<para>
|
||||
As of version PHP 5.3.3 the MySQL native driver for PHP
|
||||
(<literal>mysqlnd</literal>)
|
||||
features an internal plugin C API. C plugins, such as the replication and
|
||||
load balancing plugin, can extend the functionality of
|
||||
<link linkend="book.mysqlnd">mysqlnd</link>.
|
||||
</para>
|
||||
<para>
|
||||
The MySQL native driver for PHP is a C library which ships together with
|
||||
PHP as of PHP 5.3.0. It serves as a drop-in replacement for the
|
||||
MySQL Client Library (AKA libmysql/libmysqlclient). Using mysqlnd has
|
||||
several advantages: no extra downloads because it comes with PHP,
|
||||
PHP license, lower memory consumption in certain cases,
|
||||
new functionality such as asynchronous queries.
|
||||
</para>
|
||||
<para>
|
||||
Mysqlnd plugins such as the replication and load balancing plugin operate
|
||||
mostly transparent from an user perspective. The replication and load balancing
|
||||
plugin supports all PHP applications
|
||||
and all PHP MySQL extensions (
|
||||
<link linkend="ref.mysqli">mysqli</link>,
|
||||
<link linkend="ref.mysql">mysql</link>,
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link>).
|
||||
It does not change existing APIs. Therefore, it can easily be used with
|
||||
existing PHP applications.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
The mysqlnd replication and load balancing plugin is in alpha status.
|
||||
It is not feature complete.
|
||||
</para>
|
||||
</note>
|
||||
<section xml:id="mysqlnd-ms.key_features">
|
||||
<title>Key Features</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Transparent and therefore easy to use
|
||||
</para>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
supports all PHP MySQL extensions
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
no API changes
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
very little, if any, application changes required, dependent on the usage scenario required
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Featured read-write split strategies
|
||||
</para>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Automatic detection of SELECT, supports SQL hints to overrule automatism
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
user-defined
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Featured load balancing strategies
|
||||
</para>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Round Robin: choose different slave in round robin fashion for every slave request.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Random: choose random slave for every slave request.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Random once (sticky): choose random slave once to run all slave requests for the duration of a web request.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
User-defined. The application can register callbacks with mysqlnd_ms.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.limitations">
|
||||
<title>Limitations</title>
|
||||
<para>
|
||||
The plugin does not support MySQL replication setups with more
|
||||
than one master server.
|
||||
</para>
|
||||
<para>
|
||||
The built-in read/write-split mechanism is very basic. Every
|
||||
query which starts with <literal>SELECT</literal>
|
||||
is considered a read request to be sent to a MySQL slave server.
|
||||
All other queries, including, for example, <literal>SHOW</literal>
|
||||
statements, are considered as write requests to be sent to the MySQL master server.
|
||||
The build-in behaviour can be overruled using
|
||||
<link linkend="mysqlnd-ms.constants">SQL hints</link> or an user-defined
|
||||
<link linkend="function.mysqlnd-ms-set-user-pick-server">callback function</link>.
|
||||
</para>
|
||||
<para>
|
||||
The read/write splitter is not aware of multi-statements. Multi-statements
|
||||
are considered as one statement. The decision of where to run the statement
|
||||
will be based on the beginning of the statement string.
|
||||
</para>
|
||||
<para>
|
||||
The plugin does not support native prepared statements. Please
|
||||
note that <link linkend="ref.pdo-mysql">PDO_MySQL</link> is using a
|
||||
client-side prepared statement emulation by default. Client-side emulated
|
||||
prepared statements are fully supported by the replication and load balancing
|
||||
plugin because the emulation is not using native prepared statements.
|
||||
If you are using PHP based database abstraction, please consult the
|
||||
vendor manual to learn if a client-side prepared statement emulation is
|
||||
used.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Application must be aware of the consequences of connection switches performed
|
||||
for load balancing purpose. Please check the documentation on
|
||||
<link linkend="mysqlnd-ms.pooling">connection pooling and switching</link>,
|
||||
<link linkend="mysqlnd-ms.transaction">transaction handling</link>,
|
||||
<link linkend="mysqlnd-ms.failover">failover</link>
|
||||
<link linkend="mysqlnd-ms.loadbalancing">load balancing</link> and
|
||||
<link linkend="mysqlnd-ms.rwsplit">read-write splitting</link> carefully.
|
||||
</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.name">
|
||||
<title>On the name</title>
|
||||
<para>
|
||||
The shortcut <literal>mysqlnd_ms</literal>
|
||||
stands for <literal>mysqlnd master slave plugin</literal>. The name
|
||||
was choosen for a quick-and-dirty proof-of-concept. In the beginning
|
||||
the developers did not expect to continue using the code base.
|
||||
</para>
|
||||
</section>
|
||||
</preface>
|
||||
|
||||
&reference.mysqlnd-ms.quickstart;
|
||||
&reference.mysqlnd-ms.concepts;
|
||||
&reference.mysqlnd-ms.setup;
|
||||
&reference.mysqlnd-ms.constants;
|
||||
&reference.mysqlnd-ms.reference;
|
||||
|
||||
</book>
|
||||
|
||||
<!-- 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
|
||||
-->
|
302
reference/mysqlnd_ms/concepts.xml
Executable file
302
reference/mysqlnd_ms/concepts.xml
Executable file
|
@ -0,0 +1,302 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<chapter xml:id="mysqlnd-ms.concepts" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Concepts</title>
|
||||
<section xml:id="mysqlnd-ms.architecture">
|
||||
<title>Architecture</title>
|
||||
<para>
|
||||
The mysqlnd replication and load balancing plugin is
|
||||
implemented as a PHP extension.
|
||||
It is written in C and operates under the hood of PHP. During the
|
||||
startup of the PHP interpreter, in the module init phase of the
|
||||
PHP engine, it gets registered as a
|
||||
<link linkend="book.mysqlnd">mysqlnd</link> plugin to replace selected
|
||||
mysqlnd C methods.
|
||||
</para>
|
||||
<para>
|
||||
At PHP run time it inspects queries send from
|
||||
mysqlnd (PHP) to the MySQL server. If a query is recognized as read-only
|
||||
it will be sent to one of the configured slave servers. Statements are
|
||||
considered read-only if they either start with <literal>SELECT</literal>,
|
||||
the SQL hint <literal>/*ms=slave*/</literal> or a slave had been choose for
|
||||
running the previous query and the query starts with the SQL hint
|
||||
<literal>/*ms=last_used*/</literal>. In all other cases the query will
|
||||
be sent to the MySQL replication master server.
|
||||
</para>
|
||||
<para>
|
||||
The plugin takes care internally of opening and closing the database connections
|
||||
to the master server and the slave servers. From an application
|
||||
point of view there continues to be only one connection handle. However,
|
||||
internally, this one public connection handle represents a pool of
|
||||
internal connections managed by the plugin. The plugin proxies queries
|
||||
to the master server and the slave ones using multiple connections.
|
||||
</para>
|
||||
<para>
|
||||
Database connections have a state consisting, for example, transaction
|
||||
status, transaction settings, character set settings, temporary tables.
|
||||
The plugin will try to maintain the same state among all internal
|
||||
connections, whenever this can be done in an automatic and transparent way.
|
||||
In cases where it is not easily possible to maintain state among all
|
||||
connections, such as when using <literal>BEGIN TRANSACTION</literal>, the
|
||||
plugin leaves it to the user to handle. Please, find further details below.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.pooling">
|
||||
<title>Connection pooling and switching</title>
|
||||
<para>
|
||||
The replication and load balancing plugin changes the semantics of a PHP
|
||||
MySQL connection handle. The existing API of the PHP MySQL extensions
|
||||
(<link linkend="ref.mysqli">mysqli</link>,
|
||||
<link linkend="ref.mysql">mysql</link>,
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link>) are not changed in
|
||||
a way that functions are added or removed. But their behaviour
|
||||
changes when using the plugin. Existing applications do not need to
|
||||
be adapted to a new API. But they may need to be modified because of
|
||||
the behaviour changes.
|
||||
</para>
|
||||
<para>
|
||||
The plugin breaks the one-by-one relationship between a
|
||||
<link linkend="ref.mysqli">mysqli</link>,
|
||||
<link linkend="ref.mysql">mysql</link>,
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link> connection
|
||||
handle and a MySQL wire connection. If using the plugin a
|
||||
<link linkend="ref.mysqli">mysqli</link>,
|
||||
<link linkend="ref.mysql">mysql</link>,
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link> connection
|
||||
handle represents a local pool of connections to the configured
|
||||
MySQL replication master and the MySQL replication slave servers.
|
||||
The plugin redirects queries to the master and slave servers.
|
||||
At some point in time one and the same PHP connection handle
|
||||
may point to the MySQL master server. Later on, it may point
|
||||
to one of the slave servers or still the master. Manipulating
|
||||
and replacing the wire connection referenced by a PHP MySQL
|
||||
connection handle is not a transparent operation.
|
||||
</para>
|
||||
<para>
|
||||
Every MySQL connection has a state. The state of the connections in
|
||||
the connection pool of the plugin can differ. Whenever the
|
||||
plugin switches from one wire connection to another, the current state of
|
||||
the user connection may change. The applications must be aware of this.
|
||||
</para>
|
||||
<para>
|
||||
The following listshows what the connection state consists of.
|
||||
</para>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Transaction status
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Temporary tables
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Table locks
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Session system variables and session user variables
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Session system variables and session user variables
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Prepared statements
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>HANDLER</literal> variables
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Locks acquired with <literal>GET_LOCK()</literal>
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
The plugins philosophy is to align the state of connections in the
|
||||
pool only if the state is under full control of the plugin, or if it is
|
||||
necessary for security reasons. Just a few actions that change the
|
||||
state of the connection fall into this category. The plugin does broadcast
|
||||
the following state changing client calls to all currently open
|
||||
connections in the connection pool: <literal>change_user</literal>,
|
||||
<literal>select_db</literal>, <literal>set_charset</literal>,
|
||||
<literal>set_server_option</literal>, <literal>set_client_option</literal>,
|
||||
<literal>autocommit</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The plugin does not proxy or
|
||||
<quote>remember</quote> settings to apply them on connections
|
||||
opened in the future. This is important to remember, if
|
||||
using
|
||||
<link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link>.
|
||||
Lazy connections are connections which are not
|
||||
opened before the client sends the first connection.
|
||||
Use of lazy connections is the default plugin action.
|
||||
</para>
|
||||
<para>
|
||||
Connection switches happen right before queries are run. The plugin does
|
||||
not switch the current connection until the moment in time when
|
||||
the next statement is executed.
|
||||
</para>
|
||||
<para>
|
||||
Please, do not miss the MySQL reference manual chapter on
|
||||
replication features and issues. Some restrictions you hit may not be related
|
||||
to the PHP plugin but are properties of the MySQL replication system.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.transaction">
|
||||
<title>Transaction handling</title>
|
||||
<para>
|
||||
Transaction handling is fundamentally changed.
|
||||
A SQL transaction is a unit of work run on one database server. The
|
||||
unit of work consists of one or more SQL statements.
|
||||
</para>
|
||||
<para>
|
||||
By default the plugin is not aware of SQL transactions. The plugin may
|
||||
switch connections for load balancing at any point in time. Connection
|
||||
switches may happen in the middle of a transaction. This is against the
|
||||
nature of a SQL transaction. By default the plugin is not transaction safe.
|
||||
</para>
|
||||
<para>
|
||||
At the time of writing, applications using SQL transactions together with
|
||||
the plugin must use SQL hints to disable connection switches in the middle
|
||||
of a SQL transaction. Please, find details in the examples section.
|
||||
</para>
|
||||
<para>
|
||||
Future versions of the plugin might offer special settings to make
|
||||
plugin transaction safe.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.failover">
|
||||
<title>Failover</title>
|
||||
<para>
|
||||
Connection failover handling is left to the user. The application is responsible
|
||||
for checking return values of the database functions it calls and reacting
|
||||
to possible errors. If, for example, the plugin recognizes a query as a read-only
|
||||
query to be sent to the slave servers and the slave server selected by the
|
||||
plugin is not available, the plugin will raise an error after not executing
|
||||
the statement.
|
||||
</para>
|
||||
<para>
|
||||
It is up to
|
||||
the application to handle the error and, if need be, re-issue the query to
|
||||
trigger selection of another slave server for statement execution. The plugin
|
||||
will make no attempts to failover automatically because the plugin
|
||||
cannot ensure that an automatic failover will not change the state of
|
||||
the connection. For example, the application may have issued a query
|
||||
which depends on SQL user variables which are bound to a specific connection.
|
||||
Such a query might return wrong results if the plugin would switch the
|
||||
connection implicitly as part of automatic failover. To ensure correct
|
||||
results the application must take care of the failover and rebuild
|
||||
the required connection state. Therefore, by default, no automatic failover
|
||||
is done by the plugin.
|
||||
</para>
|
||||
<para>
|
||||
An user who does not change the connection state after opening a connection
|
||||
may activate automatic master failover.
|
||||
</para>
|
||||
<para>
|
||||
The failover policy is configured in the plugins configuration file by help
|
||||
of the
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.failover">failover</link></literal>
|
||||
configuration directive.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.loadbalancing">
|
||||
<title>Load balancing</title>
|
||||
<para>
|
||||
Four load balancing strategies are supported to distribute read-only
|
||||
statements over the configured MySQL slave servers:
|
||||
<literal>random</literal>, <literal>random_once</literal> (default),
|
||||
<literal>roundrobin</literal>, <literal>user</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The load balancing policy is configured in the plugins configuration
|
||||
file using the
|
||||
<link linkend="ini.mysqlnd-ms-plugin-config.pick">pick[]</link>
|
||||
configuration directive.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="mysqlnd-ms.rwsplit">
|
||||
<title>Read-write splitting</title>
|
||||
<para>
|
||||
The plugin runs read-only statements on the configured MySQL slaves and
|
||||
all other queries on the MySQL master. Statements are
|
||||
considered read-only if they either start with <literal>SELECT</literal>,
|
||||
the SQL hint <literal>/*ms=slave*/</literal> or a slave had been chosen for
|
||||
running the previous query and the query starts with the SQL hint
|
||||
<literal>/*ms=last_used*/</literal>. In all other cases the query will
|
||||
be send to the MySQL replication master server.
|
||||
</para>
|
||||
<para>
|
||||
SQL hints are a special kind of standard compliant SQL comments. The plugin
|
||||
does check every statement for certain SQL hints. The SQL hints are described
|
||||
together with the <link linkend="mysqlnd-ms.constants">constants</link>
|
||||
exported by the extension. Other systems
|
||||
involved in the statement processing, such as the MySQL server, SQL firewalls
|
||||
or SQL proxies are unaffected by the SQL hints because those systems are
|
||||
supposed to ignore SQL comments.
|
||||
</para>
|
||||
<para>
|
||||
The built-in read-write splitter can be replaced by a user-defined one, see also
|
||||
<function>mysqlnd_ms_set_user_pick_server</function>.
|
||||
</para>
|
||||
<para>
|
||||
A user-defined read-write splitter can ask the built-in logic to make
|
||||
a proposal where to sent a statement by invoking
|
||||
<function>mysqlnd_ms_is_select</function>.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
The built-in read-write splitter is not aware of multi-statements.
|
||||
Multi-statements are seen as one statement. The splitter will check the
|
||||
beginning of the statement to decide where to run the statement. If, for example,
|
||||
a multi-statement begins with
|
||||
<literal>SELECT 1 FROM DUAL; INSERT INTO test(id) VALUES (1); ...</literal>
|
||||
the plugin will run it on a slave although the statement is not read-only.
|
||||
</para>
|
||||
</note>
|
||||
</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
|
||||
-->
|
49
reference/mysqlnd_ms/configure.xml
Executable file
49
reference/mysqlnd_ms/configure.xml
Executable file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<section xml:id="mysqlnd-ms.installation" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
&reftitle.install;
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The mysqlnd replication and load balancing plugin is in alpha status.
|
||||
It is not feature complete.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
&pecl.moved;
|
||||
</para>
|
||||
|
||||
<para>
|
||||
&pecl.info;
|
||||
<link xlink:href="&url.pecl.package;mysqlnd_ms">&url.pecl.package;mysqlnd_ms</link>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
&pecl.windows.download;
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<!-- 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
|
||||
-->
|
246
reference/mysqlnd_ms/constants.xml
Executable file
246
reference/mysqlnd_ms/constants.xml
Executable file
|
@ -0,0 +1,246 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<appendix xml:id="mysqlnd-ms.constants" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
&reftitle.constants;
|
||||
&extension.constants;
|
||||
|
||||
<para>
|
||||
<emphasis role="bold">SQL hint related</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<para>
|
||||
The mysqlnd replication and load balancing plugin (<literal>mysqlnd_ms</literal>)
|
||||
does read/write splitting to direct write queries to a MySQL master server and
|
||||
read-only queries to MySQL slave servers in a MySQL replication setup.
|
||||
The plugin has a built-in read/write split logic. The logic is very basic.
|
||||
All queries which start with <literal>SELECT</literal> are considered read-only
|
||||
queries which shall be send to a MySQL slave server listed in
|
||||
the plugin configuration file. All other queries shall be directed to the
|
||||
MySQL master server specified in the plugin configuration file.
|
||||
</para>
|
||||
<para>
|
||||
User supplied SQL hints can be used to overrule automatic read/write splitting
|
||||
to gain full control on the process. SQL hints are standards compliant
|
||||
SQL comments. The plugin will scan the beginning of a query string for
|
||||
a SQL comment with certain contents which control query redirection.
|
||||
Other systems involved in the query processing are unaffected by the
|
||||
plugins SQL hints because other systems will ignore the SQL comments.
|
||||
</para>
|
||||
<para>
|
||||
The plugin supports three SQL hints to direct queries to the MySQL slave
|
||||
servers, the MySQL master server and the last used MySQL server. SQL hints
|
||||
must be placed at the beginning to be recognized by the plugin.
|
||||
</para>
|
||||
<para>
|
||||
It is recommended to use the string constants
|
||||
<constant>MYSQLND_MS_MASTER_SWITCH</constant>,
|
||||
<constant>MYSQLND_MS_SLAVE_SWITCH</constant> and
|
||||
<constant>MYSQLND_MS_LAST_USED_SWITCH</constant> instead of their literal
|
||||
values for better portability.
|
||||
</para>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
/* Use constants for maximum portability */
|
||||
$master_query = "/*" . MYSQLND_MS_MASTER_SWITCH . "*/SELECT id FROM test";
|
||||
|
||||
/* Valid but less portable: using literal instad of constant */
|
||||
$slave_query = "/*ms=slave*/SHOW TABLES";
|
||||
|
||||
printf("master_query = '%s'\n", $master_query);
|
||||
printf("slave_query = '%s'\n", $slave_query);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&examples.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
master_query = /*ms=master*/SELECT id FROM test
|
||||
slave_query = /*ms=slave*/SHOW TABLES
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_MASTER_SWITCH</constant>
|
||||
(<type>string</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
SQL hint used to send a query to the MySQL replication master server.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_SLAVE_SWITCH</constant>
|
||||
(<type>string</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
SQL hint used to send a query to one of the MySQL replication slave servers.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_LAST_USED_SWITCH</constant>
|
||||
(<type>string</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
SQL hint used to send a query to the last used MySQL server. The last
|
||||
used MySQL server can either be a master or a slave server in a
|
||||
MySQL replication setup.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>mysqlnd_ms_is_select</function> related
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_QUERY_USE_MASTER</constant>
|
||||
(<type>integer</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
If <function>mysqlnd_ms_is_select</function> returns
|
||||
<constant>MYSQLND_MS_QUERY_USE_MASTER</constant> for a given query, the
|
||||
built-in read/write split mechanism recommends sending the query to
|
||||
a MySQL replication master server.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_QUERY_USE_SLAVE</constant>
|
||||
(<type>integer</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
If <function>mysqlnd_ms_is_select</function> returns
|
||||
<constant>MYSQLND_MS_QUERY_USE_SLAVE</constant> for a given query, the
|
||||
built-in read/write split mechanism recommends sending the query to
|
||||
a MySQL replication slave server.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_QUERY_USE_LAST_USED</constant>
|
||||
(<type>integer</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
If <function>mysqlnd_ms_is_select</function> returns
|
||||
<constant>MYSQLND_MS_QUERY_USE_LAST_USED</constant> for a given query, the
|
||||
built-in read/write split mechanism recommends sending the query to
|
||||
the last used server.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<emphasis role="bold">Other</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
The plugins version number can be obtained using
|
||||
<constant>MYSQLND_MS_VERSION</constant> or
|
||||
<constant>MYSQLND_MS_VERSION_ID</constant>.
|
||||
<constant>MYSQLND_MS_VERSION</constant>
|
||||
is the string representation of the numerical version number
|
||||
<constant>MYSQLND_MS_VERSION_ID</constant>, which is an integer such as 10000.
|
||||
Developers can calculate the version number as follows.
|
||||
</para>
|
||||
<para>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Version (part)</entry>
|
||||
<entry>Example</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Major*10000</entry>
|
||||
<entry>1*10000 = 10000</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Minor*100</entry>
|
||||
<entry>0*100 = 0</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Patch</entry>
|
||||
<entry>0 = 0</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>MYSQLND_MS_VERSION_ID</entry>
|
||||
<entry>10000</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_VERSION</constant>
|
||||
(<type>string</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Plugin version string, for example, <quote>1.0.0-prototype</quote>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<constant>MYSQLND_MS_VERSION_ID</constant>
|
||||
(<type>integer</type>)
|
||||
</term>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Plugin version number, for example, 10000.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
</appendix>
|
||||
|
||||
<!-- 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
|
||||
-->
|
345
reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml
Executable file
345
reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml
Executable file
|
@ -0,0 +1,345 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<refentry xml:id="function.mysqlnd-ms-get-stats" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refnamediv>
|
||||
<refname>mysqlnd_ms_get_stats</refname>
|
||||
<refpurpose>Returns query distribution and connection statistics</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1 role="description">
|
||||
&reftitle.description;
|
||||
<methodsynopsis>
|
||||
<type>array</type>
|
||||
<methodname>mysqlnd_ms_get-stats</methodname>
|
||||
<void />
|
||||
</methodsynopsis>
|
||||
<para>
|
||||
Returns an array of statistics collected by the replication
|
||||
and load balancing plugin.
|
||||
</para>
|
||||
<para>
|
||||
The PHP configuration setting
|
||||
<literal><link linkend="ini.mysqlnd-ms.collect_statistics">mysqlnd_ms.collect_statistics</link></literal>
|
||||
controls the collection of statistics. The collection of statistics
|
||||
is disabled by default for performance reasons.
|
||||
</para>
|
||||
<para>
|
||||
The scope of the statistics is the
|
||||
<literal>PHP</literal> process.
|
||||
Depending on your deployment model a
|
||||
<literal>PHP</literal> process may handle one or multiple requests.
|
||||
</para>
|
||||
<para>
|
||||
Statistics are aggregated for connections. It is not possible
|
||||
to tell how much queries originating from
|
||||
<literal>mysqli</literal>,
|
||||
<literal>PDO_MySQL</literal> or
|
||||
<literal>mysql</literal> API calls have
|
||||
contributed to the aggregated data values.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="parameters">
|
||||
&reftitle.parameters;
|
||||
&no.function.parameters;
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="returnvalues">
|
||||
&reftitle.returnvalues;
|
||||
<para>
|
||||
Returns <literal>NULL</literal> if the
|
||||
the PHP configuration directive
|
||||
<link linkend="ini.mysqlnd-ms.enable"><literal>mysqlnd_ms.enable</literal></link>
|
||||
has disabled the plugin. Otherwise, returns array of statistics.
|
||||
</para>
|
||||
<para>
|
||||
Array of statistics
|
||||
</para>
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<colspec colwidth="10%"/>
|
||||
<colspec colwidth="70%"/>
|
||||
<colspec colwidth="20%"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Statistic</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Version</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_slave</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements considered as read-only by the built-in query analyzer.
|
||||
Neither statements which begin with a SQL hint to force
|
||||
use of slave nor statements directed to a slave by an user-defined
|
||||
callback are included. The total number of statements sent to the slaves is
|
||||
<literal>use_slave</literal> + <literal>use_slave_sql_hint</literal> +
|
||||
<literal>use_slave_callback</literal>.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_master</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements not considered as read-only by the built-in query analyzer.
|
||||
Neither statements which begin with a SQL hint to force
|
||||
use of master nor statements directed to a master by an user-defined
|
||||
callback are included. The total number of statements sent to the master is
|
||||
<literal>use_master</literal> + <literal>use_master_sql_hint</literal> +
|
||||
<literal>use_master_callback</literal>.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_slave_sql_hint</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements sent to a slave because statement begins with
|
||||
the SQL hint to force use of slave.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_master_sql_hint</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements sent to a master because statement begins with
|
||||
the SQL hint to force use of master.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_last_used_sql_hint</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements sent to server which has run the previous statement,
|
||||
because statement begins with the SQL hint to force use of previously
|
||||
used server.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_slave_callback</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements sent to a slave because an user-defined callback
|
||||
has chosen a slave server for statement execution.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>use_master_callback</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of statements sent to a master because an user-defined callback
|
||||
has chosen a master server for statement execution.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>non_lazy_connections_slave_success</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of successfully opened slave connections from
|
||||
configurations not using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
The total number of successfully opened slave connections
|
||||
is <literal>non_lazy_connections_slave_success</literal> +
|
||||
<literal>lazy_connections_slave_success</literal>
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>non_lazy_connections_slave_failed</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of failed slave connection attempts from
|
||||
configurations not using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
The total number of failed slave connection attempts
|
||||
is <literal>non_lazy_connections_slave_failed</literal> +
|
||||
<literal>lazy_connections_slave_failed</literal>
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>non_lazy_connections_master_success</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of successfully opened master connections from
|
||||
configurations not using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
The total number of successfully opened master connections
|
||||
is <literal>non_lazy_connections_master_success</literal> +
|
||||
<literal>lazy_connections_master_success</literal>
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>non_lazy_connections_master_failed</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of failed master connection attempts from
|
||||
configurations not using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
The total number of failed master connection attempts
|
||||
is <literal>non_lazy_connections_master_failed</literal> +
|
||||
<literal>lazy_connections_master_failed</literal>
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>lazy_connections_slave_success</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of successfully opened slave connections from
|
||||
configurations using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>lazy_connections_slave_failed</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of failed slave connection attempts from
|
||||
configurations using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>lazy_connections_master_success</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of successfully opened master connections from
|
||||
configurations using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<literal>lazy_connections_master_failed</literal>
|
||||
</entry>
|
||||
<entry>
|
||||
Number of failed master connection attempts from
|
||||
configurations using
|
||||
<literal><link linkend="ini.mysqlnd-ms-plugin-config.lazy_connections">lazy connections</link></literal>.
|
||||
</entry>
|
||||
<entry>Since 1.0.0.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="examples">
|
||||
&reftitle.examples;
|
||||
<para>
|
||||
<example>
|
||||
<title><function>mysqlnd_ms_get_stats</function> example</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
printf("mysqlnd_ms.collect_statistics = %d\n", ini_get("mysqlnd_ms.collect_statistics"));
|
||||
var_dump(mysqlnd_ms_get_stats());
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
mysqlnd_ms.collect_statistics = 0
|
||||
array(13) {
|
||||
["use_slave"]=>
|
||||
string(1) "0"
|
||||
["use_master"]=>
|
||||
string(1) "0"
|
||||
["use_slave_forced"]=>
|
||||
string(1) "0"
|
||||
["use_master_forced"]=>
|
||||
string(1) "0"
|
||||
["use_last_used_forced"]=>
|
||||
string(1) "0"
|
||||
["non_lazy_connections_slave_success"]=>
|
||||
string(1) "0"
|
||||
["non_lazy_connections_slave_failure"]=>
|
||||
string(1) "0"
|
||||
["non_lazy_connections_master_success"]=>
|
||||
string(1) "0"
|
||||
["non_lazy_connections_master_failure"]=>
|
||||
string(1) "0"
|
||||
["lazy_connections_slave_success"]=>
|
||||
string(1) "0"
|
||||
["lazy_connections_slave_failure"]=>
|
||||
string(1) "0"
|
||||
["lazy_connections_master_success"]=>
|
||||
string(1) "0"
|
||||
["lazy_connections_master_failure"]=>
|
||||
string(1) "0"
|
||||
}
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="seealso">
|
||||
&reftitle.seealso;
|
||||
<para>
|
||||
<simplelist>
|
||||
<member>
|
||||
<link linkend="mysqlnd-ms.configuration">Runtime configuration</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="ini.mysqlnd-ms.collect_statistics">mysqlnd_ms.collect_statistics</link>
|
||||
</member>
|
||||
<member>
|
||||
<link linkend="ini.mysqlnd-ms.enable">mysqlnd_ms.enable</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:t
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
indent-tabs-mode:nil
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:nil
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||||
vim: et tw=78 syn=sgml
|
||||
vi: ts=1 sw=1
|
||||
-->
|
139
reference/mysqlnd_ms/functions/mysqlnd-ms-query-is-select.xml
Executable file
139
reference/mysqlnd_ms/functions/mysqlnd-ms-query-is-select.xml
Executable file
|
@ -0,0 +1,139 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<refentry xml:id="function.mysqlnd-ms-query-is-select" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refnamediv>
|
||||
<refname>mysqlnd_ms_query_is_select</refname>
|
||||
<refpurpose>Find whether to send the query to the master, the slave or the last used MySQL server</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1 role="description">
|
||||
&reftitle.description;
|
||||
<methodsynopsis>
|
||||
<type>int</type>
|
||||
<methodname>mysqlnd_ms_query_is_select</methodname>
|
||||
<methodparam><type>string</type><parameter>query</parameter></methodparam>
|
||||
</methodsynopsis>
|
||||
<para>
|
||||
Finds whether to send the query to the master, the slave or the
|
||||
last used MySQL server.
|
||||
</para>
|
||||
<para>
|
||||
The plugins built-in read/write split mechanism
|
||||
will be used to analyze the query string to make a recommendation where
|
||||
to send the query. The built-in read/write split mechanism is very
|
||||
basic and simple. The plugin will recommend sending all queries to the
|
||||
MySQL replication master server but those which begin with
|
||||
<literal>SELECT</literal>, or begin with a SQL hint which
|
||||
enforces sending the query to a slave server. Due to the basic
|
||||
but fast algorithm the plugin may propose to run some read-only
|
||||
statements such as <literal>SHOW TABLES</literal> on the replication master.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="parameters">
|
||||
&reftitle.parameters;
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>query</parameter></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Query string to test.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="returnvalues">
|
||||
&reftitle.returnvalues;
|
||||
<para>
|
||||
A return value of <constant>MYSQLND_MS_QUERY_USE_MASTER</constant>
|
||||
indicates that the query should be send to the MySQL replication
|
||||
master server. The function returns a value of
|
||||
<constant>MYSQLND_MS_QUERY_USE_SLAVE</constant> if the query can be run
|
||||
on a slave because it is considered read-only. A value of
|
||||
<constant>MYSQLND_MS_QUERY_USE_LAST_USED</constant> is returned to recommend
|
||||
running the query on the last used server. This can either be a MySQL
|
||||
replication master server or a MySQL replication slave server.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="examples">
|
||||
&reftitle.examples;
|
||||
<para>
|
||||
<example>
|
||||
<title><function>mysqlnd_ms_query_is_select</function> example</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function is_select($query)
|
||||
{
|
||||
switch (mysqlnd_ms_query_is_select($query))
|
||||
{
|
||||
case MYSQLND_MS_QUERY_USE_MASTER:
|
||||
printf("'%s' should be run on the master.\n", $query);
|
||||
break;
|
||||
case MYSQLND_MS_QUERY_USE_SLAVE:
|
||||
printf("'%s' should be run on a slave.\n", $query);
|
||||
break;
|
||||
case MYSQLND_MS_QUERY_USE_LAST_USED:
|
||||
printf("'%s' should be run on the server that has run the previous query\n", $query);
|
||||
break;
|
||||
default:
|
||||
printf("No suggestion where to run the '%s', fallback to master recommended\n", $query);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
is_select("INSERT INTO test(id) VALUES (1)");
|
||||
is_select("SELECT 1 FROM DUAL");
|
||||
is_select("/*" . MYSQLND_MS_LAST_USED_SWITCH . "*/SELECT 2 FROM DUAL");
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
INSERT INTO test(id) VALUES (1) should be run on the master.
|
||||
SELECT 1 FROM DUAL should be run on a slave.
|
||||
/*ms=last_used*/SELECT 2 FROM DUAL should be run on the server that has run the previous query
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="seealso">
|
||||
&reftitle.seealso;
|
||||
<para>
|
||||
<simplelist>
|
||||
<member>
|
||||
<link linkend="mysqlnd-ms.constants">Predefined Constants</link>
|
||||
</member>
|
||||
</simplelist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:t
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
indent-tabs-mode:nil
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:nil
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||||
vim: et tw=78 syn=sgml
|
||||
vi: ts=1 sw=1
|
||||
-->
|
228
reference/mysqlnd_ms/functions/mysqlnd-ms-set-user-pick-server.xml
Executable file
228
reference/mysqlnd_ms/functions/mysqlnd-ms-set-user-pick-server.xml
Executable file
|
@ -0,0 +1,228 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<refentry xml:id="function.mysqlnd-ms-set-user-pick-server" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refnamediv>
|
||||
<refname>mysqlnd_ms_set_user_pick_server</refname>
|
||||
<refpurpose>Sets a callback for user-defined read/write splitting</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1 role="description">
|
||||
&reftitle.description;
|
||||
<methodsynopsis>
|
||||
<type>bool</type>
|
||||
<methodname>mysqlnd_ms_set_user_pick_server</methodname>
|
||||
<methodparam><type>string</type><parameter>function</parameter></methodparam>
|
||||
</methodsynopsis>
|
||||
<para>
|
||||
Sets a callback for user-defined read/write splitting. The plugin will
|
||||
call the callback only if <literal>pick[]=user</literal> is the default
|
||||
rule for server picking in the relevant section of the plugins configuration
|
||||
file.
|
||||
</para>
|
||||
<para>
|
||||
The plugins built-in read/write query split mechanism decisions can be
|
||||
overwritten in two ways. The easiest way is to prepend the query string
|
||||
with the SQL hints <constant>MYSQLND_MS_MASTER_SWITCH</constant>,
|
||||
<constant>MYSQLND_MS_SLAVE_SWITCH</constant> or
|
||||
<constant>MYSQLND_MS_LAST_USED_SWITCH</constant>. Using SQL hints one can
|
||||
control, for example, whether a query shall be send to the MySQL replication
|
||||
master server or one of the slave servers. By help of SQL hints it is
|
||||
not possible to pick a certain slave server for query execution.
|
||||
</para>
|
||||
<para>
|
||||
Full control on server selection can be gained using a callback function.
|
||||
Use of a callback is recommended to expert users only because the callback
|
||||
has to cover all cases otherwise handled by the plugin.
|
||||
</para>
|
||||
<para>
|
||||
The plugin will invoke the callback function for selecting a server from the
|
||||
lists of configured master and slave servers. The callback function
|
||||
inspects the query to run and picks a server for query execution by returning
|
||||
the hosts URI, as found in the master and slave list.
|
||||
</para>
|
||||
<para>
|
||||
If the lazy connections are enabled and the callback choses a slave server for
|
||||
which no connection has been established so far and establishing the connection
|
||||
to the slave fails, the plugin will return an error upon the next action
|
||||
on the failed connection, for example, when running a query. It is the
|
||||
responsibility of the application developer to handle the error. For example,
|
||||
the application can re-run the query to trigger a new server selection and
|
||||
callback invocation. If so, the callback must make sure to select
|
||||
a different slave, or check slave availability, before returning to
|
||||
the plugin to prevent an endless loop.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="parameters">
|
||||
&reftitle.parameters;
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>function</parameter></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The function to be called. Class methods may also be invoked
|
||||
statically using this function by passing
|
||||
<literal>array($classname, $methodname)</literal> to this parameter.
|
||||
Additionally class methods of an object instance may be called by passing
|
||||
<literal>array($objectinstance, $methodname)</literal> to this parameter.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="returnvalues">
|
||||
&reftitle.returnvalues;
|
||||
<para>
|
||||
Host to run the query on. The host URI is to be taken from the
|
||||
master and slave connection lists passed to the callback function.
|
||||
If callback returns a value neither found in the master nor in the slave
|
||||
connection lists the plugin will fallback to the second pick method configured
|
||||
via the <literal>pick[]</literal> setting in the plugin configuration file.
|
||||
If not second pick method is given, the plugin falls back to the build-in
|
||||
default pick method for server selection.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="examples">
|
||||
&reftitle.examples;
|
||||
<para>
|
||||
<example>
|
||||
<title><function>mysqlnd_ms_set_user_pick_server</function> example</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[] = localhost
|
||||
slave[] = 192.168.2.27:3306
|
||||
slave[] = 192.168.78.136:3306
|
||||
pick[] = user
|
||||
]]>
|
||||
</programlisting>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
|
||||
function pick_server($connected, $query, $master, $slaves, $last_used)
|
||||
{
|
||||
static $slave_idx = 0;
|
||||
static $num_slaves = NULL;
|
||||
if (is_null($num_slaves))
|
||||
$num_slaves = count($slaves);
|
||||
|
||||
/* default: fallback to the plugins build-in logic */
|
||||
$ret = NULL;
|
||||
|
||||
printf("User has connected to '%s'...\n", $connected);
|
||||
printf("... deciding where to run '%s'\n", $query);
|
||||
|
||||
$where = mysqlnd_ms_query_is_select($query);
|
||||
switch ($where)
|
||||
{
|
||||
case MYSQLND_MS_QUERY_USE_MASTER:
|
||||
printf("... using master\n");
|
||||
$ret = $master[0];
|
||||
break;
|
||||
case MYSQLND_MS_QUERY_USE_SLAVE:
|
||||
/* SELECT or SQL hint for using slave */
|
||||
if (stristr($query, "FROM table_on_slave_a_only"))
|
||||
{
|
||||
/* a table which is only on the first configured slave */
|
||||
printf("... access to table available only on slave A detected\n");
|
||||
$ret = $slaves[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* round robin */
|
||||
printf("... some read-only query for a slave\n");
|
||||
$ret = $slaves[$slave_idx++ % $num_slaves];
|
||||
}
|
||||
break;
|
||||
case MYSQLND_MS_QUERY_LAST_USED:
|
||||
printf("... using last used server\n");
|
||||
$ret = $last_used;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("... ret = '%s'\n", $ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
mysqlnd_ms_set_user_pick_server("pick_server");
|
||||
|
||||
$mysqli = new mysqli("myapp", "root", "root", "test");
|
||||
|
||||
if (!($res = $mysqli->query("SELECT 1 FROM DUAL")))
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
else
|
||||
$res->close();
|
||||
|
||||
if (!($res = $mysqli->query("SELECT 2 FROM DUAL")))
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
else
|
||||
$res->close();
|
||||
|
||||
|
||||
if (!($res = $mysqli->query("SELECT * FROM table_on_slave_a_only")))
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
else
|
||||
$res->close();
|
||||
|
||||
$mysqli->close();
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
User has connected to 'myapp'...
|
||||
... deciding where to run 'SELECT 1 FROM DUAL'
|
||||
... some read-only query for a slave
|
||||
... ret = 'tcp://192.168.2.27:3306'
|
||||
User has connected to 'myapp'...
|
||||
... deciding where to run 'SELECT 2 FROM DUAL'
|
||||
... some read-only query for a slave
|
||||
... ret = 'tcp://192.168.78.136:3306'
|
||||
User has connected to 'myapp'...
|
||||
... deciding where to run 'SELECT * FROM table_on_slave_a_only'
|
||||
... access to table available only on slave A detected
|
||||
... ret = 'tcp://192.168.2.27:3306'
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 role="seealso">
|
||||
&reftitle.seealso;
|
||||
<para>
|
||||
<simplelist>
|
||||
<member>
|
||||
<function>mysqlnd_ms_query_is_select</function>
|
||||
</member>
|
||||
</simplelist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:t
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
indent-tabs-mode:nil
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:nil
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||||
vim: et tw=78 syn=sgml
|
||||
vi: ts=1 sw=1
|
||||
-->
|
128
reference/mysqlnd_ms/ini.xml
Executable file
128
reference/mysqlnd_ms/ini.xml
Executable file
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<section xml:id="mysqlnd-ms.configuration" xmlns="http://docbook.org/ns/docbook">
|
||||
&reftitle.runtime;
|
||||
&extension.runtime;
|
||||
<para>
|
||||
<table>
|
||||
<title>Mysqlnd_ms &ConfigureOptions;</title>
|
||||
<tgroup cols="4">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>&Name;</entry>
|
||||
<entry>&Default;</entry>
|
||||
<entry>&Changeable;</entry>
|
||||
<entry>&Changelog;</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>mysqlnd_ms.enable</entry>
|
||||
<entry>0</entry>
|
||||
<entry>its PHP_INI_* value</entry>
|
||||
<entry><!-- leave empty, this will be filled by an automatic script --></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>mysqlnd_ms.force_config_usage</entry>
|
||||
<entry>0</entry>
|
||||
<entry>its PHP_INI_* value</entry>
|
||||
<entry><!-- leave empty, this will be filled by an automatic script --></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>mysqlnd_ms.ini_file</entry>
|
||||
<entry></entry>
|
||||
<entry>its PHP_INI_* value</entry>
|
||||
<entry><!-- leave empty, this will be filled by an automatic script --></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>mysqlnd_ms.collect_statistics</entry>
|
||||
<entry></entry>
|
||||
<entry>its PHP_INI_* value</entry>
|
||||
<entry><!-- leave empty, this will be filled by an automatic script --></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
&ini.descriptions.title;
|
||||
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry xml:id="ini.mysqlnd-ms.enable">
|
||||
<term>
|
||||
<parameter>mysqlnd_ms.enable</parameter>
|
||||
<type>integer</type>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Enables or disables the plugin. If set to disabled, the extension will not plug
|
||||
into
|
||||
<link linkend="book.mysqlnd">mysqlnd</link> to proxy internal
|
||||
<link linkend="book.mysqlnd">mysqlnd</link> C API calls.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry xml:id="ini.mysqlnd-ms.force-config-usage">
|
||||
<term>
|
||||
<parameter>mysqlnd_ms.force_config_usage</parameter>
|
||||
<type>integer</type>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
If enabled the plugin checks if the host (server) parameter value of any
|
||||
MySQL connection attempt matches a section name from the plugin configuration
|
||||
file. If not, the connection attempt is blocked.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry xml:id="ini.mysqlnd-ms.ini-file">
|
||||
<term>
|
||||
<parameter>mysqlnd_ms.ini_file</parameter>
|
||||
<type>string</type>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Plugin specific configuration file.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry xml:id="ini.mysqlnd-ms.collect_statistics">
|
||||
<term>
|
||||
<parameter>mysqlnd_ms.collect_statistics</parameter>
|
||||
<type>integer</type>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Enables or disables the collection of statistics. The collection of
|
||||
statistics is disabled by default for performance reasons.
|
||||
Statistics are returned by the function
|
||||
<function>mysqlnd_ms_get_stats</function>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<!-- 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
|
||||
-->
|
611
reference/mysqlnd_ms/quickstart.xml
Executable file
611
reference/mysqlnd_ms/quickstart.xml
Executable file
|
@ -0,0 +1,611 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision: $ -->
|
||||
<chapter xml:id="mysqlnd-ms.quickstart" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Quickstart and Examples</title>
|
||||
<para>
|
||||
The mysqlnd replication load balancing plugin is easy to use.
|
||||
The quickstart will demo typical use-cases and give practical advice on getting
|
||||
started.
|
||||
</para>
|
||||
<para>
|
||||
It is strongly recommended to read the reference sections in addition to the
|
||||
quickstart. The quickstart tries to avoid discussing theoretical concepts
|
||||
and limitations. Instead, it will link to the reference sections. It is safe
|
||||
to begin with the quickstart. However, before using the plugin in mission critical
|
||||
environments we urge you to read additionally the background information from the
|
||||
reference sections.
|
||||
</para>
|
||||
<section xml:id="mysqlnd-ms.quickstart.configuration">
|
||||
<title>Setup</title>
|
||||
<para>
|
||||
The plugin is implemented as a PHP extension.
|
||||
Please, follow the
|
||||
<link linkend="mysqlnd-ms.installation">installation instructions</link> to
|
||||
install the
|
||||
<link xlink:href="&url.pecl.package;mysqlnd_ms">PECL/mysqlnd_ms</link> extension.
|
||||
Then, load the extension into PHP and activate the plugin in the PHP configuration
|
||||
file using the PHP configuration directive named
|
||||
<link linkend="ini.mysqlnd-ms.enable">mysqlnd_ms.enable</link>.
|
||||
</para>
|
||||
<para>
|
||||
The plugin is using its own configuration file. Use the PHP
|
||||
configuration directive
|
||||
<link linkend="ini.mysqlnd-ms.ini-file">mysqlnd_ms.ini_file</link>
|
||||
to set the full path to the plugin-specific configuration file.
|
||||
This file must be readable by PHP.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Enabling the plugin (php.ini)</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
mysqlnd_ms.enable=1
|
||||
mysqlnd_ms.ini_file=/path/to/mysqlnd_ms_plugin.ini
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
Create a plugin-specific configuration file. Save the file to the path
|
||||
set by the PHP configuration directive
|
||||
<link linkend="ini.mysqlnd-ms.ini-file">mysqlnd_ms.ini_file</link>.
|
||||
The plugin-specific file must be readable by PHP.
|
||||
</para>
|
||||
<para>
|
||||
The plugins configuration file is divided into one or more sections.
|
||||
Each section has a name, for example, <literal>myapp</literal>. Every section
|
||||
makes its own set of configuration settings.
|
||||
</para>
|
||||
<para>
|
||||
A section must at least list the MySQL replication master server.
|
||||
The plugin supports using only one master server per section. Multi-master
|
||||
MySQL replication setups are not supported.
|
||||
Use the configuration directive
|
||||
<link linkend="ini.mysqlnd-ms-plugin-config.master">master[]</link>
|
||||
to set the hostname and the port or socket of the MySQL master server.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Minimal plugin-specific configuration file (mysqlnd_ms_plugin.ini)</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
It is allowed to set no MySQL slave server but it is not recommended to do.
|
||||
You should always configure at least one slave server as well. Slave servers
|
||||
are set using the configuration directive
|
||||
<link linkend="ini.mysqlnd-ms-plugin-config.slave">slave[]</link>.
|
||||
A configuration section may contain no, one or multiple
|
||||
<literal>slave[]</literal> directives to set no, one or multiple
|
||||
MySQL slaves.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Recommended minimal plugin-specific config (mysqlnd_ms_plugin.ini)</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
slave[]=192.168.2.27:3306
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
If there are
|
||||
at least two servers in total, the plugin can start to load balance and switch
|
||||
connections. Switching connections is not always transparent and can cause
|
||||
issues in certain cases. The reference section on
|
||||
<link linkend="mysqlnd-ms.pooling">connection pooling and switching</link>,
|
||||
<link linkend="mysqlnd-ms.transaction">transaction handling</link>,
|
||||
<link linkend="mysqlnd-ms.failover">fail over</link>
|
||||
<link linkend="mysqlnd-ms.loadbalancing">load balancing</link> and
|
||||
<link linkend="mysqlnd-ms.rwsplit">read-write splitting</link> gives details.
|
||||
For now you can continue reading the quickstart. Potential pitfalls
|
||||
will be described later in the quickstart guide.
|
||||
</para>
|
||||
<para>
|
||||
It is responsibility of the application to handle potential issues caused
|
||||
by connection switches. By always configuring a master and at lease one slave
|
||||
server you can be sure to detect issues early because switches become
|
||||
possible.
|
||||
</para>
|
||||
<para>
|
||||
The MySQL master and MySQL slave servers, which you configure, do not need to
|
||||
be part of MySQL replication setup. For testing purpose you can use single
|
||||
MySQL server and make it known to the plugin as a master and slave server
|
||||
as shown below. This could help you to detect many potential issues with
|
||||
connection switches. However, such a setup will not be prone to the issues
|
||||
caused by replication lag.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Using one server as a master and as a slave (testing only!)</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
slave[]=127.0.0.1:3306
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.quickstart.usage">
|
||||
<title>Running statements</title>
|
||||
<para>
|
||||
The plugin can be used with any PHP MySQL extension
|
||||
(<link linkend="ref.mysqli">mysqli</link>,
|
||||
<link linkend="ref.mysql">mysql</link>,
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link>)
|
||||
compiled to use the <link linkend="book.mysqlnd">mysqlnd</link> library.
|
||||
PECL/mysqlnd_ms plugs into the <link linkend="book.mysqlnd">mysqlnd</link> library.
|
||||
It does not change the PHP MySQL extensions and their API.
|
||||
</para>
|
||||
<para>
|
||||
Whenever a connection to MySQL is being opened, the plugin compares the host
|
||||
parameter value of the connect call with the section names
|
||||
from the plugin specific configuration file. If, for example, the
|
||||
plugin specific configuration file has a section <literal>myapp</literal>
|
||||
the section should be referenced by opening a MySQL connection to the
|
||||
host <literal>myapp</literal>
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Plugin specific configuration file (mysqlnd_ms_plugin.ini)</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
slave[]=192.168.2.27:3306
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Opening a load balanced connection</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
/* Load balanced following "myapp" section rules from the plugins config file */
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
$pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
|
||||
$mysql = mysql_connect("myapp", "username", "password");
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
All of three connections opened in the example will be load balanced.
|
||||
The plugin will send read-only statements to the MySQL slave server with the
|
||||
IP <literal>192.168.2.27</literal> and listening on port <literal>3306</literal>
|
||||
for MySQL client connection. All other statements will be directed to the
|
||||
MySQL master server running on the host <literal>localhost</literal> accepting
|
||||
MySQL client connection on the Unix domain socket <literal>/tmp/mysql.sock</literal>.
|
||||
The plugin will use the user name <literal>username</literal> and the password
|
||||
<literal>password</literal> to connect to any of the MySQL servers listed in
|
||||
the section <literal>myapp</literal> of the plugins configuration file. Upon
|
||||
connect, the plugin will select <literal>database</literal> as the current
|
||||
schemata. The username, password and schema name are taken from the connect
|
||||
API calls and used for all servers. In other words: you must use the same
|
||||
username and password for every MySQL server listed in a plugin configuration
|
||||
file section.
|
||||
</para>
|
||||
<para>
|
||||
The plugin does not change the API for running statements.
|
||||
<link linkend="mysqlnd-ms.rwsplit">Read-write splitting</link>
|
||||
works out of the box. The following example assumes that there is no
|
||||
significant replication lag between the master and the slave.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Executing statements</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
/* Load balanced following "myapp" section rules from the plugins config file */
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
if (!$mysqli)
|
||||
/* Of course, your error handling is nicer... */
|
||||
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
/* Statements will be run on the master */
|
||||
if (!$mysqli->query("DROP TABLE IF EXISTS test")) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
if (!$mysqli->query("CREATE TABLE test(id INT)")) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
if (!$mysqli->query("INSERT INTO test(id) VALUES (1)")) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
|
||||
/* read-only: statement will be run on a slave */
|
||||
if (!($res = $mysqli->query("SELECT id FROM test")) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
} else {
|
||||
$row = $res->fetch_assoc();
|
||||
$res->close();
|
||||
printf("Slave returns id = '%s'\n", $row['id'];
|
||||
}
|
||||
$mysqli->close();
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
Slave returns id = '1'
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
The plugin does not support native prepared statements. Prepared
|
||||
statements are not load balanced. Most users of
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link>
|
||||
will be unaffected by this restriction because
|
||||
<link linkend="ref.pdo-mysql">PDO_MYSQL</link> is using a
|
||||
client-side prepared statement emulation by default.
|
||||
</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.quickstart.connectionpooling">
|
||||
<title>Connection state</title>
|
||||
<para>
|
||||
The plugin changes the semantics of a PHP MySQL connection handle.
|
||||
A connection handle does no longer represent a single MySQL client-server
|
||||
network connection but a connection pool. The connection pool consists
|
||||
of a master connection and none, one or multiple slave connections.
|
||||
</para>
|
||||
<para>
|
||||
Every connection from the connection pool has its own state. For example,
|
||||
SQL user variables, temporary tables and transactions are part of the state.
|
||||
Please, find a complete list of what belongs to the state of a connection
|
||||
at the concepts page on
|
||||
<link linkend="mysqlnd-ms.pooling">connection pooling and switching</link>.
|
||||
If the plugin decides to switch connections for load balancing the
|
||||
application could be given connection which has a different state.
|
||||
Applications must be made aware of this!
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Plugin config with one slave and one master</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
slave[]=192.168.2.27:3306
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Pitfall: connection state and SQL user variables</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
if (!$mysqli)
|
||||
/* Of course, your error handling is nicer... */
|
||||
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
/* Connection 1, connection bound SQL user variable, no SELECT thus run on master */
|
||||
if (!$mysqli->query("SET @myrole='master'")) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
|
||||
/* Connection 2, run on slave because SELECT */
|
||||
if (!($res = $mysqli->query("SELECT @myrole AS _role"))) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
} else {
|
||||
$row = $res->fetch_assoc();
|
||||
$res->close();
|
||||
printf("@myrole = '%s'\n", $row['_role']);
|
||||
}
|
||||
$mysqli->close();
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
@myrole = ''
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
The example openes a load balanced connection and executes two statements.
|
||||
The first statement <literal>SET @myrole='master'</literal> does not begin
|
||||
with the string <literal>SELECT</literal>. Therefore the plugin does not
|
||||
recognize it as a read-only query which shall be run on a slave. The
|
||||
plugin runs the statement on the connection to the master. The statement
|
||||
sets a SQL user variable which is bound to the master connection. The
|
||||
state of the master connection has been changed.
|
||||
</para>
|
||||
<para>
|
||||
The next statement is <literal>SELECT @myrole AS _role</literal>.
|
||||
The plugin does recognize it as a read-only query and sends it to
|
||||
the slave. The statement is run on a connection to the slave. This
|
||||
second connection does not have any SQL user variables bound to it.
|
||||
It has a different state than the first connection to the master.
|
||||
The requested SQL user variable is not set. The example script prints
|
||||
<literal>@myrole = ''</literal>.
|
||||
</para>
|
||||
<para>
|
||||
It is the responsibility of the application developer to take care
|
||||
of the connection state. The plugin does not monitor all
|
||||
connection state changing activities. Monitoring all possible cases would
|
||||
be a very CPU intensive task, if it could be done at all.
|
||||
</para>
|
||||
<para>
|
||||
The pitfalls can easily be worked around using SQL hints.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.quickstart.sqlhints">
|
||||
<title>SQL Hints</title>
|
||||
<para>
|
||||
SQL hints can be used to force the plugin to pick a certain server from
|
||||
the connection pool. Hinting the plugin to use a certain server can solve
|
||||
issues caused by connection switches and connection state.
|
||||
</para>
|
||||
<para>
|
||||
SQL hints are standard compliant SQL comments. Because
|
||||
SQL comments are supposed to be ignored by SQL processing systems they
|
||||
do not infere with other programs such as the MySQL Server, the MySQL Proxy
|
||||
or a firewall.
|
||||
</para>
|
||||
<para>
|
||||
Three SQL hints are supported by the plugin:
|
||||
<constant>MYSQLND_MS_MASTER_SWITCH</constant>,
|
||||
<constant>MYSQLND_MS_SLAVE_SWITCH</constant> and
|
||||
<constant>MYSQLND_MS_LAST_USED_SWITCH</constant>.
|
||||
<constant>MYSQLND_MS_MASTER_SWITCH</constant> makes the plugin run a statement
|
||||
on the master, <constant>MYSQLND_MS_SLAVE_SWITCH</constant> enforces the use
|
||||
of the slave and <constant>MYSQLND_MS_MASTER_SWITCH</constant> will run a
|
||||
statement on the same server that has been used for running the previous
|
||||
statement.
|
||||
</para>
|
||||
<para>
|
||||
The plugin scans the beginning of a statement for the existance of a SQL
|
||||
hint. SQL hints are only recognized if they appear at the very beginning of
|
||||
the statement.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Plugin config with one slave and one master</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
slave[]=192.168.2.27:3306
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>SQL hints to prevent connection switches</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
if (!$mysqli)
|
||||
/* Of course, your error handling is nicer... */
|
||||
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
/* Connection 1, connection bound SQL user variable, no SELECT thus run on master */
|
||||
if (!$mysqli->query("SET @myrole='master'")) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
|
||||
/* Connection 1, run on master because of SQL hint */
|
||||
if (!($res = $mysqli->query(sprintf("/*%s*/SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)))) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
} else {
|
||||
$row = $res->fetch_assoc();
|
||||
$res->close();
|
||||
printf("@myrole = '%s'\n", $row['_role']);
|
||||
}
|
||||
$mysqli->close();
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
@myrole = 'master'
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
In the example the session variables issue from the previous page is solved
|
||||
using <constant>MYSQLND_MS_LAST_USED_SWITCH</constant> to prevent switching
|
||||
from the master to a slave when running the <literal>SELECT</literal> statement.
|
||||
</para>
|
||||
<para>
|
||||
SQL hints can also be used to run <literal>SELECT</literal> statements
|
||||
on the MySQL master server. This may be desired if the MySQL slave servers
|
||||
tend to be behind the master but you need current data from the database.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Fighting replication lag</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
if (!$mysqli)
|
||||
/* Of course, your error handling is nicer... */
|
||||
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
/* Force use of master, master has always fresh and current data */
|
||||
if (!$mysqli->query(sprintf("/*%s*/SELECT critical_data FROM important_table", MYSQLND_MS_MASTER_SWITCH))) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
use case may include the creation of tables on a slave.
|
||||
If no SQL hint is given, the plugin will send <literal>CREATE</literal>
|
||||
and <literal>INSERT</literal> statements to the master. Use the
|
||||
SQL hint <constant>MYSQLND_MS_SLAVE_SWITCH</constant> if you want to
|
||||
run any such statement on a slave, for example, to build temporary
|
||||
reporting tables.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Table creation on a slave</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
if (!$mysqli)
|
||||
/* Of course, your error handling is nicer... */
|
||||
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
/* Force use of slave */
|
||||
if (!$mysqli->query(sprintf("/*%s*/CREATE TABLE slave_reporting(id INT)", MYSQLND_MS_SLAVE_SWITCH))) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
/* Continue using this particular slave connection */
|
||||
if (!$mysqli->query(sprintf("/*%s*/INSERT INTO slave_reporting(id) VALUES (1), (2), (3)", MYSQLND_MS_LAST_USED_SWITCH))) {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
/* Don't use MYSQLND_MS_SLAVE_SWITCH which would allow switching to another slave! */
|
||||
if ($res = $mysqli->query(sprintf("/*%s*/SELECT COUNT(*) AS _num FROM slave_reporting", MYSQLND_MS_LAST_USED_SWITCH))) {
|
||||
$row = $res->fetch_assoc();
|
||||
$res->close();
|
||||
printf("There are %d rows in the table 'slave_reporting'", $row['_num']);
|
||||
} else {
|
||||
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
|
||||
}
|
||||
$mysqli->close();
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
The SQL hint <constant>MYSQLND_MS_LAST_USED</constant> forbids switching
|
||||
connection and forces the use of the previously used connection.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="mysqlnd-ms.quickstart.transactions">
|
||||
<title>Transactions</title>
|
||||
<para>
|
||||
The current version of the plugin is not transaction safe,
|
||||
because it is not transaction aware. SQL transactions are
|
||||
units of work to be run on a single server.
|
||||
The plugin does not know when the unit of work starts and when it ends.
|
||||
Therefore, the plugin may decide to switch connections in the middle
|
||||
of a transaction.
|
||||
</para>
|
||||
<para>
|
||||
You must use SQL hints to work around this limitation.
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Plugin config with one slave and one master</title>
|
||||
<programlisting role="ini">
|
||||
<![CDATA[
|
||||
[myapp]
|
||||
master[]=localhost:/tmp/mysql.sock
|
||||
slave[]=192.168.2.27:3306
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<title>Using SQL hints for transactions</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$mysqli = new mysqli("myapp", "username", "password", "database");
|
||||
if (!$mysqli)
|
||||
/* Of course, your error handling is nicer... */
|
||||
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
|
||||
|
||||
/* Not a SELECT, will use master */
|
||||
if (!$mysqli->query("START TRANSACTION")) {
|
||||
/* Please use better error handling in your code */
|
||||
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
|
||||
}
|
||||
|
||||
/* Prevent connection switch! */
|
||||
if (!$mysqli->query(sprintf("/*%s*/INSERT INTO test(id) VALUES (1)", MYSQLND_MS_LAST_USED_SWITCH)))) {
|
||||
/* Please do proper ROLLBACK in your code, don't just die */
|
||||
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
|
||||
}
|
||||
if ($res = $mysqli->query(sprintf("/*%s*/SELECT COUNT(*) AS _num FROM test", MYSQLND_MS_LAST_USED_SWITCH)))) {
|
||||
$row = $res->fetch_assoc();
|
||||
$res->close();
|
||||
if ($row['_num'] > 1000) {
|
||||
if (!$mysqli->query(sprintf("/*%s*/INSERT INTO events(task) VALUES ('cleanup')", MYSQLND_MS_LAST_USED_SWITCH)))) {
|
||||
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
|
||||
}
|
||||
if (!$mysqli->query(sprintf("/*%s*/UPDATE log SET last_update = NOW()", MYSQLND_MS_LAST_USED_SWITCH)))) {
|
||||
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
|
||||
}
|
||||
if (!$mysqli->query(sprintf("/*%s*/COMMIT", MYSQLND_MS_LAST_USED_SWITCH)))) {
|
||||
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
|
||||
}
|
||||
|
||||
$mysqli->close();
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
<para>
|
||||
Future versions of the plugin may be made aware of transactions started,
|
||||
rolled back and committed using API calls. Therefore, whenever possible
|
||||
you should start using API calls to control transactions unlike using
|
||||
SQL statements, as shown in the above 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
|
||||
-->
|
30
reference/mysqlnd_ms/reference.xml
Executable file
30
reference/mysqlnd_ms/reference.xml
Executable file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
|
||||
<reference xml:id="ref.mysqlnd-ms" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Mysqlnd_ms &Functions;</title>
|
||||
|
||||
&reference.mysqlnd-ms.entities.functions;
|
||||
|
||||
</reference>
|
||||
|
||||
<!-- 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
|
||||
-->
|
329
reference/mysqlnd_ms/setup.xml
Executable file
329
reference/mysqlnd_ms/setup.xml
Executable file
|
@ -0,0 +1,329 @@
|
|||
<?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.
|
||||
</para>
|
||||
<para>
|
||||
The <literal>mysqlnd_ms</literal> replication and load balancing
|
||||
plugin supports all PHP applications and all availablePHP 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">
|
||||
<title xmlns="http://docbook.org/ns/docbook">Plugin configuration file</title>
|
||||
<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 minics standard <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 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 remeber 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>
|
||||
</variablelist>
|
||||
</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
|
||||
-->
|
33
reference/mysqlnd_ms/versions.xml
Executable file
33
reference/mysqlnd_ms/versions.xml
Executable file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
<!--
|
||||
Do NOT translate this file
|
||||
-->
|
||||
|
||||
<versions>
|
||||
<!-- Functions -->
|
||||
<function name='mysqlnd_ms_set_user_pick_server' from='PECL mysqlnd_ms >= 1.0.0'/>
|
||||
<function name='mysqlnd_ms_query_is_select' from='PECL mysqlnd_ms >= 1.0.0'/>
|
||||
<function name='mysqlnd_ms_get_stats' from='PECL mysqlnd_ms >= 1.0.0'/>
|
||||
</versions>
|
||||
|
||||
<!-- 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
|
||||
-->
|
Loading…
Reference in a new issue