diff --git a/reference/mysqlnd_ms/book.xml b/reference/mysqlnd_ms/book.xml
index 8279de2073..0831f934e0 100755
--- a/reference/mysqlnd_ms/book.xml
+++ b/reference/mysqlnd_ms/book.xml
@@ -47,6 +47,9 @@
Key Features
+
+ The key features of PECL/mysqlnd_ms are as follows.
+
@@ -166,7 +169,12 @@
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.
+ will be based on the beginning of the statement string. For example, if
+ using mysqli_multi_query
+ to execute the multi-statement SELECT id FROM test ; INSERT INTO test(id) VALUES (1),
+ the statement will be redirected to a slave server because it begins with
+ SELECT. The INSERT statement, which is
+ also part of the multi-statement, will not be redirected to a master server.
Prior to version 1.1.0-beta the plugin did not support native prepared statements.
diff --git a/reference/mysqlnd_ms/concepts.xml b/reference/mysqlnd_ms/concepts.xml
index 9c55dbc4cd..f97d54bcfa 100755
--- a/reference/mysqlnd_ms/concepts.xml
+++ b/reference/mysqlnd_ms/concepts.xml
@@ -4,7 +4,7 @@
Concepts
- The concept section explains the overall architecture and important concepts
+ The concepts section explains the overall architecture and important concepts
of the plugin. The materials aim to help you understanding the impact of
MySQL replication and using the plugin for your development tasks.
Any application using MySQL replication must take care of certain tasks that
@@ -34,18 +34,25 @@
the SQL hint /*ms=slave*/ or a slave had been choose for
running the previous query and the query starts with the SQL hint
/*ms=last_used*/. In all other cases the query will
- be sent to the MySQL replication master server.
+ be sent to the MySQL replication master server. Applications are requested
+ to use the MYSQLND_MS_MASTER_SWITCH,
+ MYSQLND_MS_SLAVE_SWITCH and
+ MYSQLND_MS_LAST_USED_SWITCH
+ predefined constants
+ instead of their literal values,
+ such as /*ms=slave*/,
+ for better portability.
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
+ network connections managed by the plugin. The plugin proxies queries
to the master server and the slave ones using multiple connections.
- Database connections have a state consisting, for example, transaction
+ Database connections have a state consisting of, 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.
@@ -84,7 +91,7 @@
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
+ and replacing the network connection referenced by a PHP MySQL
connection handle is not a transparent operation.
@@ -121,7 +128,7 @@
- The current database set using USE
+ The current database set using USE and other state chaning SQL commands
@@ -155,7 +162,7 @@
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
+ necessary for security reasons. Just a few actions that change the
state of the connection fall into this category.
@@ -348,7 +355,7 @@
Please note that the connection state is not only changed by API calls. Thus,
even if PECL mysqlnd_ms monitors all API calls, the application still needs
- to take care. Ultimately, it is in the application developers reposibility
+ to take care. Ultimately, it is in the applications reposibility
to maintain connection state, if needed.
@@ -395,6 +402,213 @@
+
+ Error handling
+
+ Applications using PECL/mysqlnd_ms should to proper error handling
+ of any user API call. Due to the fact that the plugin changes the semantics
+ of a connection handle, API calls may return unexpected errors. If using
+ the plugin a connection handle no longer represents an individual network
+ connection but a connection pool. An error code and error message will
+ be set on the connection handle whenever an error occurs on any of the network
+ connections behind.
+
+
+ If using lazy connections, which is a default, connections are not
+ opened until needed for query execution. Therefore, it can happen that
+ an API call for statement execution returns a connection error.
+ In the example an error is provoked when trying to run a statement on a slave.
+ Opening a slave connection fails because the plugins configuration file
+ lists an invalid host name of the slave.
+
+
+
+ Provoking a connection error
+
+
+
+
+
+
+ Explicitly activating lazy connections is done for demonstration purpose.
+
+
+
+ Connection error on query execution
+
+query("SET @myrole='master'")) {
+ printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
+}
+
+/* Connection 2, run on slave because SELECT, provoke connection error */
+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();
+?>
+]]>
+
+&example.outputs;
+
+
+
+
+
+
+ Applications are expected to be able to handle the connection error. In
+ most cases this will not require code changes, if the application does
+ proper error handling already.
+
+
+ Depending on the use case applications may want to handle connection errors
+ differently from other errors. Typical connection errors are
+ 2002 (CR_CONNECTION_ERROR) - Can't connect to local MySQL server through socket '%s' (%d),
+ 2003 (CR_CONN_HOST_ERROR) - Can't connect to MySQL server on '%s' (%d) and
+ 2005 (CR_UNKNOWN_HOST) - Unknown MySQL server host '%s' (%d).
+ For example, the application may test for the error codes and manually
+ perform fail over. The plugins philosophy is not to offer automatic fail over
+ beyond master fail over because fail over is not a transparent operation.
+
+
+
+ Provoking a connection error
+
+
+
+
+
+
+ Explicitly activating lazy connections is done for demonstration purpose.
+ Please, note that round robin load balancing is used instead of the default
+ random once.
+
+
+
+ Most basic failover
+
+query("SET @myrole='master'")) {
+ printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
+}
+
+/* Connection 2, first slave */
+$res = $mysqli->query("SELECT VERSION() AS _version");
+/* Hackish manual fail over */
+if (2002 == $mysqli->errno || 2003 == $mysqli->errno || 2004 == $mysqli->errno) {
+ /* Connection 3, first slave connection failed, trying next slave */
+ $res = $mysqli->query("SELECT VERSION() AS _version");
+}
+
+if (!$res) {
+ printf("ERROR, [%d] '%s'\n", $mysqli->errno, $mysqli->error);
+} else {
+ /* Error messages are taken from connection 3, thus no error */
+ printf("SUCCESS, [%d] '%s'\n", $mysqli->errno, $mysqli->error);
+ $row = $res->fetch_assoc();
+ $res->close();
+ printf("version = %s\n", $row['_version']);
+}
+$mysqli->close();
+?>
+]]>
+
+&example.outputs;
+
+
+
+
+
+
+ In some cases, it may not be easily possible to retrieve all errors that
+ occur on all network connections through a connection handle. Assume a
+ connection handle represents a pool of three open connections. One connection
+ to a master and two connections to the slaves. The application changes the
+ current database using the user API call mysqli_select_db,
+ which in turn calls the mysqlnd library function to change the schemata.
+ PECL/mysqlnd_ms monitors the function and tries to change the current
+ database on all connections.to harmonize their state. Let the master succeed
+ in changing the database and let both slaves fail. Upon the first error
+ from the first slave, the plugin will set an appropriate error on the
+ connection handle. The same is done when the second slave fails to change the
+ database. The error message from the first slave is lost.
+
+
+ Such cases can be debugged by either checking for errors of the type
+ E_WARNING (see above) or, if no other option, investigation
+ of the debug and trace log.
+
+
+
Failover
@@ -408,8 +622,8 @@
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
+ 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.
@@ -429,6 +643,10 @@
failover
configuration directive.
+
+ A most basic manual failover example is given under
+ error handling.
+
@@ -488,7 +706,7 @@
A user-defined read-write splitter can ask the built-in logic to make
a proposal where to sent a statement by invoking
- mysqlnd_ms_is_select.
+ mysqlnd_ms_is_select.
diff --git a/reference/mysqlnd_ms/quickstart.xml b/reference/mysqlnd_ms/quickstart.xml
index 2a8b0431fc..a9eef86b89 100755
--- a/reference/mysqlnd_ms/quickstart.xml
+++ b/reference/mysqlnd_ms/quickstart.xml
@@ -60,7 +60,6 @@ mysqlnd_ms.ini_file=/path/to/mysqlnd_ms_plugin.ini
Create a plugin-specific configuration file. Save the file to the path
set by the PHP configuration directive
mysqlnd_ms.ini_file.
- The plugin-specific file must be readable by PHP.
The plugins configuration file
@@ -104,7 +103,7 @@ mysqlnd_ms.ini_file=/path/to/mysqlnd_ms_plugin.ini
It is not allowed to omit the MySQL slave server list. However,
an empty list may be configured. Doing so is not recommended.
You should always configure at least one slave server as well.
- The slave server list may consist of one or more servers.
+ The slave server list, if not empty, may consist of one or more servers.
Server lists can use
@@ -265,10 +264,18 @@ $mysql = mysql_connect("myapp", "username", "password");
password to connect to any of the MySQL servers listed in
the section myapp of the plugins configuration file. Upon
connect, the plugin will select database as the current
- schemata. The username, password and schema name are taken from the connect
+ 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.
+ file section. The is not a general limitation. As of PECL/mysqlnd_ms 1.1.0,
+ it is possible to set the
+ username and
+ password for any server in the
+ plugins configuration file to be used instead of the credentials passed
+ to the API call.
The plugin does not change the API for running statements.
@@ -284,7 +291,7 @@ $mysql = mysql_connect("myapp", "username", "password");
Example excerpt from the debug log (connection failure):
@@ -1836,6 +1840,17 @@ mysqlnd.debug=d:t:x:O,/tmp/mysqlnd.trace
]]>
+
+ In this case the statement DROP TABLE IF EXISTS test has been
+ executed. Note that the statement string is shown in the log file. You may want
+ to take measures to restrict access to the log for security considerations.
+
+
+ The statement has been load balanced using round robin policy,
+ as you can easily guess from the functions name >mysqlnd_ms_choose_connection_rr.
+ It has been sent to a master server running on
+ host=localhost user=root db=test port=3306 flags=131072 persistent=0 state=0.
+