Quickstart addition, outline of XA related setup and one of the XA transaction related functions.

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@334062 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Ulf Wendel 2014-07-01 17:17:37 +00:00
parent ef28865843
commit 5e6265f846
5 changed files with 836 additions and 22 deletions

View file

@ -87,6 +87,38 @@
<para>
Feature changes
<itemizedlist>
<listitem>
<para>
Added a basic distributed transaction abstraction.
XA transactions can are supported ever since using standard SQL calls.
This is inconvenient as XA participants must be managed manually.
PECL/mysqlnd_ms introduces API calls to control XA transaction among MySQL servers.
When using the new functions, PECL/mysqlnd_ms acts as a transaction coordinator.
After starting a distributed transaction, the plugin tracks all servers
involved until the transaction is ended and issues appropriate SQL statements
on the XA participants.
</para>
<para>
This is useful, for example, when using Fabric and sharding. When using
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.
</para>
</listitem>
<listitem>
<para>
Introduced automatic retry loop for
<link linkend="mysqlnd-ms.transient_errors">transient errors</link> and
<link linkend="function.mysqlnd-ms-get-stats">corresponding statistic</link>
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.
</para>
</listitem>
<listitem>
<para>
Introduced automatic retry loop for

View file

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 327381 $ -->
<refentry xml:id="function.mysqlnd-ms-xa-begin" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<refnamediv>
<refname>mysqlnd_ms_xa_begin</refname>
<refpurpose>Starts a distributed/XA transaction among MySQL servers</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<type>int</type>
<methodname>mysqlnd_ms_xa_begin</methodname>
<methodparam><type>mixed</type><parameter>connection</parameter></methodparam>
<methodparam><type>string</type><parameter>gtrid</parameter></methodparam>
</methodsynopsis>
<para>
Starts a XA transaction among MySQL servers. PECL/mysqlnd_ms acts as a transaction
coordinator the distributed transaction.
</para>
<para>
Once a global transaction has been started, the plugin injects appropriate
<literal>XA BEGIN</literal> SQL statements on all MySQL servers used in the following.
The global transaction is either ended by calling <function>mysqlnd_ms_xa_commit</function>,
<function>mysqlnd_ms_xa_rollback</function> or by an implicit rollback in case
of an error.
</para>
<para>
During a global transaction, the plugin tracks all server switches,
for example, when switching from one MySQL shard to another MySQL shard.
Immediately before a query is run on a server that has not been participating
in the global transaction yet, <literal>XA BEGIN</literal> is executed on
the server. From a users perspective the injection happens during a call to a
query execution function such as <function>mysqli_query</function>. Should
the injection fail an error is reported to the caller of the query execution
function. The failing server does not become a participant in the global
transaction. The user may retry executing a query on the server and hereby retry
injecting <literal>XA BEGIN</literal>, abort the global transaction because
not all required servers can participat or, ignore continue the global without
the failed server.
</para>
<para>
Reasons to fail executing <literal>XA BEGIN</literal> include but are not limited to
a server being unreachable or the server having an open, concurrent
XA transaction using the same xid.
</para>
<para>
Please note, global and local transactions
are mutually exclusive. You cannot start a XA transaction when you have a local
transaction open. The local transaction must be ended first. The plugin tries
to detect this conflict as early as possible. It monitors API calls for controlling
local transactions to learn about the current state. However, if using
SQL statements for local transactions such as <literal>BEGIN</literal>, the
plugin may not know the current state and the conflict is not detected
before <literal>XA BEGIN</literal> is injected and executed.
</para>
<para>
The use of other XA resources but MySQL servers is not supported by
the function. To carry out a global transaction among, for example,
a MySQL server and another vendors database system, you should issue
the systems SQL commands yourself.
</para>
<note>
<title>Experimental</title>
<para>
The feature is currently under development. There may be issues and/or
feature limitations. Do not use in production environments.
</para>
</note>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<variablelist>
<varlistentry>
<term><parameter>connection</parameter></term>
<listitem>
<para>
A MySQL connection handle obtained from any of the
connect functions of the <link linkend="ref.mysqli">mysqli</link>,
<link linkend="ref.mysql">mysql</link> or
<link linkend="ref.pdo-mysql">PDO_MYSQL</link> extensions.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>gtrid</parameter></term>
<listitem>
<para>
Global transaction identifier (gtrid). The gtrid is a binary string
upto 64 bytes long. Please note, depending on your character set settings,
64 characters may require more than 64 bytes to store.
</para>
<para>
In accordance with the MySQL SQL syntax,
XA transactions use identifiers made of three parts. An xid consists of a
global transaction identifier (gtrid), a branch qualifier (bqual) and a
format identifier (formatID). Only the global transaction identifier can
and needs to be set.
</para>
<para>
The branch qualifier and format identifier are set automatically. The details
should be considered implementation dependent, which may change without
prior notice. In version 1.6 the branch qualifier is consecutive number
which is incremented whenever a participant joins the global transaction.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
Returns &true; if there is no open local or global transaction and a new global
transaction can be started. Otherwise, returns &false;
</para>
</refsect1>
<refsect1 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member>
<link linkend="mysqlnd-ms.quickstart.xa_transactions">Quickstart XA/Distributed transactions</link>
</member>
<member>
<link linkend="mysqlnd-ms.configuration">Runtime configuration</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
-->

