Background/concepts information on XA transaction support. Document XA related statistics

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@334413 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Ulf Wendel 2014-07-29 17:04:02 +00:00
parent 3e71d7cc2f
commit 0f4adfde51
9 changed files with 325 additions and 23 deletions

View file

@ -103,6 +103,7 @@
Fabric the actual shard servers involved in a business transaction may not be known
in advance. Thus, manually controlling a transaction that spawns multiple shards becomes
difficult.
Please, be warned about <link linkend="mysqlnd-ms.concept_xa_trx">current limitations</link>.
</para>
</listitem>
<listitem>

View file

@ -385,7 +385,7 @@
</section>
<section xml:id="mysqlnd-ms.transaction">
<title>Transaction handling</title>
<title>Local transaction handling</title>
<para>
Transaction handling is fundamentally changed.
An SQL transaction is a unit of work that is run on one database server. The
@ -1433,7 +1433,8 @@ Transient error retries before error: 2
</para>
<para>
As of MySQL 5.6.5-m8 the MySQL server features built-in global transaction identifiers.
The MySQL built-in global transaction ID feature is supported by PECL/mysqlnd_ms 1.3.0-alpha or
The MySQL built-in global transaction ID feature is supported by
<literal>PECL/mysqlnd_ms</literal> 1.3.0-alpha or
later. Neither are client-side transaction boundary monitoring nor any setup
activities required if using the server feature.
</para>
@ -1447,7 +1448,7 @@ Transient error retries before error: 2
<emphasis role="bold">Idea and client-side emulation</emphasis>
</para>
<para>
PECL/mysqlnd_ms can do client-side transparent global transaction ID injection.
<literal>PECL/mysqlnd_ms</literal> can do client-side transparent global transaction ID injection.
In its most basic form, a global transaction identifier is a counter which is
incremented for every transaction executed on the master. The counter is held
in a table on the master. Slaves replicate the counter table.
@ -1491,7 +1492,8 @@ Transient error retries before error: 2
</para>
<para>
Client-side global transaction ID injection has shortcomings. The potential
issues are not specific to PECL/mysqlnd_ms but are rather of general nature.
issues are not specific to <literal>PECL/mysqlnd_ms</literal>
but are rather of general nature.
<itemizedlist>
<listitem>
<simpara>
@ -1522,7 +1524,8 @@ Transient error retries before error: 2
<emphasis role="bold">Using server-side global transaction identifier</emphasis>
</para>
<para>
Starting with PECL/mysqlnd_ms 1.3.0-alpha the MySQL 5.6.5-m8 or newer built-in global
Starting with <literal>PECL/mysqlnd_ms</literal> 1.3.0-alpha
the MySQL 5.6.5-m8 or newer built-in global
transaction identifier feature is supported. Use of the server feature lifts
all of the above listed limitations. Please, see the MySQL Reference Manual
for limitations and preconditions for using server built-in global transaction
@ -1589,7 +1592,7 @@ Transient error retries before error: 2
systems, such as a database cluster. Global transaction identifiers can
be used for, for example, system wide identification of transactions,
global ordering of transactions, heartbeat mechanism and
for checking the replication status of replicas. PECL/mysqlnd_ms, a clientside
for checking the replication status of replicas. <literal>PECL/mysqlnd_ms</literal>, a clientside
driver based software, does focus on using GTIDs for tasks that can be
handled at the client, such as checking the replication status of replicas
for asynchronous replication setups.
@ -1602,15 +1605,17 @@ Transient error retries before error: 2
<note>
<title>Version requirement</title>
<para>
The feature requires use of PECL/mysqlnd_ms 1.3.0-beta or later,
and PECL/mysqlnd_qc 1.1.0-alpha or newer. PECL/mysqlnd_ms must be
The feature requires use of <literal>PECL/mysqlnd_ms</literal> 1.3.0-beta or later,
and <literal>PECL/mysqlnd_qc</literal> 1.1.0-alpha or newer.
<literal>PECL/mysqlnd_ms</literal> must be
compiled to support the feature. PHP 5.4.0 or newer is required.
</para>
</note>
<note>
<title>Setup: extension load order</title>
<para>
PECL/mysqlnd_ms must be loaded before PECL/mysqlnd_qc, when using shared
<literal>PECL/mysqlnd_ms</literal> must be loaded before
<literal>PECL/mysqlnd_qc</literal>, when using shared
extensions.
</para>
</note>
@ -1631,7 +1636,8 @@ Transient error retries before error: 2
</note>
<para>
Support for MySQL replication clusters (asynchronous primary copy) is the
main focus of PECL/mysqlnd_ms. The slaves of a MySQL replication cluster
main focus of <literal>PECL/mysqlnd_ms</literal>.
The slaves of a MySQL replication cluster
may or may not reflect the latest updates from the master.
Slaves are asynchronous and can lag behind the master. A read from a slave
is eventual consistent from a cluster-wide perspective.
@ -1648,13 +1654,14 @@ Transient error retries before error: 2
replace a remote database access with a local cache access to gain better possibility.
</para>
<para>
As of PECL/mysqlnd_ms 1.3.0-beta the plugin is capable of transparently controlling
PECL/mysqlnd_ms 1.1.0-alpha or newer to cache a read-only query if explicitly
allowed by setting an appropriate quality of service through
<function>mysqlnd_ms_set_qos</function>. Please, see the
As of <literal>PECL/mysqlnd_ms</literal> 1.3.0-beta the plugin is
capable of transparently controlling <literal>PECL/mysqlnd_ms</literal> 1.1.0-alpha
or newer to cache a read-only query if explicitly allowed by setting an
appropriate quality of service through <function>mysqlnd_ms_set_qos</function>. P
lease, see the
<link linkend="mysqlnd-ms.quickstart.cache">quickstart</link> for a code example.
Both plugins must be installed, PECL/mysqlnd_ms must be compiled to support the
cache feature and PHP 5.4.0 or newer has to be used.
Both plugins must be installed, <literal>PECL/mysqlnd_ms</literal>
must be compiled to support the cache feature and PHP 5.4.0 or newer has to be used.
</para>
<para>
Applications have full control of cache usage and can request fresh data
@ -1667,7 +1674,7 @@ Transient error retries before error: 2
relaxed to eventual consistency the cache can be used again.
</para>
<para>
If caching is enabled for a read-only statement, PECL/mysqlnd_ms may inject
If caching is enabled for a read-only statement, <literal>PECL/mysqlnd_ms</literal> may inject
<link linkend="mysqlnd-qc.quickstart.caching">SQL hints to control caching</link>
by PECL/mysqlnd_qc. It may modify the SQL statement it got from the application.
Subsequent SQL processors are supposed to ignore the SQL hints. A SQL hint is a
@ -1735,7 +1742,7 @@ Transient error retries before error: 2
</listitem>
<listitem>
<simpara>
Inject the appropriate SQL hints to enable caching by PECL/mysqlnd_qc.
Inject the appropriate SQL hints to enable caching by <literal>PECL/mysqlnd_qc</literal>.
</simpara>
</listitem>
<listitem>
@ -1746,9 +1753,10 @@ Transient error retries before error: 2
</listitem>
<listitem>
<simpara>
PECL/mysqlnd_qc is loaded after PECL/mysqlnd_ms by PHP. Thus, it will see
all query modifications of PECL/mysqlnd_ms and cache the query if instructed
to do so.
<literal>PECL/mysqlnd_qc</literal> is loaded after
<literal>PECL/mysqlnd_ms</literal> by PHP. Thus, it will see
all query modifications of <literal>PECL/mysqlnd_ms</literal> and cache
the query if instructed to do so.
</simpara>
</listitem>
</itemizedlist>
@ -2124,6 +2132,201 @@ mysqlnd_ms.disable_rw_split=1
help to reduce collision rates and thus improve performance.
</para>
</section>
<section xml:id="mysqlnd-ms.concept_xa_trx">
<title>XA/Distributed transactions</title>
<note>
<title>Version requirement</title>
<para>
XA related functions have been introduced in <literal>PECL/mysqlnd_ms</literal> version 1.6.0-alpha.
</para>
</note>
<note>
<title>Early adaptors wanted</title>
<para>
The feature is currently under development. There may be issues and/or
feature limitations. Do not use in production environments, although
early lab tests indicate reasonable quality.
</para>
<para>
Please, contact the development team if you are interested in this feature.
We are looking for real life feedback to complement the feature.
</para>
<para>
Below is a list of some feature restrictions.
<itemizedlist>
<listitem>
<para>The feature is not yet compatible with the MySQL Fabric support . This limitation is soon to be lifted.</para>
<para>XA transaction identifier are currently restricted to numbers. This limitation will be lifted upon request, it is a simplification used during the initial implementation.</para>
</listitem>
</itemizedlist>
</para>
</note>
<note>
<title>MySQL server restrictions</title>
<para>
The XA support by the MySQL server has some restrictions. Most noteably,
the servers binary log may lack changes made by XA transactions in case
of certain errors. Please, see the MySQL manual for details.
</para>
</note>
<para>
XA/Distributed transactions can spawn multiple MySQL servers.
Thus, they may seem like a perfect
tool for sharded MySQL clusters, for example, clusters managed with MySQL Fabric.
<literal>PECL/mysqlnd_ms</literal> hides most of the SQL commands
to control XA transactions and performs automatic administrative tasks in cases
of errors, to provide the user with a comprehensive API. Users should
setup the plugin carefully and be well aware of server restrictions prior
to using the feature.
</para>
<para>
<example>
<title>General pattern for XA transactions</title>
<programlisting role="php">
<![CDATA[
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
/* BEGIN */
mysqlnd_ms_xa_begin($mysqli, 1 /* xa id */);
/* run queries on various servers */
$mysqli->query("UPDATE some_table SET col_a = 1");
...
/* COMMIT */
mysqlnd_ms_xa_commit($link, 1);
?>
]]>
</programlisting>
</example>
</para>
<para>
XA transactions use the two-phase commit protocol. The two-phase commit
protocol is a blocking protocol. During the first phase participating servers
begin a transaction and the client carries out its work. This phase is followed
by a second voting phase. During voting, the servers first make a firm promise
that they are ready to commit the work even in case of their possible unexpected
failure. Should a server crash in this phase, it will still recall the aborted
transaction after recover and wait for the client to decide on whether
it shall be committed or rolled back.
</para>
<para>
Should a client that has initiated a global transaction crash after all the
participating servers gave their promise to be ready to commit, then the servers
must wait for a decision. The servers are not allowed to uniliterally decide on the
transaction.
</para>
<para>
A client crash or disconnect from a participant, a server crash or server error
during the fist phase of the protocol is uncritical. In most cases, the server
will forget about the XA transaction and its work is rolled back. Additionally,
the plugin tries to reach out to as many participants as it can to instruct
the server to roll back the work immediately. It is not possible to disable this implicit
rollback carried out by <literal>PECL/mysqlnd_ms</literal> in case of errors
during the first phase of the protocol. This design decision has been made to
keep the implementation simple.
</para>
<para>
An error during the second phase of the commit protocol can develop into a
more severe situation. The servers will not forget about
prepared but unfinished transactions in all cases. The plugin will not
attempt to solve these cases immediately but waits for optional background
garbage collection to ensure progress of the commit protocol. It is assumed
that a solution will take significant time as it may include waiting
for a participating server to recover from a crash. This time span may
be longer than a developer and end user expects when trying to commit a
global transaction with <function>mysqlnd_ms_xa_commit</function>. Thus,
the function returns with the unfinished global transaction still
requiring attention. Please, be warned that at this point, it is not yet
clear whether the global transaction will be committed or rolled back later on.
</para>
<para>
Errors during the second phase can be ignored, handled by yourself or solved
by the build-int garbage collection logic. Ignoring them is not recommended
as you may experience unfinished global transactions on your servers that block
resources virtually indefinetly. Handling the errors requires knowing the
participants, checking their state and issueing appropriate SQL commands on them.
There are no user API calls to expose this very information. You will have to
configure a state store and make the plugin record its actions in it to receive
the desired facts.
</para>
<para>
Please, see the
<link linkend="mysqlnd-ms.quickstart.xa_transactions">quickstart</link> and
related <link linkend="ini.mysqlnd-ms-plugin-config-v2.xa.state-store">plugin
configuration file settings</link> for an example how to configure a state.
In addition to configuring a state store, you have to setup some SQL tables.
The table definitions are given in the description of the plugin configuration
settings.
</para>
<para>
Setting up and configuring a state store is also a precondition for using the
built-in garbage collection for XA transactions that fail during the
second commit phase. Recording information about ongoing XA transactions is
an unavoidable extra task. The extra task consists of updating the state
store after each and every operation that changes the state of the global transaction
itself (started, committed, rolled back, errors and aborts), the addition of
participants (host, optionally user and password required to connect) and any
changes to a participants state. Please note, depending on configuration and your
security policies, these recordings may be considered sensitive.
It is therefore recommended to restrict access to the state store. Unless the
state store itself becomes overloaded, writing the state information may contribute
noteworthy to the runtime but should overall be only a minor factor.
</para>
<para>
It is possible that the effort it takes to implement your own routines for handling
XA transactions that failed during the second commit phase exceeds the benefits
of using the XA feature of <literal>PECL/mysqlnd_ms</literal> in the first place.
Thus, the manual focussed on using the built-on garbage collection only.
</para>
<para>
Garbage collection can be triggered manually or automatically in the background.
You may want to call <function>mysqlnd_ms_xa_gc</function> immediately after
a commit failure to attempt to solve any failed but still open global transactions
as soon as possible. You may also decide to disable the automatic background
garbage collection, implement your own rule set for invoking the built-in
garbage collection and trigger it when desired.
</para>
<para>
By default the plugin will start the garbage collection with a certain probability
in the extensions internal <literal>RSHUTDOWN</literal> method. The request
shutdown is called after your script finished. Whether the garbage collection
will be triggered is determined by computing a random value between
<literal>1...1000</literal> and comparing it with the configuration setting
<link linkend="ini.mysqlnd-ms-plugin-config-v2.xa.gc"><literal>probability</literal></link>
(default: 5). If the setting is
greater or equal to the random value, the garbage collection will be triggered.
</para>
<para>
Once started, the garbage collection acts upon up to
<literal>max_transactions_per_run</literal> (default: 100) global transactions
recorded. Records include successfully finished but also unfinished XA
transactions. Records for successful transactions are removed and unfinished
transactions are attempted to be solved. There are no statistics that help
you finding the right balance between keeping garbage collection runs short
by limiting the number of transactions considered per run and preventing the garbage
collection to fall behind, resulting in many records.
</para>
<para>
For each failed XA transaction the garbage collection makes
<literal>max_retries</literal> (default: 5) attempts to finish it. After that
<literal>PECL/mysqlnd_ms</literal> gives up and the XA transaction must be
cleaned up by a human operator. There are two possible reasons for this. Either
a participating server crashed and has not become accessible again within
<literal>max_retries</literal> invocations of the garbage collection, or there
is a situation that the built-in garbage collection cannot cope with. Likely, the
latter would be considered a bug.
</para>
<para>
The function <link linkend="function.mysqlnd-ms-get-stats"><function>mysqlnd_ms_get_stats</function></link>
provides some statistics on how many XA transactions have been started,
committed, failed or rolled back.
</para>
</section>
</chapter>
<!-- Keep this comment at the end of the file

