#### 17.1.3.2 GTID Life Cycle

[]()

 The life cycle of a GTID consists of the following steps:

1. A transaction is executed and committed on the source. This client transaction is assigned a GTID composed of the source's UUID and the smallest nonzero transaction sequence number not yet used on this server. The GTID is written to the source's binary log (immediately preceding the transaction itself in the log). If a client transaction is not written to the binary log (for example, because the transaction was filtered out, or the transaction was read-only), it is not assigned a GTID.

2. If a GTID was assigned for the transaction, the GTID is persisted atomically at commit time by writing it to the binary log at the beginning of the transaction (as a `Gtid_log_event`). Whenever the binary log is rotated or the server is shut down, the server writes GTIDs for all transactions that were written into the previous binary log file into the `mysql.gtid_executed` table.

3. If a GTID was assigned for the transaction, the GTID is externalized non-atomically (very shortly after the transaction is committed) by adding it to the set of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable (`@@GLOBAL.gtid_executed`). This GTID set contains a representation of the set of all committed GTID transactions, and it is used in replication as a token that represents the server state. With binary logging enabled (as required for the source), the set of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable is a complete record of the transactions applied, but the `mysql.gtid_executed` table is not, because the most recent history is still in the current binary log file.

4. After the binary log data is transmitted to the replica and stored in the replica's relay log (using established mechanisms for this process, see [Section 17.2, “Replication Implementation”](replication-implementation.html), for details), the replica reads the GTID and sets the value of its [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) system variable as this GTID. This tells the replica that the next transaction must be logged using this GTID. It is important to note that the replica sets `gtid_next` in a session context.

5. The replica verifies that no thread has yet taken ownership of the GTID in [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) in order to process the transaction. By reading and checking the replicated transaction's GTID first, before processing the transaction itself, the replica guarantees not only that no previous transaction having this GTID has been applied on the replica, but also that no other session has already read this GTID but has not yet committed the associated transaction. So if multiple clients attempt to apply the same transaction concurrently, the server resolves this by letting only one of them execute. The [`gtid_owned`](replication-options-gtids.html#sysvar_gtid_owned) system variable (`@@GLOBAL.gtid_owned`) for the replica shows each GTID that is currently in use and the ID of the thread that owns it. If the GTID has already been used, no error is raised, and the auto-skip function is used to ignore the transaction.

6. If the GTID has not been used, the replica applies the replicated transaction. Because [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) is set to the GTID already assigned by the source, the replica does not attempt to generate a new GTID for this transaction, but instead uses the GTID stored in [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next).

7. If binary logging is enabled on the replica, the GTID is persisted atomically at commit time by writing it to the binary log at the beginning of the transaction (as a `Gtid_log_event`). Whenever the binary log is rotated or the server is shut down, the server writes GTIDs for all transactions that were written into the previous binary log file into the `mysql.gtid_executed` table.

8. If binary logging is disabled on the replica, the GTID is persisted atomically by writing it directly into the `mysql.gtid_executed` table. MySQL appends a statement to the transaction to insert the GTID into the table. From MySQL 8.0, this operation is atomic for DDL statements as well as for DML statements. In this situation, the `mysql.gtid_executed` table is a complete record of the transactions applied on the replica.