View file

@ -215,7 +215,7 @@ mysqlnd_ms.config_file=/path/to/mysqlnd_ms_plugin.ini
<link linkend="ref.mysql">mysql</link>, and
<link linkend="ref.pdo-mysql">PDO_MYSQL</link>) that is
compiled to use the <link linkend="book.mysqlnd">mysqlnd</link> library.
PECL/mysqlnd_ms plugs into the <link linkend="book.mysqlnd">mysqlnd</link> library.
<literal>PECL/mysqlnd_ms</literal> plugs into the <link linkend="book.mysqlnd">mysqlnd</link> library.
It does not change the API or behavior of those extensions.
</para>
<para>
@ -285,7 +285,7 @@ $mysql = mysql_connect("myapp", "username", "password");
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. The is not a general limitation. As of PECL/mysqlnd_ms 1.1.0,
file section. The is not a general limitation. As of <literal>PECL/mysqlnd_ms</literal> 1.1.0,
it is possible to set the
<link linkend="mysqlnd-ms.plugin-ini-json.server-config-keywords">username</link> and
<link linkend="mysqlnd-ms.plugin-ini-json.server-config-keywords">password</link> for any server in the
@ -622,7 +622,7 @@ $mysqli->close();
</section>
<section xml:id="mysqlnd-ms.quickstart.transactions">
<title>Transactions</title>
<title>Local transactions</title>
<para>
The current version of the plugin is not transaction safe by default,
because it is not aware of running transactions in all cases. SQL transactions are
@ -731,7 +731,7 @@ $mysqli->close();
</para>
<para>
API based transaction boundary detection has been improved with PHP 5.5.0 and
PECL/mysqlnd_ms 1.5.0 to cover not only calls to <function>mysqli_autocommit</function>
<literal>PECL/mysqlnd_ms</literal> 1.5.0 to cover not only calls to <function>mysqli_autocommit</function>
but also <function>mysqli_begin</function>,
<function>mysqli_commit</function> and <function>mysqli_rollback</function>.
</para>
@ -819,6 +819,236 @@ $mysqli->close();
section.
</para>
</section>
<section xml:id="mysqlnd-ms.quickstart.xa_transactions">
<title>XA/Distributed Transactions</title>
<note>
<title>Version requirement</title>
<para>
XA related functions have been introduced in PECL mysqlnd_ms version 1.6.0-alpha.
</para>
</note>
<note>
<title>Experimental</title>
<para>
The feature is currently under development. There may be issues and/or
feature limitations. Do not use in production environments.
</para>
</note>
<para>
XA transactions are a standardized method for executing transactions across
multiple resources. Those resources can be databases or other transactional
systems. The MySQL server supports XA SQL statements which allows users
to carry out a distributed SQL transaction that spawns multiple database servers
or any kind as long as they support the SQL statements too. In such a scenario
it is in the responsibility of the user to coordinate the participating
servers.
</para>
<para>
<literal>PECL/mysqlnd_ms</literal> can act as a transaction coordinator for a global (distributed, XA)
transaction carried out on MySQL servers only. As a transaction coordinator, the plugin
tracks all servers involved in a global transaction and transparently issues
appropriate SQL statements on the participants. The global transactions are controlled with
<function>mysqlnd_ms_xa_begin</function>, <function>mysqlnd_ms_xa_commit</function>
and <function>mysqlnd_ms_xa_rollback</function>. SQL details are mostly hidden from
the application as is the need to track and coordinate participants.
</para>
<para>
<example>
<title>General pattern for XA 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()));
/* start a global transaction */
$gtrid_id = "12345";
if (!mysqlnd_ms_xa_begin($mysqli, $gtrid_id)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* run queries as usual: XA BEGIN will be injected upon running a query */
if (!$mysqli->query("INSERT INTO orders(order_id, item) VALUES (1, 'christmas tree, 1.8m')")) {
/* Either INSERT failed or the injected XA BEGIN failed */
if ('XA' == substr($mysqli->sqlstate, 0, 2)) {
printf("Global transaction/XA related failure, [%d] %s\n", $mysqli->errno, $mysqli->error);
} else {
printf("INSERT failed, [%d] %s\n", $mysqli->errno, $mysqli->error);
}
/* rollback global transaction */
mysqlnd_ms_xa_rollback($mysqli, $xid);
die("Stopping.");
}
/* continue carrying out queries on other servers, e.g. other shards */
/* commit the global transaction */
if (!mysqlnd_ms_xa_commit($mysqli, $xa_id)) {
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Unlike with local transactions, which are carried out on a single server,
XA transactions have an identifier (xid) associated with them.
The XA transaction identifier is composed of a global transaction
identifier (gtrid), a branch qualifier (bqual)
a format identifier (formatID). Only the global transaction identifier can
and must be given when calling any of the plugins XA functions.
</para>
<para>
Once a global transaction has been started, the plugin begins tracking servers
until the global transaction ends. When a server is picked for query execution,
the plugin injects the SQL statement <literal>XA BEGIN</literal> prior to
executing the actual SQL statement on the server. <literal>XA BEGIN</literal>
makes the server participate in the global transaction. If the injected
SQL statement fails, the plugin will report the issue in reply to the query
execution function that was used. In the above example,
<literal>$mysqli->query("INSERT INTO orders(order_id, item) VALUES (1, 'christmas tree, 1.8m')")</literal>
would indicate such an error. You may want to check the errors SQL state code to
determine whether the actual query (here: <literal>INSERT</literal>) has failed
or the error is related to the global transaction. It is up to you to ignore the
failure to start the global transaction on a server and continue execution
without having the server participate in the global transaction.
</para>
<para>
<example>
<title>Local and global transactions are mutually exclusive</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()));
/* start a local transaction */
if (!$mysqli->begin_transaction())
die(sprintf("[%d/%s] %s\n", $mysqli->errno, $mysqli->sqlstate, $mysqli->error));
/* cannot start global transaction now - must end local transaction first */
$gtrid_id = "12345";
if (!mysqlnd_ms_xa_begin($mysqli, $gtrid_id)) {
die(sprintf("[%d/%s] %s\n", $mysqli->errno, $mysqli->sqlstate, $mysqli->error));
}
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Warning: mysqlnd_ms_xa_begin(): (mysqlnd_ms) Some work is done outside global transaction. You must end the active local transaction first in ... on line ...
[1400/XAE09] (mysqlnd_ms) Some work is done outside global transaction. You must end the active local transaction first
]]>
</screen>
</example>
</para>
<para>
A global transaction cannot be started when a local transaction is active.
The plugin tries to detect this situation as early as possible, that is when
<function>mysqlnd_ms_xa_begin</function> is called. If using API calls only to
control transactions, the plugin will know that a local transaction is open and
return an error for <function>mysqlnd_ms_xa_begin</function>. However, note the
plugins <link linkend="mysqlnd-ms.transaction">limitations on detecting
transaction boundaries.</link>. In the worst case, if using direct SQL
for local transactions (<literal>BEGIN</literal>,
<literal>COMMIT</literal>, ...), it may happen that an error is delayed
until some SQL is executed on a server.
</para>
<para>
To end a global transaction invoke <function>mysqlnd_ms_xa_commit</function> or
<function>mysqlnd_ms_xa_rollback</function>. When a global transaction is ended
all participants must be informed of the end. Therefore, PECL/mysqlnd_ms
transparently issues appropriate XA related SQL statements
on some or all of them. Any failure during this phase will cause an implicit
rollback. The XA related API is intentionally kept simple here. A more
complex API that gave more control would bare few, if any, advantages over
a user implementation that issues all lower level XA SQL statements itself.
</para>
<para>
XA transactions use the two-phase commit protocol. The two-phase commit
protocol is a blocking protocol. There are cases when no progress can
be made, not even when using timeouts. Transaction coordinators
should survive their own failure, be able to detect blockades and break ties.
<literal>PECL/mysqlnd_ms</literal> takes the role of a transaction coordinator and can be
configured to survive its own crash to avoid issues with blocked MySQL servers.
Therefore, the plugin can and should be configured to use a persistent and crash-safe state
to allow garbage collection of unfinished, aborted global transactions.
A global transaction can be aborted in an open state if either the plugin fails (crashes)
or a connection from the plugin to a global transaction participant fails.
</para>
<para>
<example>
<title>Transaction coordinator state store</title>
<programlisting role="ini">
<![CDATA[
{
"myapp": {
"xa": {
"state_store": {
"participant_localhost_ip": "192.168.2.12",
"mysql": {
"host": "192.168.2.13",
"user": "root",
"password": "",
"db": "test",
"port": "3312",
"socket": null
}
}
},
"master": {
"master_0": {
"host": "localhost",
"socket": "\/tmp\/mysql.sock"
}
},
"slave": {
"slave_0": {
"host": "192.168.2.14",
"port": "3306"
}
}
}
}
]]>
</programlisting>
</example>
</para>
<para>
Currently, <literal>PECL/mysqlnd_ms</literal> supports only using MySQL database tables
as a state store. The SQL definitions of the tables are given in the
<link linkend="ini.mysqlnd-ms-plugin-config-v2.xa">plugin configuration section.</link>
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.
</para>
<para>
If a state store has been configured, the plugin can perform a garbage collection.
During garbage collection it may be necessary to connect to a participant
of a failed global transaction. Thus, the state store holds a list of participants
and, among others, their host names. If the garbage collection is run
on another host but the one that has written a participant entry with the
host name <literal>localhost</literal>, then <literal>localhost</literal>
resolves to different machines. There are two solutions to the problem.
Either you do not configure any servers with the host name <literal>localhost</literal> but
configure an IP address (and port) or, you hint the garbage collection.
In the above example, <literal>localhost</literal> is used for
<literal>master_0</literal>, hence it may not resolve to the correct
host during garbage collection. However, <literal>participant_localhost_ip</literal>
is also set to hint the garbage collection that <literal>localhost</literal>
stands for the IP <literal>192.168.2.12</literal>.
</para>
</section>
<section xml:id="mysqlnd-ms.quickstart.qos-consistency">
<title>Service level and consistency</title>
<note>
@ -1116,14 +1346,14 @@ PHP Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last f
</para>
<para>
As of MySQL 5.6.5-m8 release candidate 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. However, the final feature set found in MySQL 5.6 production releases to date is not
sufficient to support the ideas discussed below in all cases. Please, see also the
<link linkend="mysqlnd-ms.gtid">concepts section</link>.
</para>
</note>
<para>
PECL/mysqlnd_ms can either use its own global transaction ID emulation or the
<literal>PECL/mysqlnd_ms</literal> can either use its own global transaction ID emulation or the
global transaction ID feature built-in to MySQL 5.6.5-m8 or later. From a developer
perspective the client-side and server-side approach offer the same features with
regards to service levels provided by PECL/mysqlnd_ms. Their differences
@ -1131,7 +1361,7 @@ PHP Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last f
</para>
<para>
The quickstart first demonstrates the use of the client-side global transaction ID emulation
built-in to PECL/mysqlnd_ms before its show how to use the server-side counterpart.
built-in to <literal>PECL/mysqlnd_ms</literal> before its show how to use the server-side counterpart.
The order ensures that the underlying idea is discussed first.
</para>
<para>
@ -1148,7 +1378,7 @@ PHP Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last f
already.
</para>
<para>
PECL/mysqlnd_ms can inject SQL for every committed transaction to increment a GTID counter.
<literal>PECL/mysqlnd_ms</literal> can inject SQL for every committed transaction to increment a GTID counter.
The so created GTID is accessible by the application to identify an applications
write operation. This enables the plugin to deliver session consistency (read your writes)
service level by not only querying masters but also slaves which have replicated
@ -1545,7 +1775,7 @@ var_dump($res->fetch_assoc());
</note>
<para>
Databases clusters can deliver different levels of consistency. As of
PECL/mysqlnd_ms 1.2.0 it is possible to advice the plugin to consider only
<literal>PECL/mysqlnd_ms</literal> 1.2.0 it is possible to advice the plugin to consider only
cluster nodes that can deliver the consistency level requested. For example,
if using asynchronous MySQL Replication with its cluster-wide eventual
consistency, it is possible to request session consistency (read your writes)