View file

@ -517,6 +517,83 @@
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_begin</literal>
</entry>
<entry>
How many XA/distributed transactions have been started
using <function>mysqlnd_ms_xa_begin</function>.
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_commit_success</literal>
</entry>
<entry>
How many XA/distributed transactions have been successfully committed
using <function>mysqlnd_ms_xa_commit</function>.
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_commit_failure</literal>
</entry>
<entry>
How many XA/distributed transactions failed to commit
during <function>mysqlnd_ms_xa_commit</function>.
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_rollback_success</literal>
</entry>
<entry>
How many XA/distributed transactions have been successfully rolled back
using <function>mysqlnd_ms_xa_rollback</function>. The figure does
not include implict rollbacks performed as a result of
<function>mysqlnd_ms_xa_commit</function> failure.
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_rollback_failure</literal>
</entry>
<entry>
How many XA/distributed transactions could not be rolled back.
This includes failures of <function>mysqlnd_ms_xa_rollback</function>
but also failured during rollback when closing a connection, if
<literal>rollback_on_close</literal> is set. Please, see also
<literal>xa_rollback_on_close</literal> below.
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_participants</literal>
</entry>
<entry>
Total number of participants in any XA transaction started with
<function>mysqlnd_ms_xa_begin</function>.
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>xa_rollback_on_close</literal>
</entry>
<entry>
How many XA transactions have been rolled back implicitly when
a connection was close and <literal>rollback_on_close</literal> is set.
Depending on your coding policies, this may hint a flaw in your code as
you may prefer to explicitly clean up resources.
</entry>
<entry>Since 1.6.0.</entry>
</row>
</tbody>
</tgroup>
</informaltable>