9. Very shortly after the replicated transaction is committed on the replica, the GTID is externalized non-atomically by adding it to the set of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable (`@@GLOBAL.gtid_executed`) for the replica. As for the source, this GTID set contains a representation of the set of all committed GTID transactions. If binary logging is disabled on the replica, the `mysql.gtid_executed` table is also a complete record of the transactions applied on the replica. If binary logging is enabled on the replica, meaning that some GTIDs are only recorded in the binary log, the set of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable is the only complete record.

 Client transactions that are completely filtered out on the source are not assigned a GTID, therefore they are not added to the set of transactions in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable, or added to the `mysql.gtid_executed` table. However, the GTIDs of replicated transactions that are completely filtered out on the replica are persisted. If binary logging is enabled on the replica, the filtered-out transaction is written to the binary log as a `Gtid_log_event` followed by an empty transaction containing only `BEGIN` and `COMMIT` statements. If binary logging is disabled, the GTID of the filtered-out transaction is written to the `mysql.gtid_executed` table. Preserving the GTIDs for filtered-out transactions ensures that the `mysql.gtid_executed` table and the set of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable can be compressed. It also ensures that the filtered-out transactions are not retrieved again if the replica reconnects to the source, as explained in [Section 17.1.3.3, “GTID Auto-Positioning”](replication-gtids-auto-positioning.html).

 On a multithreaded replica (with [`replica_parallel_workers > 0`](replication-options-replica.html#sysvar_replica_parallel_workers) or [`slave_parallel_workers > 0`](replication-options-replica.html#sysvar_slave_parallel_workers) ), transactions can be applied in parallel, so replicated transactions can commit out of order (unless [`replica_preserve_commit_order=1`](replication-options-replica.html#sysvar_replica_preserve_commit_order) or [`slave_preserve_commit_order=1`](replication-options-replica.html#sysvar_slave_preserve_commit_order) is set). When that happens, the set of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable contains multiple GTID ranges with gaps between them. (On a source or a single-threaded replica, there are monotonically increasing GTIDs without gaps between the numbers.) Gaps on multithreaded replicas only occur among the most recently applied transactions, and are filled in as replication progresses. When replication threads are stopped cleanly using the [`STOP REPLICA`](stop-replica.html) statement, ongoing transactions are applied so that the gaps are filled in. In the event of a shutdown such as a server failure or the use of the [`KILL`](kill.html) statement to stop replication threads, the gaps might remain.

##### What changes are assigned a GTID?

 The typical scenario is that the server generates a new GTID for a committed transaction. However, GTIDs can also be assigned to other changes besides transactions, and in some cases a single transaction can be assigned multiple GTIDs.

 Every database change (DDL or DML) that is written to the binary log is assigned a GTID. This includes changes that are autocommitted, and changes that are committed using `BEGIN` and `COMMIT` or `START TRANSACTION` statements. A GTID is also assigned to the creation, alteration, or deletion of a database, and of a non-table database object such as a procedure, function, trigger, event, view, user, role, or grant.

 Non-transactional updates as well as transactional updates are assigned GTIDs. In addition, for a non-transactional update, if a disk write failure occurs while attempting to write to the binary log cache and a gap is therefore created in the binary log, the resulting incident log event is assigned a GTID.

 When a table is automatically dropped by a generated statement in the binary log, a GTID is assigned to the statement. Temporary tables are dropped automatically when a replica begins to apply events from a source that has just been started, and when statement-based replication is in use ([`binlog_format=STATEMENT`](replication-options-binary-log.html#sysvar_binlog_format)) and a user session that has open temporary tables disconnects. Tables that use the [`MEMORY`](memory-storage-engine.html) storage engine are deleted automatically the first time they are accessed after the server is started, because rows might have been lost during the shutdown.

 When a transaction is not written to the binary log on the server of origin, the server does not assign a GTID to it. This includes transactions that are rolled back and transactions that are executed while binary logging is disabled on the server of origin, either globally (with `--skip-log-bin` specified in the server's configuration) or for the session (`SET @@SESSION.sql_log_bin = 0`). This also includes no-op transactions when row-based replication is in use ([`binlog_format=ROW`](replication-options-binary-log.html#sysvar_binlog_format)).

 XA transactions are assigned separate GTIDs for the `XA PREPARE` phase of the transaction and the `XA COMMIT` or `XA ROLLBACK` phase of the transaction. XA transactions are persistently prepared so that users can commit them or roll them back in the case of a failure (which in a replication topology might include a failover to another server). The two parts of the transaction are therefore replicated separately, so they must have their own GTIDs, even though a non-XA transaction that is rolled back would not have a GTID.

 In the following special cases, a single statement can generate multiple transactions, and therefore be assigned multiple GTIDs:

* A stored procedure is invoked that commits multiple transactions. One GTID is generated for each transaction that the procedure commits.

* A multi-table [`DROP TABLE`](drop-table.html) statement drops tables of different types. Multiple GTIDs can be generated if any of the tables use storage engines that do not support atomic DDL, or if any of the tables are temporary tables.

* A [`CREATE TABLE ... SELECT`](create-table-select.html) statement is issued when row-based replication is in use ([`binlog_format=ROW`](replication-options-binary-log.html#sysvar_binlog_format)). One GTID is generated for the [`CREATE TABLE`](create-table.html) action and one GTID is generated for the row-insert actions.

##### The `gtid_next` System Variable

 By default, for new transactions committed in user sessions, the server automatically generates and assigns a new GTID. When the transaction is applied on a replica, the GTID from the server of origin is preserved. You can change this behavior by setting the session value of the [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) system variable:

* When [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) is set to `AUTOMATIC`, which is the default, and a transaction is committed and written to the binary log, the server automatically generates and assigns a new GTID. If a transaction is rolled back or not written to the binary log for another reason, the server does not generate and assign a GTID.

* If you set [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) to a valid GTID (consisting of a UUID and a transaction sequence number, separated by a colon), the server assigns that GTID to your transaction. This GTID is assigned and added to [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) even when the transaction is not written to the binary log, or when the transaction is empty.

 Note that after you set [`gtid_next`](replication-options-gtids.html#sysvar_gtid_next) to a specific GTID, and the transaction has been committed or rolled back, an explicit `SET @@SESSION.gtid_next` statement must be issued before any other statement. You can use this to set the GTID value back to `AUTOMATIC` if you do not want to assign any more GTIDs explicitly.

 When replication applier threads apply replicated transactions, they use this technique, setting `@@SESSION.gtid_next` explicitly to the GTID of the replicated transaction as assigned on the server of origin. This means the GTID from the server of origin is retained, rather than a new GTID being generated and assigned by the replica. It also means the GTID is added to [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) on the replica even when binary logging or replica update logging is disabled on the replica, or when the transaction is a no-op or is filtered out on the replica.

 It is possible for a client to simulate a replicated transaction by setting `@@SESSION.gtid_next` to a specific GTID before executing the transaction. This technique is used by [**mysqlbinlog**](mysqlbinlog.html) to generate a dump of the binary log that the client can replay to preserve GTIDs. A simulated replicated transaction committed through a client is completely equivalent to a replicated transaction committed through a replication applier thread, and they cannot be distinguished after the fact.

##### The `gtid_purged` System Variable

[]()[]()

 The set of GTIDs in the [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) system variable (`@@GLOBAL.gtid_purged`) contains the GTIDs of all the transactions that have been committed on the server, but do not exist in any binary log file on the server. [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) is a subset of [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed). The following categories of GTIDs are in [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged):

* GTIDs of replicated transactions that were committed with binary logging disabled on the replica.

* GTIDs of transactions that were written to a binary log file that has now been purged.

* GTIDs that were added explicitly to the set by the statement `SET @@GLOBAL.gtid_purged`.

 You can change the value of [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) in order to record on the server that the transactions in a certain GTID set have been applied, although they do not exist in any binary log on the server. When you add GTIDs to [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged), they are also added to [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed). An example use case for this action is when you are restoring a backup of one or more databases on a server, but you do not have the relevant binary logs containing the transactions on the server. Before MySQL 8.0, you could only change the value of [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) when [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) (and therefore [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)) was empty. From MySQL 8.0, this restriction does not apply, and you can also choose whether to replace the whole GTID set in [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) with a specified GTID set, or to add a specified GTID set to the GTIDs already in [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged). For details of how to do this, see the description for [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged).

 The sets of GTIDs in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) and [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) system variables are initialized when the server starts. Every binary log file begins with the event `Previous_gtids_log_event`, which contains the set of GTIDs in all previous binary log files (composed from the GTIDs in the preceding file's `Previous_gtids_log_event`, and the GTIDs of every `Gtid_log_event` in the preceding file itself). The contents of `Previous_gtids_log_event` in the oldest and most recent binary log files are used to compute the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) and [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) sets at server startup:

* [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) is computed as the union of the GTIDs in `Previous_gtids_log_event` in the most recent binary log file, the GTIDs of transactions in that binary log file, and the GTIDs stored in the `mysql.gtid_executed` table. This GTID set contains all the GTIDs that have been used (or added explicitly to [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)) on the server, whether or not they are currently in a binary log file on the server. It does not include the GTIDs for transactions that are currently being processed on the server (`@@GLOBAL.gtid_owned`).

* [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) is computed by first adding the GTIDs in `Previous_gtids_log_event` in the most recent binary log file and the GTIDs of transactions in that binary log file. This step gives the set of GTIDs that are currently, or were once, recorded in a binary log on the server (`gtids_in_binlog`). Next, the GTIDs in `Previous_gtids_log_event` in the oldest binary log file are subtracted from `gtids_in_binlog`. This step gives the set of GTIDs that are currently recorded in a binary log on the server (`gtids_in_binlog_not_purged`). Finally, `gtids_in_binlog_not_purged` is subtracted from [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed). The result is the set of GTIDs that have been used on the server, but are not currently recorded in a binary log file on the server, and this result is used to initialize [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged).

 If binary logs from MySQL 5.7.7 or older are involved in these computations, it is possible for incorrect GTID sets to be computed for [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) and [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged), and they remain incorrect even if the server is later restarted. For details, see the description for the [`binlog_gtid_simple_recovery`](replication-options-gtids.html#sysvar_binlog_gtid_simple_recovery) system variable, which controls how the binary logs are iterated to compute the GTID sets. If one of the situations described there applies on a server, set [`binlog_gtid_simple_recovery=FALSE`](replication-options-gtids.html#sysvar_binlog_gtid_simple_recovery) in the server's configuration file before starting it. That setting makes the server iterate all the binary log files (not just the newest and oldest) to find where GTID events start to appear. This process could take a long time if the server has a large number of binary log files without GTID events.

##### Resetting the GTID Execution History

 If you need to reset the GTID execution history on a server, use the [`RESET MASTER`](reset-master.html) statement. For example, you might need to do this after carrying out test queries to verify a replication setup on new GTID-enabled servers, or when you want to join a new server to a replication group but it contains some unwanted local transactions that are not accepted by Group Replication.

Warning

 Use [`RESET MASTER`](reset-master.html) with caution to avoid losing any wanted GTID execution history and binary log files.

 Before issuing [`RESET MASTER`](reset-master.html), ensure that you have backups of the server's binary log files and binary log index file, if any, and obtain and save the GTID set held in the global value of the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable (for example, by issuing a `SELECT @@GLOBAL.gtid_executed` statement and saving the results). If you are removing unwanted transactions from that GTID set, use [**mysqlbinlog**](mysqlbinlog.html) to examine the contents of the transactions to ensure that they have no value, contain no data that must be saved or replicated, and did not result in data changes on the server.

 When you issue [`RESET MASTER`](reset-master.html), the following reset operations are carried out:

* The value of the [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) system variable is set to an empty string (`''`).

* The global value (but not the session value) of the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) system variable is set to an empty string.

* The `mysql.gtid_executed` table is cleared (see [mysql.gtid\_executed Table](replication-gtids-concepts.html#replication-gtids-gtid-executed-table)).

* If the server has binary logging enabled, the existing binary log files are deleted and the binary log index file is cleared.

 Note that [`RESET MASTER`](reset-master.html) is the method to reset the GTID execution history even if the server is a replica where binary logging is disabled. [`RESET REPLICA`](reset-replica.html) has no effect on the GTID execution history.