View file

@ -421,7 +421,7 @@ Fatal error: Call to a member function fetch_assoc() on a non-object in Command
to set the error type used to display buffered errors. By default an error
of type <literal>E_WARNING</literal> will be emitted.
</para>
<para>
<para>
<example>
<title>Improved configuration file validation since 1.5.0</title>
<programlisting role="php">
@ -731,7 +731,7 @@ Warning: mysqli::mysqli(): (mysqlnd_ms) Exclusive usage of configuration enforce
</entry>
<entry>Since 1.2.0.</entry>
</row>
<row>
<row>
<entry>
<literal>wait_for_gtid_timeout</literal>
</entry>
@ -912,7 +912,7 @@ Warning: mysqli::mysqli(): (mysqlnd_ms) Exclusive usage of configuration enforce
<function>mysqlnd_ms_fabric_select_global</function></link>,
set the boolean flag <literal>trx_warn_server_list_changes</literal>.
</para>
<para>
<para>
<example>
<title>Warnings about the violation of transaction boundaries</title>
<programlisting role="ini">
@ -1560,8 +1560,8 @@ PHP Warning: mysqli::query(): Couldn't fetch mysqli in filter_warning.php on li
</tbody>
</tgroup>
</informaltable>
<para>
<example>
<para>
<example>
<title>Using a callback</title>
<programlisting role="ini">
<![CDATA[
@ -1766,7 +1766,6 @@ function pick_server($connected, $query, $masters, $slaves, $last_used_connectio
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.filter-node-groups">
<term>
Filter: <parameter>node_groups</parameter>
@ -1783,7 +1782,7 @@ function pick_server($connected, $query, $masters, $slaves, $last_used_connectio
must be followed by other filters to reduce the number of candidates
down to one for statement execution.
</para>
<informaltable>
<informaltable>
<tgroup cols="3">
<colspec colwidth="1*"/>
<colspec colwidth="7*"/>
@ -1797,10 +1796,10 @@ function pick_server($connected, $query, $masters, $slaves, $last_used_connectio
</thead>
<tbody>
<row>
<entry>
<literal>user defined node group name</literal>
</entry>
<entry>
<entry>
<literal>user defined node group name</literal>
</entry>
<entry>
<para>
One or more node groups must be defined. A node group can have an
arbitrary user defined name. The name is used in combination with
@ -2046,6 +2045,7 @@ function pick_server($connected, $query, $masters, $slaves, $last_used_connectio
</informaltable>
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.failover">
<term>
<parameter>failover</parameter>
@ -2233,6 +2233,7 @@ function pick_server($connected, $query, $masters, $slaves, $last_used_connectio
</para>
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.lazy-connections">
<term>
<parameter>lazy_connections</parameter>
@ -2294,6 +2295,7 @@ function pick_server($connected, $query, $masters, $slaves, $last_used_connectio
</para>
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.server-charset">
<term>
<parameter>server_charset</parameter>
@ -2396,6 +2398,7 @@ $mysqli->set_charset("latin1");
</para>
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.master-on-write">
<term>
<parameter>master_on_write</parameter>
@ -2453,6 +2456,7 @@ $mysqli->set_charset("latin1");
</para>
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.trx-stickiness">
<term>
<parameter>trx_stickiness</parameter>
@ -2724,10 +2728,401 @@ $mysqli->set_charset("latin1");
</listitem>
</varlistentry>
<varlistentry xml:id="ini.mysqlnd-ms-plugin-config-v2.xa">
<term>
<parameter>xa</parameter>
<type>object</type>
</term>
<listitem>
<para>
The setting has been introduced in 1.6.0.
</para>
<para>
<note>
<title>Experimental</title>
<para>
The feature is currently under development. There may be issues and/or
feature limitations. Do not use in production environments.
</para>
</note>
</para>
<informaltable>
<tgroup cols="2">
<colspec colwidth="2*"/>
<colspec colwidth="8*"/>
<thead>
<row>
<entry>Keyword</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>state_store</literal>
</entry>
<entry>
<informaltable>
<tgroup cols="2">
<colspec colwidth="2*"/>
<colspec colwidth="8*"/>
<thead>
<row>
<entry>Keyword</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>record_participant_credentials</literal>
</entry>
<entry>
<para>
Whether to store the username and password of a global transaction
participant in the participants table. If disabled, the garbage
collection will use the default username and password when connecting
to the participants. Unless you are using a different username and
password for each of your MySQL servers, you can use the default
and avoid storing the sensible information in state store.
</para>
<para>
Please note, username and password are stored in clear text when using
the MySQL state store, which is the only one available. It is in your
responsibility to protect this sensible information.
</para>
<para>
Default: <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>participant_localhost_ip</literal>
</entry>
<entry>
<para>
During XA garbage collection the plugin may find a participant server
for which the host <literal>localhost</literal>
has been recorded. If the garbage collection takes place on another host
but the host that has written the participant record to the state store,
the host name <literal>localhost</literal> now resolves to a different
host. Therefore, when recording a participant servers host name
in the state store, a value of <literal>localhost</literal> must
be replaced with the actual IP address of <literal>localhost</literal>.
</para>
<para>
Setting <literal>participant_localhost_ip</literal> should be considered
only if using <literal>localhost</literal> cannot be avoided.
From a garbage collection point of view only, it is preferrable not to
configure any socket connection but to provide an IP address and port
for a node.
</para>
</entry>
</row>
<row>
<entry>
<literal>mysql</literal>
</entry>
<entry>
<para>
The MySQL state store is the only state store available.
</para>
<informaltable>
<tgroup cols="2">
<colspec colwidth="2*"/>
<colspec colwidth="8*"/>
<thead>
<row>
<entry>Keyword</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>global_trx_table</literal>
</entry>
<entry>
<para>
Name of the MySQL table used to store the state of an ongoing or aborted
global transaction. Use the below SQL statement to create the table.
Make sure to edit the table name to match your configuration.
</para>
<para>
<example>
<title>SQL definition for the MySQL state store transaction table</title>
<programlisting role="sql">
<![CDATA[
CREATE TABLE mysqlnd_ms_xa_trx (
store_trx_id int(11) NOT NULL AUTO_INCREMENT,
gtrid int(11) NOT NULL,
format_id int(10) unsigned NOT NULL DEFAULT '1',
state enum('XA_NON_EXISTING','XA_ACTIVE','XA_IDLE','XA_PREPARED','XA_COMMIT','XA_ROLLBACK') NOT NULL DEFAULT 'XA_NON_EXISTING',
intend enum('XA_NON_EXISTING','XA_ACTIVE','XA_IDLE','XA_PREPARED','XA_COMMIT','XA_ROLLBACK') DEFAULT 'XA_NON_EXISTING',
finished enum('NO','SUCCESS','FAILURE') NOT NULL DEFAULT 'NO',
modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
started datetime DEFAULT NULL,
timeout datetime DEFAULT NULL,
PRIMARY KEY (store_trx_id),
KEY idx_xa_id (gtrid,format_id,finished),
KEY idx_state (state)
) ENGINE=InnoDB
]]>
</programlisting>
</example>
</para>
<para>
Default: <literal>mysqlnd_ms_xa_trx</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>participant_table</literal>
</entry>
<entry>
<para>
Name of the MySQL table used to store participants of an ongoing or aborted
global transaction. Use the below SQL statement to create the table.
Make sure to edit the table name to match your configuration.
</para>
<para>
Storing credentials can be enabled and disabled using
<literal>record_participant_credentials</literal>
</para>
<para>
<example>
<title>SQL definition for the MySQL state store transaction table</title>
<programlisting role="sql">
<![CDATA[
CREATE TABLE mysqlnd_ms_xa_participants (
fk_store_trx_id int(11) NOT NULL,
bqual varbinary(64) NOT NULL DEFAULT '',
participant_id int(10) unsigned NOT NULL AUTO_INCREMENT,
server_uuid varchar(127) DEFAULT NULL,
scheme varchar(1024) NOT NULL,
host varchar(127) DEFAULT NULL,
port smallint(5) unsigned DEFAULT NULL,
socket varchar(127) DEFAULT NULL,
user varchar(127) DEFAULT NULL,
password varchar(127) DEFAULT NULL,
state enum('XA_NON_EXISTING','XA_ACTIVE','XA_IDLE','XA_PREPARED','XA_COMMIT','XA_ROLLBACK')
NOT NULL DEFAULT 'XA_NON_EXISTING',
health enum('OK','GC_DONE','CLIENT ERROR','SERVER ERROR') NOT NULL DEFAULT 'OK',
connection_id int(10) unsigned DEFAULT NULL,
client_errno smallint(5) unsigned DEFAULT NULL,
client_error varchar(1024) DEFAULT NULL,
modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (participant_id),
KEY idx_xa_bqual (bqual),
KEY idx_store_trx (fk_store_trx_id),
CONSTRAINT mysqlnd_ms_xa_participants_ibfk_1 FOREIGN KEY (fk_store_trx_id)
REFERENCES mysqlnd_ms_xa_trx (store_trx_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB
]]>
</programlisting>
</example>
</para>
<para>
Default: <literal>mysqlnd_ms_xa_participants</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>garbage_collection_table</literal>
</entry>
<entry>
<para>
Name of the MySQL table used to track and synchronize garbage collection runs.
Use the below SQL statement to create the table.
Make sure to edit the table name to match your configuration.
</para>
<para>
<example>
<title>SQL definition for the MySQL state store garbage collection table</title>
<programlisting role="sql">
<![CDATA[
CREATE TABLE mysqlnd_ms_xa_gc (
gc_id int(10) unsigned NOT NULL AUTO_INCREMENT,
gtrid int(11) NOT NULL,
format_id int(10) unsigned NOT NULL DEFAULT '1',
fk_store_trx_id int(11) DEFAULT NULL,
modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
attempts smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (gc_id),
KEY idx_store_trx (gtrid,format_id,fk_store_trx_id)
) ENGINE=InnoDB
]]>
</programlisting>
</example>
</para>
<para>
Default: <literal>mysqlnd_ms_xa_gc</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>host</literal>
</entry>
<entry>
<para>
Host name of the MySQL server.
</para>
</entry>
</row>
<row>
<entry>
<literal>user</literal>
</entry>
<entry>
<para>
Name of the user used to connect to the MySQL server.
</para>
</entry>
</row>
<row>
<entry>
<literal>password</literal>
</entry>
<entry>
<para>
Password for the MySQL server user.
</para>
</entry>
</row>
<row>
<entry>
<literal>db</literal>
</entry>
<entry>
<para>
Database that holds the garbage collection tables.
Please note, you have to create the garbage collection
tables prior to using the plugin. The tables will not be
created implicitly during runtime but garbage collection
will fail if the tables to not exist.
</para>
</entry>
</row>
<row>
<entry>
<literal>port</literal>
</entry>
<entry>
<para>
Port of the MySQL server.
</para>
</entry>
</row>
<row>
<entry>
<literal>socket</literal>
</entry>
<entry>
<para>
Unix domain socket of the MySQL server. Please note,
if you have multiple PHP servers each of them will
try to carry out garbage collection and need to be able
to connect to the state store. In this case, you may
prefer configuring an IP address and a port for
the MySQL state store server to ensure all PHP servers
can reach it.
</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</entry>
</row>
<row>
<entry>
<literal>garbage_collection</literal>
</entry>
<entry>
<informaltable>
<tgroup cols="3">
<colspec colwidth="1*"/>
<colspec colwidth="7*"/>
<colspec colwidth="2*"/>
<thead>
<row>
<entry>Keyword</entry>
<entry>Description</entry>
<entry>Version</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>max_retries</literal>
</entry>
<entry>
<para>
Maximum number of garbage collection runs before giving up.
Allowed values are from <literal>0</literal> to <literal>100</literal>.
A setting of <literal>0</literal> means no limit, unless
the state store enforces a limit. Should the state store enforce a limit,
it can be supposed to be significantly higher than <literal>100</literal>.
</para>
<para>
Default: <literal>5</literal>
</para>
</entry>
<entry>Since 1.6.0.</entry>
</row>
<row>
<entry>
<literal>probability</literal>
</entry>
<entry>
<para>
Garbage collection probability. Setting the value has not effect.
The feature is under development.
</para>
<para>
Default: <literal>5</literal>
</para>
</entry>
<entry>Since 1.6.0.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</entry>
</row>
<row>
<entry>
<literal>rollback_on_close</literal>
</entry>
<entry>
<para>
Whether to automatically rollback an open global transaction is
a connection is closed.
</para>
<para>
Default: <literal>true</literal>
</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
</section>
<section xml:id="mysqlnd-ms.plugin-ini-v1">
<title xmlns="http://docbook.org/ns/docbook">Plugin configuration file (&lt;= 1.0.x)</title>

View file

@ -14,6 +14,7 @@
<function name='mysqlnd_ms_query_is_select' from='PECL mysqlnd_ms &gt;= 1.0.0'/>
<function name='mysqlnd_ms_set_user_pick_server' from='PECL mysqlnd_ms &lt; 1.1.0'/>
<function name='mysqlnd_ms_set_qos' from='PECL mysqlnd_ms &lt; 1.2.0'/>
<function name='mysqlnd_ms_xa_begin' from='PECL mysqlnd_ms &lt; 1.6.0'/>
</versions>