View file

@ -148,6 +148,9 @@
<member>
<link linkend="mysqlnd-ms.configuration">Runtime configuration</link>
</member>
<member>
<link linkend="function.mysqlnd-ms-get-stats"><function>mysqlnd_ms_get_stats</function></link>
</member>
</simplelist>
</para>
</refsect1>

View file

@ -80,6 +80,9 @@
<member>
<link linkend="mysqlnd-ms.configuration">Runtime configuration</link>
</member>
<member>
<link linkend="function.mysqlnd-ms-get-stats"><function>mysqlnd_ms_get_stats</function></link>
</member>
</simplelist>
</para>
</refsect1>

View file

@ -100,6 +100,9 @@
<member>
<link linkend="ini.mysqlnd-ms-plugin-config-v2.xa">State store configuration</link>
</member>
<member>
<link linkend="function.mysqlnd-ms-get-stats"><function>mysqlnd_ms_get_stats</function></link>
</member>
</simplelist>
</para>
</refsect1>

View file

@ -75,6 +75,9 @@
<member>
<link linkend="mysqlnd-ms.configuration">Runtime configuration</link>
</member>
<member>
<link linkend="function.mysqlnd-ms-get-stats"><function>mysqlnd_ms_get_stats</function></link>
</member>
</simplelist>
</para>
</refsect1>

View file

@ -1034,7 +1034,7 @@ Warning: mysqlnd_ms_xa_begin(): (mysqlnd_ms) Some work is done outside global tr
Please, make sure to use a transactional and crash-safe
storage engine for the tables, such as InnoDB. InnoDB is the default
table engine in recent versions of the MySQL server. Make also sure
the database server itself is higly available.
the database server itself is highly available.
</para>
<para>
If a state store has been configured, the plugin can perform a garbage collection.

View file

@ -3011,7 +3011,7 @@ CREATE TABLE mysqlnd_ms_xa_gc (
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.xa.gc">
<term>garbage_collection</term>
<listitem>
<variablelist>
@ -3026,6 +3026,15 @@ CREATE TABLE mysqlnd_ms_xa_gc (
it can be supposed to be significantly higher than <literal>100</literal>.
Available since 1.6.0.
</para>
<para>
Please note, it is important to end failed XA
transactions within reasonable time to make participating servers
free resources bound to the transaction. The built-in garbage
collection is not expected to fail for a long period as
long as crashed servers become available again quickly.
Still, a situation may arise where a human is required to
act because the built-in garbage collection stopped or failed.
</para>
<para>
Default: <literal>5</literal>
</para>