diff --git a/reference/mysqlnd_ms/changes.xml b/reference/mysqlnd_ms/changes.xml
index 265a44377b..e250cd54aa 100644
--- a/reference/mysqlnd_ms/changes.xml
+++ b/reference/mysqlnd_ms/changes.xml
@@ -12,6 +12,63 @@
for a complete list of changes.
+
+ PECL/mysqlnd_ms 1.6 series
+
+ 1.6.0-alpha
+
+
+
+ Release date: TBD
+
+
+
+
+ Motto/theme: Maintenance
+
+
+
+
+
+
+ This is the current development series. All
+ features are at an early stage. Changes may happen at any time without
+ prior notice. Please, do not use this version in production environments.
+
+
+ The documentation may not reflect all changes yet.
+
+
+
+ Bug fixes
+
+
+
+ No new bugs reported
+
+
+
+
+
+ Feature changes
+
+
+
+ Introduced automatic retry loop for transient errors and
+ corresponding statistic
+ to count the number of implicit retries. Some distributed
+ database clusters use transient errors to hint a client to retry
+ its operation in a bit. Most often, the client is then supposed
+ to halt execution (sleep) for a short moment before retrying the
+ desired operation. Immediately failing over to another node
+ is not necessary in response to the error. Instead, a retry loop
+ can be performed. Common situation when using MySQL Cluster.
+
+
+
+
+
+
PECL/mysqlnd_ms 1.5 series
@@ -31,12 +88,11 @@
- This is the current development series. All
- features are at an early stage. Changes may happen at any time without
- prior notice. Please, do not use this version in production environments.
+ This is the current release series. Albeit a stable release is missing,
+ it can be considered stable. Use this version in production environments.
- The documentation may not reflect all changes yet.
+ The documentation is complete.
@@ -140,7 +196,7 @@
modified to use the new C API calls of the mysqlnd
library to begin, commit, and rollback a transaction or savepoint.
If trx_stickiness
- is used to enable transaction aware load balancing, the mysqli_begin,
+ is used to enable transaction aware load balancing, the mysqli_begin,
mysqli_commit and mysqli_rollback functions
will now be monitered by the plugin, to go along with the mysqli_autocommit
function that was already supported. All SQL features to control
diff --git a/reference/mysqlnd_ms/concepts.xml b/reference/mysqlnd_ms/concepts.xml
index 85bb7b5ccc..5fa17e2ae3 100755
--- a/reference/mysqlnd_ms/concepts.xml
+++ b/reference/mysqlnd_ms/concepts.xml
@@ -658,6 +658,166 @@ version = 5.6.2-m5-log
+
+ Transient errors
+
+ Some distributed database clusters make use of transient errors. A transient
+ error is a temporary error that is likely to disappear soon. By definition
+ it is safe for a client to ignore a transient error and retry the failed
+ operation on the same database server. The retry is free of side effects.
+ Clients are not forced to abort their work or to fail over to another database
+ server immediately. They may enter a retry loop before to wait for the
+ error to disappear before giving up on the database server.
+ Transient errors can be seen, for example, when using MySQL Cluster. But they
+ are not bound to any specific clustering solution per se.
+
+
+ PECL/mysqlnd_ms can perform an automatic retry loop in
+ case of a transient error. This increases distribution transparency and thus
+ makes it easier to migrate an application running on a single database
+ server to run on a cluster of database servers without having to change
+ the source of the application.
+
+
+ The automatic retry loop will repeat the requested operation up to a user
+ configurable number of times and pause between the attempts for a configurable
+ amount of time. If the error disappears during the loop, the application will
+ never see it. If not, the error is forwarded to the application for handling.
+
+
+ In the example below a duplicate key error is provoked to make the plugin
+ retry the failing query two times before the error is passed to the application.
+ Between the two attempts the plugin sleeps for 100 milliseconds.
+
+
+
+ Provoking a transient error
+
+
+
+
+
+
+
+
+
+
+ Transient error retry loop
+
+query("DROP TABLE IF EXISTS test") ||
+ !$mysqli->query("CREATE TABLE test(id INT PRIMARY KEY)") ||
+ !$mysqli->query("INSERT INTO test(id) VALUES (1))")) {
+ printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
+}
+
+/* Retry loop is completely transparent. Checking statistics is
+ the only way to know about implicit retries */
+$stats = mysqlnd_ms_get_stats();
+printf("Transient error retries before error: %d\n", $stats['transient_error_retries']);
+
+/* Provoking duplicate key error to see statistics change */
+if (!$mysqli->query("INSERT INTO test(id) VALUES (1))")) {
+ printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
+}
+
+$stats = mysqlnd_ms_get_stats();
+printf("Transient error retries after error: %d\n", $stats['transient_error_retries']);
+
+$mysqli->close();
+?>
+]]>
+
+&example.outputs.similar;
+
+
+
+
+
+
+ Because the execution of the retry loop is transparent from a users point of
+ view, the example checks the
+ statistics
+ provided by the plugin to learn about it.
+
+
+ As the example shows, the plugin can be instructed to consider any error
+ transient regardless of the database servers error semantics. The only error
+ that a stock MySQL server considers temporary has the error code
+ 1297. When configuring other error codes but
+ 1297 make sure your configuration reflects
+ the semantics of your clusters error codes.
+
+
+ The following mysqlnd C API calls are monitored by the plugin to check
+ for transient errors: query(),
+ change_user(), select_db(),
+ set_charset(), set_server_option()
+ prepare(), execute(),
+ set_autocommit(),
+ tx_begin(), tx_commit(),
+ tx_rollback(), tx_commit_or_rollback().
+ The corresponding user API calls have similar names.
+
+
+ The maximum time the plugin may sleep during the retry loop depends on the
+ function in question. The a retry loop for query(),
+ prepare() or execute() will sleep for
+ up to max_retries * usleep_retry milliseconds.
+
+
+ However, functions that
+ control connection state
+ are dispatched to all all connections. The retry loop settings are applied
+ to every connection on which the command is to be run. Thus, such a function
+ may interrupt program execution for longer than a function that is run
+ on one server only. For example, set_autocommit() is
+ dispatched to connections and may sleep up to
+ (max_retries * usleep_retry) * number_of_open_connections)
+ milliseconds. Please, keep this in mind when setting long sleep times
+ and large retry numbers. Using the default settings of
+ max_retries=1, usleep_retry=100 and
+ lazy_connections=1 it is unlikely that you will
+ ever see a delay of more than 1 second.
+
+
+
Failover
diff --git a/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml b/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml
index fc04303d09..084508a37c 100755
--- a/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml
+++ b/reference/mysqlnd_ms/functions/mysqlnd-ms-get-stats.xml
@@ -442,6 +442,18 @@
Since 1.2.0.
+
+
+ transient_error_retries
+
+
+ How often an operation has been retried when a transient error was
+ detected. See also,
+ transient_error
+ plugin configuration file setting.
+
+ Since 1.6.0.
+
@@ -519,6 +531,8 @@ array(26) {
string(1) "0"
["gtid_implicit_commit_injections_failure"]=>
string(1) "0"
+ ["transient_error_retries"]=>
+ string(1) "0"
}
]]>
diff --git a/reference/mysqlnd_ms/setup.xml b/reference/mysqlnd_ms/setup.xml
index ac682a839a..9259cc004c 100755
--- a/reference/mysqlnd_ms/setup.xml
+++ b/reference/mysqlnd_ms/setup.xml
@@ -2399,9 +2399,136 @@ $mysqli->set_charset("latin1");
+
+
+
+ transient_error
+ object
+
+
+
+ The setting has been introduced in 1.6.0.
+
+
+ A database cluster node may reply a transient error to a client. The client
+ can then repeat the operation on the same node, fail over to a different node
+ or abort the operation. Per definition is it safe for a client to
+ retry the same operation on the same node before giving up.
+
+
+ PECL/mysqlnd_ms can perform the retry
+ loop on behalf of the application.
+ By configuring transient_error the plugin can be
+ instructed to repeat operations failing with a certain error code for
+ a certain maximum number of times with a pause between the retries.
+ If the transient error disappears during loop execution, it is
+ hidden from the application. Otherwise, the error is
+ forwarded to the application by the end of the loop.
+
+
+
+ Retry loop for transient errors
+
+
+
+
+
+
+
+
+
+
+
+
+ Keyword
+ Description
+ Version
+
+
+
+
+
+ mysql_error_codes
+
+
+
+ List of transient error codes. You may add any MySQL error code
+ to the list. It is possible to consider any error as transient
+ not only 1297
+ (HY000 (ER_GET_TEMPORARY_ERRMSG),
+ Message: Got temporary error %d '%s' from %s).
+ Before adding other codes but 1297 to the list,
+ make sure your cluster supports a new attempt without impacting
+ the state of your application.
+
+
+ Since 1.6.0.
+
+
+
+ max_retries
+
+
+
+ How often to retry an operation which
+ fails with a transient error before forwarding the
+ failure to the user.
+
+
+ Default: 1
+
+
+ Since 1.6.0.
+
+
+
+ usleep_retry
+
+
+
+ Milliseconds to sleep between transient error retries.
+ The value is passed to the C function usleep,
+ hence the name.
+
+
+ Default: 100
+
+
+ Since 1.6.0.
+
+
+
+
+
+
+
-
+
+
Plugin configuration file (<= 1.0.x)