MySQL supports local transactions (within a given client
connection) through statements such as SET
AUTOCOMMIT
, START TRANSACTION
,
COMMIT
, and ROLLBACK
. See
Section 13.4.1, “START TRANSACTION
, COMMIT
, and
ROLLBACK
Syntax”. Beginning with MySQL 5.0, XA transaction
support is available, which enables MySQL to participate in
distributed transactions as well. See Section 13.4.7, “XA Transactions”.
START TRANSACTION | BEGIN [WORK] COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] SET AUTOCOMMIT = {0 | 1}
The START TRANSACTION
and
BEGIN
statement begin a new transaction.
COMMIT
commits the current transaction,
making its changes permanent. ROLLBACK
rolls
back the current transaction, canceling its changes. The
SET AUTOCOMMIT
statement disables or enables
the default autocommit mode for the current connection.
Beginning with MySQL 5.0.3, the optional WORK
keyword is supported for COMMIT
and
RELEASE
, as are the CHAIN
and RELEASE
clauses. CHAIN
and RELEASE
can be used for additional
control over transaction completion. The value of the
completion_type
system variable determines
the default completion behavior. See
Section 5.2.2, “Server System Variables”.
The AND CHAIN
clause causes a new transaction
to begin as soon as the current one ends, and the new
transaction has the same isolation level as the just-terminated
transaction. The RELEASE
clause causes the
server to disconnect the current client connection after
terminating the current transaction. Including the
NO
keyword suppresses
CHAIN
or RELEASE
completion, which can be useful if the
completion_type
system variable is set to
cause chaining or release completion by default.
By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk.
If you are using a transaction-safe storage engine (such as
InnoDB
, BDB
, or
NDB Cluster
), you can disable autocommit mode
with the following statement:
SET AUTOCOMMIT=0;
After disabling autocommit mode by setting the
AUTOCOMMIT
variable to zero, you must use
COMMIT
to store your changes to disk or
ROLLBACK
if you want to ignore the changes
you have made since the beginning of your transaction.
To disable autocommit mode for a single series of statements,
use the START TRANSACTION
statement:
START TRANSACTION; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summary=@A WHERE type=1; COMMIT;
With START TRANSACTION
, autocommit remains
disabled until you end the transaction with
COMMIT
or ROLLBACK
. The
autocommit mode then reverts to its previous state.
BEGIN
and BEGIN WORK
are
supported as aliases of START TRANSACTION
for
initiating a transaction. START TRANSACTION
is standard SQL syntax and is the recommended way to start an
ad-hoc transaction.
The BEGIN
statement differs from the use of
the BEGIN
keyword that starts a
BEGIN ... END
compound statement. The latter
does not begin a transaction. See Section 17.2.5, “BEGIN ... END
Compound Statement Syntax”.
You can also begin a transaction like this:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
The WITH CONSISTENT SNAPSHOT
clause starts a
consistent read for storage engines that are capable of it.
Currently, this applies only to InnoDB
. The
effect is the same as issuing a START
TRANSACTION
followed by a SELECT
from any InnoDB
table. See
Section 14.2.10.4, “Consistent Non-Locking Read”.
The WITH CONSISTENT SNAPSHOT
clause does not
change the current transaction isolation level, so it provides a
consistent snapshot only if the current isolation level is one
that allows consistent read (REPEATABLE READ
or SERIALIZABLE
).
Beginning a transaction causes an implicit UNLOCK
TABLES
to be performed.
For best results, transactions should be performed using only tables managed by a single transactional storage engine. Otherwise, the following problems can occur:
-
If you use tables from more than one transaction-safe storage engine (such as
InnoDB
andBDB
), and the transaction isolation level is notSERIALIZABLE
, it is possible that when one transaction commits, another ongoing transaction that uses the same tables will see only some of the changes made by the first transaction. That is, the atomicity of transactions is not guaranteed with mixed engines and inconsistencies can result. (If mixed-engine transactions are infrequent, you can useSET TRANSACTION ISOLATION LEVEL
to set the isolation level toSERIALIZABLE
on a per-transaction basis as necessary.) -
If you use non-transaction-safe tables within a transaction, any changes to those tables are stored at once, regardless of the status of autocommit mode.
If you issue a
ROLLBACK
statement after updating a non-transactional table within a transaction, anER_WARNING_NOT_COMPLETE_ROLLBACK
warning occurs. Changes to transaction-safe tables are rolled back, but not changes to non-transaction-safe tables.
Each transaction is stored in the binary log in one chunk, upon
COMMIT
. Transactions that are rolled back are
not logged. (Exception:
Modifications to non-transactional tables cannot be rolled back.
If a transaction that is rolled back includes modifications to
non-transactional tables, the entire transaction is logged with
a ROLLBACK
statement at the end to ensure
that the modifications to those tables are replicated.) See
Section 5.12.3, “The Binary Log”.
You can change the isolation level for transactions with
SET TRANSACTION ISOLATION LEVEL
. See
Section 13.4.6, “SET TRANSACTION
Syntax”.
Rolling back can be a slow operation that may occur without the
user having explicitly asked for it (for example, when an error
occurs). Because of this, SHOW PROCESSLIST
displays Rolling back
in the
State
column for the connection during
implicit and explicit (ROLLBACK
SQL
statement) rollbacks.
Some statements cannot be rolled back. In general, these include data definition language (DDL) statements, such as those that create or drop databases, those that create, drop, or alter tables or stored routines.
You should design your transactions not to include such
statements. If you issue a statement early in a transaction that
cannot be rolled back, and then another statement later fails,
the full effect of the transaction cannot be rolled back in such
cases by issuing a ROLLBACK
statement.
Each of the following statements (and any synonyms for them)
implicitly end a transaction, as if you had done a
COMMIT
before executing the statement:
-
ALTER FUNCTION
,ALTER PROCEDURE
,ALTER TABLE
,BEGIN
,CREATE DATABASE
,CREATE FUNCTION
,CREATE INDEX
,CREATE PROCEDURE
,CREATE TABLE
,DROP DATABASE
,DROP FUNCTION
,DROP INDEX
,DROP PROCEDURE
,DROP TABLE
,LOAD MASTER DATA
,LOCK TABLES
,LOAD DATA INFILE
,RENAME TABLE
,SET AUTOCOMMIT=1
,START TRANSACTION
,TRUNCATE TABLE
,UNLOCK TABLES
. -
UNLOCK TABLES
commits a transaction only if any tables currently are locked. -
The
CREATE TABLE
,CREATE DATABASE
DROP DATABASE
, andTRUNCATE TABLE
statements cause an implicit commit beginning with MySQL 5.0.8. TheALTER FUNCTION
,ALTER PROCEDURE
,CREATE FUNCTION
,CREATE PROCEDURE
,DROP FUNCTION
, andDROP PROCEDURE
statements cause an implicit commit beginning with MySQL 5.0.13. -
The
CREATE TABLE
statement inInnoDB
is processed as a single transaction. This means that aROLLBACK
from the user does not undoCREATE TABLE
statements the user made during that transaction.
Transactions cannot be nested. This is a consequence of the
implicit COMMIT
performed for any current
transaction when you issue a START
TRANSACTION
statement or one of its synonyms.
Statements that cause implicit cannot be used in an XA
transaction while the transaction is in an
ACTIVE
state.
SAVEPOINTidentifier
ROLLBACK [WORK] TO SAVEPOINTidentifier
RELEASE SAVEPOINTidentifier
InnoDB
supports the SQL statements
SAVEPOINT
and ROLLBACK TO
SAVEPOINT
. Starting from MySQL 5.0.3, RELEASE
SAVEPOINT
and the optional WORK
keyword for ROLLBACK
are supported as well.
The SAVEPOINT
statement sets a named
transaction savepoint with a name of
identifier
. If the current
transaction has a savepoint with the same name, the old
savepoint is deleted and a new one is set.
The ROLLBACK TO SAVEPOINT
statement rolls
back a transaction to the named savepoint. Modifications that
the current transaction made to rows after the savepoint was set
are undone in the rollback, but InnoDB
does
not release the row locks that were stored
in memory after the savepoint. (Note that for a new inserted
row, the lock information is carried by the transaction ID
stored in the row; the lock is not separately stored in memory.
In this case, the row lock is released in the undo.) Savepoints
that were set at a later time than the named savepoint are
deleted.
If the ROLLBACK TO SAVEPOINT
statement
returns the following error, it means that no savepoint with the
specified name exists:
ERROR 1181: Got error 153 during ROLLBACK
The RELEASE SAVEPOINT
statement removes the
named savepoint from the set of savepoints of the current
transaction. No commit or rollback occurs. It is an error if the
savepoint does not exist.
All savepoints of the current transaction are deleted if you
execute a COMMIT
, or a
ROLLBACK
that does not name a savepoint.
Beginning with MySQL 5.0.17, a new savepoint level is created when a stored function is invoked or a trigger is activated. The savepoints on previous levels become unavailable and thus do not conflict with savepoints on the new level. When the function or trigger terminates, any savepoints it created are released and the previous savepoint level is restored.
LOCK TABLEStbl_name
[ASalias
] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [,tbl_name
[ASalias
] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ... UNLOCK TABLES
LOCK TABLES
locks base tables (but not views)
for the current thread. If any of the tables are locked by other
threads, it blocks until all locks can be acquired.
UNLOCK TABLES
releases any locks held by the
current thread. All tables that are locked by the current thread
are implicitly unlocked when the thread issues another
LOCK TABLES
, or when the connection to the
server is closed.
A table lock protects only against inappropriate reads or writes
by other clients. The client holding the lock, even a read lock,
can perform table-level operations such as DROP
TABLE
.
Note the following regarding the use of LOCK
TABLES
with transactional tables:
-
LOCK TABLES
is not transaction-safe and implicitly commits any active transactions before attempting to lock the tables. Also, beginning a transaction (for example, withSTART TRANSACTION
) implicitly performs anUNLOCK TABLES
. (See Section 13.4.3, “Statements That Cause an Implicit Commit”.) -
The correct way to use
LOCK TABLES
with transactional tables, such asInnoDB
tables, is to setAUTOCOMMIT = 0
and not to callUNLOCK TABLES
until you commit the transaction explicitly. When you callLOCK TABLES
,InnoDB
internally takes its own table lock, and MySQL takes its own table lock.InnoDB
releases its table lock at the next commit, but for MySQL to release its table lock, you have to callUNLOCK TABLES
. You should not haveAUTOCOMMIT = 1
, because thenInnoDB
releases its table lock immediately after the call ofLOCK TABLES
, and deadlocks can very easily happen. Note that we do not acquire theInnoDB
table lock at all ifAUTOCOMMIT=1
, to help old applications avoid unnecessary deadlocks. -
ROLLBACK
does not release MySQL's non-transactional table locks.
To use LOCK TABLES
, you must have the
LOCK TABLES
privilege and the
SELECT
privilege for the involved tables.
The main reasons to use LOCK TABLES
are to
emulate transactions or to get more speed when updating tables.
This is explained in more detail later.
If a thread obtains a READ
lock on a table,
that thread (and all other threads) can only read from the
table. If a thread obtains a WRITE
lock on a
table, only the thread holding the lock can write to the table.
Other threads are blocked from reading or writing the table
until the lock has been released.
The difference between READ LOCAL
and
READ
is that READ LOCAL
allows non-conflicting INSERT
statements
(concurrent inserts) to execute while the lock is held. However,
this cannot be used if you are going to manipulate the database
files outside MySQL while you hold the lock. For
InnoDB
tables, READ LOCAL
is the same as READ
as of MySQL 5.0.13.
(Before that, READ LOCAL
essentially does
nothing: It does not lock the table at all, so for
InnoDB
tables, the use of READ
LOCAL
is deprecated because a plain consistent-read
SELECT
does the same thing, and no locks are
needed.)
When you use LOCK TABLES
, you must lock all
tables that you are going to use in your queries. Because
LOCK TABLES
will not lock views, if the
operation that you are performing uses any views, you must also
lock all of the base tables on which those views depend. While
the locks obtained with a LOCK TABLES
statement are in effect, you cannot access any tables that were
not locked by the statement. Also, you cannot use a locked table
multiple times in a single query. Use aliases instead, in which
case you must obtain a lock for each alias separately.
mysql>LOCK TABLE t WRITE, t AS t1 WRITE;
mysql>INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES mysql>INSERT INTO t SELECT * FROM t AS t1;
If your queries refer to a table by means of an alias, you must lock the table using that same alias. It does not work to lock the table without specifying the alias:
mysql>LOCK TABLE t READ;
mysql>SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
Conversely, if you lock a table using an alias, you must refer to it in your queries using that alias:
mysql>LOCK TABLE t AS myalias READ;
mysql>SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES mysql>SELECT * FROM t AS myalias;
WRITE
locks normally have higher priority
than READ
locks to ensure that updates are
processed as soon as possible. This means that if one thread
obtains a READ
lock and then another thread
requests a WRITE
lock, subsequent
READ
lock requests wait until the
WRITE
thread has gotten the lock and released
it. You can use LOW_PRIORITY WRITE
locks to
allow other threads to obtain READ
locks
while the thread is waiting for the WRITE
lock. You should use LOW_PRIORITY WRITE
locks
only if you are sure that eventually there will be a time when
no threads have a READ
lock.
LOCK TABLES
works as follows:
-
Sort all tables to be locked in an internally defined order. From the user standpoint, this order is undefined.
-
If a table is locked with a read and a write lock, put the write lock before the read lock.
-
Lock one table at a time until the thread gets all locks.
This policy ensures that table locking is deadlock free. There
are, however, other things you need to be aware of about this
policy: If you are using a LOW_PRIORITY WRITE
lock for a table, it means only that MySQL waits for this
particular lock until there are no threads that want a
READ
lock. When the thread has gotten the
WRITE
lock and is waiting to get the lock for
the next table in the lock table list, all other threads wait
for the WRITE
lock to be released. If this
becomes a serious problem with your application, you should
consider converting some of your tables to transaction-safe
tables.
You can safely use KILL
to terminate a thread
that is waiting for a table lock. See Section 13.5.5.3, “KILL
Syntax”.
Note that you should not lock any tables
that you are using with INSERT DELAYED
because in that case the INSERT
is performed
by a separate thread.
Normally, you do not need to lock tables, because all single
UPDATE
statements are atomic; no other thread
can interfere with any other currently executing SQL statement.
However, there are a few cases when locking tables may provide
an advantage:
-
If you are going to run many operations on a set of
MyISAM
tables, it is much faster to lock the tables you are going to use. LockingMyISAM
tables speeds up inserting, updating, or deleting on them. The downside is that no thread can update aREAD
-locked table (including the one holding the lock) and no thread can access aWRITE
-locked table other than the one holding the lock.The reason some
MyISAM
operations are faster underLOCK TABLES
is that MySQL does not flush the key cache for the locked tables untilUNLOCK TABLES
is called. Normally, the key cache is flushed after each SQL statement. -
If you are using a storage engine in MySQL that does not support transactions, you must use
LOCK TABLES
if you want to ensure that no other thread comes between aSELECT
and anUPDATE
. The example shown here requiresLOCK TABLES
to execute safely:LOCK TABLES trans READ, customer WRITE; SELECT SUM(value) FROM trans WHERE customer_id=
some_id
; UPDATE customer SET total_value=sum_from_previous_statement
WHERE customer_id=some_id
; UNLOCK TABLES;Without
LOCK TABLES
, it is possible that another thread might insert a new row in thetrans
table between execution of theSELECT
andUPDATE
statements.
You can avoid using LOCK TABLES
in many cases
by using relative updates (UPDATE customer SET
value
=value
+new_value
)
or the LAST_INSERT_ID()
function. See
Section 1.9.5.3, “Transactions and Atomic Operations”.
You can also avoid locking tables in some cases by using the
user-level advisory lock functions GET_LOCK()
and RELEASE_LOCK()
. These locks are saved in
a hash table in the server and implemented with
pthread_mutex_lock()
and
pthread_mutex_unlock()
for high speed. See
Section 12.9.4, “Miscellaneous Functions”.
See Section 7.3.1, “Locking Methods”, for more information on locking policy.
You can lock all tables in all databases with read locks with
the FLUSH TABLES WITH READ LOCK
statement.
See Section 13.5.5.2, “FLUSH
Syntax”. This is a very convenient way to
get backups if you have a filesystem such as Veritas that can
take snapshots in time.
Note: If you use ALTER
TABLE
on a locked table, it may become unlocked. See
Section A.7.1, “Problems with ALTER TABLE
”.
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
This statement sets the transaction isolation level for the next transaction, globally, or for the current session.
The default behavior of SET TRANSACTION
is to
set the isolation level for the next (not yet started)
transaction. If you use the GLOBAL
keyword,
the statement sets the default transaction level globally for
all new connections created from that point on. Existing
connections are unaffected. You need the
SUPER
privilege to do this. Using the
SESSION
keyword sets the default transaction
level for all future transactions performed on the current
connection.
For descriptions of each InnoDB
transaction
isolation level, see
Section 14.2.10.3, “InnoDB
and TRANSACTION ISOLATION LEVEL
”.
InnoDB
supports each of these levels in MySQL
5.0. The default level is REPEATABLE
READ
.
To set the initial default global isolation level for
mysqld, use the
--transaction-isolation
option. See
Section 5.2.1, “mysqld Command Options”.
MySQL 5.0.3 and up provides server-side support for XA
transactions. Currently, this support is available for the
InnoDB
storage engine. The MySQL XA
implementation is based on the X/Open CAE document
Distributed Transaction Processing: The XA
Specification. This document is published by The
Open Group and available at
http://www.opengroup.org/public/pubs/catalog/c193.htm.
Limitations of the current XA implementation are described in
Section I.5, “Restrictions on XA Transactions”.
On the client side, there are no special requirements. The XA
interface to a MySQL server consists of SQL statements that
begin with the XA
keyword. MySQL client
programs must be able to send SQL statements and to understand
the semantics of the XA statement interface. They do not need be
linked against a recent client library. Older client libraries
also will work.
Currently, among the MySQL Connectors, MySQL Connector/J 5.0.0 supports XA directly (by means of a class interface that handles the XA SQL statement interface for you).
XA supports distributed transactions; that is, the ability to allow multiple separate transactional resources to participate in a global transaction. Transactional resources often are RDBMSs but may be other kinds of resources.
A global transaction involves several actions that are
transactional in themselves, but that all must either complete
successfully as a group, or all be rolled back as a group. In
essence, this extends ACID properties “up a level”
so that multiple ACID transactions can be executed in concert as
components of a global operation that also has ACID properties.
(However, for a distributed transaction, you must use the
SERIALIZABLE
isolation level to achieve ACID
properties. It is enough to use REPEATABLE
READ
for a non-distributed transaction, but not for a
distributed transaction.)
Some examples of distributed transactions:
-
An application may act as an integration tool that combines a messaging service with an RDBMS. The application makes sure that transactions dealing with message sending, retrieval, and processing that also involve a transactional database all happen in a global transaction. You can think of this as “transactional email.”
-
An application performs actions that involve different database servers, such as a MySQL server and an Oracle server (or multiple MySQL servers), where actions that involve multiple servers must happen as part of a global transaction, rather than as separate transactions local to each server.
-
A bank keeps account information in an RDBMS and distributes and receives money via automated teller machines (ATMs). It is necessary to ensure that ATM actions are correctly reflected in the accounts, but this cannot be done with the RDBMS alone. A global transaction manager integrates the ATM and database resources to ensure overall consistency of financial transactions.
Applications that use global transactions involve one or more Resource Managers and a Transaction Manager:
-
A Resource Manager (RM) provides access to transactional resources. A database server is one kind of resource manager. It must be possible to either commit or roll back transactions managed by the RM.
-
A Transaction Manager (TM) coordinates the transactions that are part of a global transaction. It communicates with the RMs that handle each of these transactions. The individual transactions within a global transaction are “branches” of the global transaction. Global transactions and their branches are identified by a naming scheme described later.
The MySQL implementation of XA MySQL enables a MySQL server to act as a Resource Manager that handles XA transactions within a global transaction. A client program that connects to the MySQL server acts as the Transaction Manager.
To carry out a global transaction, it is necessary to know which components are involved, and bring each component to a point when it can be committed or rolled back. Depending on what each component reports about its ability to succeed, they must all commit or roll back as an atomic group. That is, either all components must commit, or all components musts roll back. To manage a global transaction, it is necessary to take into account that any component or the connecting network might fail.
The process for executing a global transaction uses two-phase commit (2PC). This takes place after the actions performed by the branches of the global transaction have been executed.
-
In the first phase, all branches are prepared. That is, they are told by the TM to get ready to commit. Typically, this means each RM that manages a branch records the actions for the branch in stable storage. The branches indicate whether they are able to do this, and these results are used for the second phase.
-
In the second phase, the TM tells the RMs whether to commit or roll back. If all branches indicated when they were prepared that they will be able to commit, all branches are told to commit. If any branch indicated when it was prepared that it will not be able to commit, all branches are told to roll back.
In some cases, a global transaction might use one-phase commit (1PC). For example, when a Transaction Manager finds that a global transaction consists of only one transactional resource (that is, a single branch), that resource can be told to prepare and commit at the same time.
To perform XA transactions in MySQL, use the following statements:
XA {START|BEGIN}xid
[JOIN|RESUME] XA ENDxid
[SUSPEND [FOR MIGRATE]] XA PREPARExid
XA COMMITxid
[ONE PHASE] XA ROLLBACKxid
XA RECOVER
For XA START
, the JOIN
and RESUME
clauses are not supported.
For XA END
the SUSPEND [FOR
MIGRATE]
clause is not supported.
Each XA statement begins with the XA
keyword, and most of them require an
xid
value. An
xid
is an XA transaction
identifier. It indicates which transaction the statement
applies to. xid
values are supplied
by the client, or generated by the MySQL server. An
xid
value has from one to three
parts:
xid
:gtrid
[,bqual
[,formatID
]]
gtrid
is a global transaction
identifier, bqual
is a branch
qualifier, and formatID
is a number
that identifies the format used by the
gtrid
and
bqual
values. As indicated by the
syntax, bqual
and
formatID
are optional. The default
bqual
value is
''
if not given. The default
formatID
value is 1 if not given.
gtrid
and
bqual
must be string literals, each
up to 64 bytes (not characters) long.
gtrid
and
bqual
can be specified in several
ways. You can use a quoted string ('ab'
),
hex string (0x6162
,
X'ab'
), or bit value
(b'
nnnn
').
formatID
is an unsigned integer.
The gtrid
and
bqual
values are interpreted in
bytes by the MySQL server's underlying XA support routines.
However, while an SQL statement containing an XA statement is
being parsed, the server works with some specific character
set. To be safe, write gtrid
and
bqual
as hex strings.
xid
values typically are generated
by the Transaction Manager. Values generated by one TM must be
different from values generated by other TMs. A given TM must
be able to recognize its own xid
values in a list of values returned by the XA
RECOVER
statement.
XA START
xid
starts an XA transaction with the given
xid
value. Each XA transaction must
have a unique xid
value, so the
value must not currently be used by another XA transaction.
Uniqueness is assessed using the
gtrid
and
bqual
values. All following XA
statements for the XA transaction must be specified using the
same xid
value as that given in the
XA START
statement. If you use any of those
statements but specify an xid
value
that does not correspond to some existing XA transaction, an
error occurs.
One or more XA transactions can be part of the same global
transaction. All XA transactions within a given global
transaction must use the same gtrid
value in the xid
value. For this
reason, gtrid
values must be
globally unique so that there is no ambiguity about which
global transaction a given XA transaction is part of. The
bqual
part of the
xid
value must be different for
each XA transaction within a global transaction. (The
requirement that bqual
values be
different is a limitation of the current MySQL XA
implementation. It is not part of the XA specification.)
The XA RECOVER
statement returns
information for those XA transactions on the MySQL server that
are in the PREPARED
state. (See
Section 13.4.7.2, “XA Transaction States”.) The output includes a row for
each such XA transaction on the server, regardless of which
client started it.
XA RECOVER
output rows look like this (for
an example xid
value consisting of
the parts 'abc'
, 'def'
,
and 7
):
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
The output columns have the following meanings:
-
formatID
is theformatID
part of the transactionxid
-
gtrid_length
is the length in bytes of thegtrid
part of thexid
-
bqual_length
is the length in bytes of thebqual
part of thexid
-
data
is the concatenation of thegtrid
andbqual
parts of thexid
An XA transaction progresses through the following states:
-
Use
XA START
to start an XA transaction and put it in theACTIVE
state. -
For an
ACTIVE
XA transaction, issue the SQL statements that make up the transaction, and then issue anXA END
statement.XA END
puts the transaction in theIDLE
state. -
For an
IDLE
XA transaction, you can issue either anXA PREPARE
statement or anXA COMMIT ... ONE PHASE
statement:-
XA PREPARE
puts the transaction in thePREPARED
state. AnXA RECOVER
statement at this point will include the transaction'sxid
value in its output, becauseXA RECOVER
lists all XA transactions that are in thePREPARED
state. -
XA COMMIT ... ONE PHASE
prepares and commits the transaction. Thexid
value will not be listed byXA RECOVER
because the transaction terminates.
-
-
For a
PREPARED
XA transaction, you can issue anXA COMMIT
statement to commit and terminate the transaction, orXA ROLLBACK
to roll back and terminate the transaction.
Here is a simple XA transaction that inserts a row into a table as part of a global transaction:
mysql>XA START 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec) mysql>XA END 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
Within the context of a given client connection, XA
transactions and local (non-XA) transactions are mutually
exclusive. For example, if XA START
has
been issued to begin an XA transaction, a local transaction
cannot be started until the XA transaction has been committed
or rolled back. Conversely, if a local transaction has been
started with START TRANSACTION
, no XA
statements can be used until the transaction has been
committed or rolled back.
Note that if an XA transaction is in the
ACTIVE
state, you cannot issue any
statements that cause an implicit commit. That would violate
the XA contract because you could not roll back the XA
transaction. You will receive the following error if you try
to execute such a statement:
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
Statements to which the preceding remark applies are listed at Section 13.4.3, “Statements That Cause an Implicit Commit”.