mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 00:48:54 +00:00
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:
parent
ef28865843
commit
5e6265f846
5 changed files with 836 additions and 22 deletions
|
@ -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
|
||||
|
|
156
reference/mysqlnd_ms/functions/mysqlnd-ms-xa-begin.xml
Normal file
156
reference/mysqlnd_ms/functions/mysqlnd-ms-xa-begin.xml
Normal 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
|
||||
-->
|
|
@ -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)
|
||||
|
|
|
@ -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 (<= 1.0.x)</title>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<function name='mysqlnd_ms_query_is_select' from='PECL mysqlnd_ms >= 1.0.0'/>
|
||||
<function name='mysqlnd_ms_set_user_pick_server' from='PECL mysqlnd_ms < 1.1.0'/>
|
||||
<function name='mysqlnd_ms_set_qos' from='PECL mysqlnd_ms < 1.2.0'/>
|
||||
<function name='mysqlnd_ms_xa_begin' from='PECL mysqlnd_ms < 1.6.0'/>
|
||||
|
||||
</versions>
|
||||
|
||||
|
|
Loading…
Reference in a new issue