WL#2775: System tables for master.info, relay_log.info
Affects: Server-5.6
—
Status: Complete
SUMMARY ------- Replace the master.info and relay_log.info files with system tables. MOTIVATION ---------- 1. Get rid of the files making the system more easy to manage. This becomes especially important with WL#1697 Multi-source since that implementation would create sets of files for *every* named master. 2. System table updates should be intermixed with the ongoing transaction, thus making the replication more fault tolerant. I.e. it would be impossible for the slave to crash between the data update and the relay_log_pos update... 3. Brian wants this as part of multi-source (WL#1697). RELATED WORKLOGS ---------------- (Impact on and by) WL#1697 - Multi-source replication. WL#3584 - Group-ids (global-bin-log positions). WL#4209 - Integrate Backup with Replication. WL#4621 - Recovery process to synchronize the master.info, the relay-log.info and the relay-log after a failure. WL#5125 - Refactory of Slave master.info and slave.info (Previous work towards this worklog) WL#3089 - Refactoring for multi-source and info system tables. (Additional thoughts) WL#3835 - Slave tables to track progress of replication. (Different alternative with XA) WL#3970 - Safe slave positions. DECISIONS --------- This should be first discussed with Mats and then reviewed by Peter G. Configuration of this new system table needs to be very clearly specified. -- Lars Thalmann, 2009-01-26 OPEN ISSUES ----------- 1. Perhaps consider storing the password as encrypted. "Due to the lack of time, we are not going to consider this as part of this worklog." -- Alfranio, 2009-10-16 2. Although the code can be easily extended to support WL#1697 - Multi-source replication, this still requires additional work. 3. We are not considering the integration with Backup, WL#4209 - Integrate Backup with Replication. BUGS ---- BUG#55105 - Some PB2 tests fail sporadically with SIGSEGV in inline_mysql_mutex_lock. BUG#56324 - Race Condition while shutting down MySQL: "PSI_server" BUG#51054 - mysqld segfault after binlog enabled The bugs above need to be fixed so we can properly test this worklog.
WL#4621: Recovery process to synchronize the master.info, the relay-log.info and the relay-log after a failure.
WL#5125: Refactory of Slave's master.info and relay_log.info
WL#5125: Refactory of Slave's master.info and relay_log.info
REQUIREMENTS ------------ (REQ-1) It shall be possible to store the information in any kind of storage engine. (REQ-2) - It shall be possible to easily extend the proposed solution to handle multi-source replication. See also WL#1697. (REQ-3) The master.info table shall be updated whenever: (i) a relay log is rotated, (ii) CHANGE MASTER is executed and (iii) I/O Thread is stopped. (REQ-4) After a failure, a recovery process should throw away possible corrupted relay log files and rely on the information in the relay.info to start re-fetching data from the master. See also WL#4621. (REQ-5) The relay.info table shall be updated whenever: (i) the relay log file is rotated, (ii) transaction SQL Thread is stopped, (iii) while processing a Xid_log_event, (iv) after processing commit or rollback, i.e. a Query_log_event, and (v)after processing any statement written to the binary log without a transaction context. (REQ-6) The system should cope with the fact that an user may switch the type of the repository without disabling the previous one. REQ-1 ----- It shall be possible to create the system tables using any kind of storage engine. Specifically, the system tables are the slave_master_info (master.info) and slave_relay_log_info (relay.info) and by default both tables are created using the default engine, which currently is MyISAM. This is done because the MyIsam storage engine is always available. For those users concerned about reliability, a "super user" may change the type of the engine at any time. It is also possible to specify the type of the engine in the installation procedure by defining the option -rep-engine=engine. Common users are not be able to change (e.g. drop) the system tables. However, a "super user" may alter them but this is not recommend as some changes may stop the slave. For instance, the primary key should never be changed or removed. In particular, changing default values for the columns in the system tables does not affect default values defined in the server. This means that when a "CHANGE MASTER" is executed the default values specified in the system tables are ignored as they are overwritten by those internally defined in the server. However, the "super user" can still stop the replication and directly perform changes to the system tables and in such cases the default values defined for the columns will be used. Users are not able to directly update the system tables but any user can read from it. In particular, a super user may read and also acquire a read lock on them thus blocking the replication until the lock is released. A read lock can be acquired with the command: "FLUSH TABLES WITH READ LOCK" REQ-2 ----- It shall be as simple as having an *unique* index (PK or UK not null) in master.info and relay.info tables in the column that stores the master id. So supporting multi-source is as simple as adding new entries to the tables. REQ-3 ----- (REQ-3) The master.info table shall be updated whenever: (i) a relay log is rotated, (ii) CHANGE MASTER is executed and (iii) I/O Thread is stopped. One may also control if the master.info is updated after reading an event from the master and writing it to relay log. This is done through the option --sync-master-info = N, where N is the number of events after which the update will take place. There is a key difference however between the use of a file and a system table. When we update the positions into a file, we optimistically write to the OS' cache and eventually the changes will be written to disk if the server does not crash. If we want to guarantee that the data is successfully written to disk right after returning from the update call we need to set the option --sync-master-info. However, there is no optimistic write to a table which means that nothing is written before the sync period is reached. By default the value is 0 which means that data is persisted only in cases (i), (ii) and (iii). There is no need to set --sync-master-info as the recovery process described in REQ-4 is mandatory to provide reliability/data integrity and by consequence some possible corrupted relay log files are thrown away and the positions stored in the master.info are updated based on the positions in the relay.info. Deleted events are re-fetched from the master if necessary. REQ-4 ----- To correctly recovery from failures, one shall relay on the following option: --relay-log-recovery. REQ-5 ----- (REQ-5) The relay.info table shall be updated whenever: (i) the relay log file is rotated, (ii) transaction SQL Thread is stopped, (iii) while processing a Xid_log_event, (iv) after processing commit or rollback, i.e. a Query_log_event, and (v)after processing any statement written to the binary log without a transaction context. The Xid_log_event is a commit for transactional engines and must be handled differently to provide reliability/data integrity. While committing updates to transactional engines the following behavior shall be implemented: . If the relay.info is stored in a transactional repository, for instance, a system table created using Innodb, the positions are updated in the context of the transaction that updated data. Therefore, should the server crash before successfully committing the transaction the changes to the position tables will be rolled back too . If the relay.info is stored in a non-transactional repository, for instance, a file or a system table created using MyIsam, the positions are update after processing the commit as in (iv) and (v). In particular, when there are mixed transactions, i.e a transaction that updates both transaction and non-transactional engines, the Xid_log_event is still used but reliability/data integrity cannot be achieved as we shall explain in what follows. Changes to non-transactional engines, such as MyIsam, cannot be rolled back if a failure happens. For that reason, there is no point in updating the positions within the boundaries of any on-going transaction. This is true for both commit and rollback. If a failure happens after processing the pseudo-transaction but before updating the positions, the transaction will be re-executed when the slave is up most likely causing an error that needs to be manually circumvented. This is a well-known issue when non-transactional statements are executed. Specifically, if rolling back any transaction, positions are updated outside the transaction boundaries. See WL#4801 for additional details. Statements written to the binary log outside the boundaries of a transaction are DDLs or maintenance commands which are not transactional. This means that they cannot be rolled back if a failure happens. In such cases, the positions are updated after processing the events. If a failure happens after processing the statement but before updating the positions, the statement will be re-executed when the slave is up most likely causing an error that needs to be manually circumvented. This is a well-known issue when non-transactional statements are executed. The --sync-relay-log-info does not have effect when a transactional system table is used. REQ-6 ----- The following table describes what shall happen when an user restarts the server with different repositories: |--------------+-----------------------+-----------------------| | Exists \ Opt | TABLE | FILE | |--------------+-----------------------+-----------------------| | !T,F | Update (and delete F) | Read F | | T,F | ERROR | ERROR | | !T,!F | Fill in T | Create and Fill in F | | T,!F | Read T | Update (and delete T) | |--------------+-----------------------+-----------------------| .F - file with data, .!F - no file, .!T - no data in table, .T - table with data. By default the persistent storage system is a file for both the master info and relay log info. Two options are provided to change persistent storage system: master_info_repository = (FILE | TABLE) relay_log_info_repository = (FILE | TABLE)
ARCHITECTURE ------------ We extend the architecture defined in the WL#5125 as fallows: ---------------------- ---------------------- | Rpl_info_Handler |<>---| Rpl_info_fields | ---------------------- ---------------------- ^ | ---------------------- ------------------------- | Rpl_info_table |<>---| Rpl_info_table_access | ---------------------- ------------------------- A factory is responsible for creating and assembling this set of components, i.e., setting the dependencies between the instances as follows: ---------------------- | Rpl_info_factory | ---------------------- ---------------------- ---------------------- | Master_info |<>---| Rpl_info_table | ---------------------- ---------------------- ---------------------- ---------------------- | Relay_log_info |<>---| Rpl_info_table | ---------------------- ---------------------- CLASSES ------- Rpl_info_Handler ================ . This an abstract class that provides a simple interface to build persistence mechanisms. Rpl_info_factory ================ . Creates and assembles the set of components presented in this section. Master_info =========== . Master_info will handle the following information: - Master_Log_File - The name of the master binary log currently being read from the master. - Read_Master_Log_Pos - The current position within the master binary log that have been read from the master. - Master_Host - The host name of the master. - Master_User - The user name used to connect to the master. - Master_Password (not shown by SHOW SLAVE STATUS) - The password used to connect to the master. - Master_Port - The network port used to connect to the master. - Connect_Retry - The period (in seconds) that the slave will wait before trying to reconnect to the master. - Master_SSL_Allowed - Indicates whether the server supports SSL connections. - Master_SSL_CA_File - The file used for the Certificate Authority (CA) certificate. - Master_SSL_CA_Path - The path to the Certificate Authority (CA) certificates. - Master_SSL_Cert - The name of the SSL certificate file. - Master_SSL_Cipher - The name of the cipher in use for the SSL connection. - Master_SSL_Key - The name of the SSL key file. - Master_SSL_Verify_Server_Cert - Whether to verify the server certificate. Any change that may happen to the structure of the Master_info will be handled at merging time. Relay_log_info ============== . Relay_log_info will handle the following information: - Relay_Log_File - The name of the current relay log file. - Relay_Log_Pos - The current position within the relay log file. Events up to this position have been executed on the slave database. - Relay_Master_Log_File - The name of the master binary log file from which the events in the relay log file were read. - Exec_Master_Log_Pos - The equivalent position within the master's binary log file of events that have already been executed. Any change that may happen to the structure of the Relay_log_info will be handled at merging time. class Rpl_info_table_access: ============================ . Provides the necessary means and interfaces to create threads and access information stored in a system table. I has the following methods: open_table() opens and locks a table in a database but before doing that, saves the previous lock state. close_table() releases the table lock and close the table and at the end restores the previous lock state. bool find_info_id() puts the cursor pointing to the record that corresponds to the server id. bool load_info_fields() prepares a data structure (e.g. Rpl_info_fields) to read data from a table. bool store_info_fields() prepares a data structure (e.g. Rpl_info_fields) to write data into a table. create_fake_thd() creates a fake thread to access a table when there is no current_thread. drop_fake_thd() drops a fake thread created to access a table. { public: Rpl_info_table_access(); virtual ~Rpl_info_table_access(); bool open_table(THD* thd, const char *dbstr, const char *tbstr, uint max_num_field, enum thr_lock_type lock_type, TABLE** table, Open_tables_state* backup); bool close_table(THD* thd, TABLE* table, Open_tables_state* backup); bool find_info_id(uint idx, LEX_STRING, TABLE*); bool load_info_fields(uint max_num_field, Field **fields, ...); bool load_info_fields(uint max_num_field, Field **fields, Rpl_info_fields *field_values); bool store_info_fields(uint max_num_field, Field **fields, ...); bool store_info_fields(uint max_num_field, Field **fields, Rpl_info_fields *field_values); THD *create_fake_thd(); bool drop_fake_thd(THD* thd, bool error); private: Rpl_info_table_access& operator=(const Rpl_info_table_access& info); Rpl_info_table_access(const Rpl_info_table_access& info); }; class Rpl_info_table : public Rpl_info_handler ===================== . This is a concrete class that inherits from the Rpl_info_handler. See WL#5125. { public: Rpl_info_table(uint nparam, uint param_field_id, const char* param_schema, const char *param_table); virtual ~Rpl_info_table(); private: Rpl_info_table_access *access; int do_init_info(); int do_check_info(); void do_end_info(); int do_flush_info(const bool force); int do_reset_info(); bool is_transactional(); int do_prepare_info_for_read(); int do_prepare_info_for_write(); bool do_set_info(const int pos, const char *value); bool do_set_info(const int pos, const int value); bool do_set_info(const int pos, const ulong value); bool do_set_info(const int pos, const float value); bool do_set_info(const int pos, const Server_ids *value); bool do_get_info(const int pos, char *value, const size_t size, const char *default_value); bool do_get_info(const int pos, int *value, const int default_value); bool do_get_info(const int pos, ulong *value, const ulong default_value); bool do_get_info(const int pos, float *value, const float default_value); bool do_get_info(const int pos, Server_ids *value, const Server_ids *default_value); Rpl_info_table& operator=(const Rpl_info_table& info); Rpl_info_table(const Rpl_info_table& info); }; class Rpl_info_fields: ====================== . Provides a sequence of elements that can be used as a temporary area to store information before flushing it to a repository. bool init() - allocate memory according to the number of elements in the master_info ro relay_log_info. void restore() - Restore the pointer from "saved" to "use". For instance, this may happen when a the repository is a table and one reads from it. resize() - Extends memory if the pre-allocated space is not enough to temporary store data. { public: Rpl_info_fields(int param_ninfo): field(0), ninfo(param_ninfo) { }; virtual ~Rpl_info_fields(); bool configure(); bool resize(int needed_size, int pos); info_fields *field; private: int ninfo; Rpl_info_fields& operator=(const Rpl_info_fields& fields); Rpl_info_fields(const Rpl_info_fields& fields); }; struct info_fields { LEX_STRING use; LEX_STRING saved; int size; } typedef info_fields; In what follows, we describe the structure of the master.info (i.e. slave_master_info) and relay.info (i.e. slave_relay_log_info) tables. TABLES ------ MASTER.INFO CREATE TABLE IF NOT EXISTS slave_master_info ( Master_id INTEGER UNSIGNED NOT NULL, Lines INTEGER UNSIGNED NOT NULL, Master_log_name TEXT NOT NULL, Master_log_pos INTEGER UNSIGNED NOT NULL, Host TEXT utf8_bin, User TEXT, Password TEXT, Port INTEGER UNSIGNED NOT NULL, Connect_retry INTEGER UNSIGNED NOT NULL, Ssl BOOLEAN NOT NULL, Ssl_ca TEXT, Ssl_capath TEXT, Ssl_cert TEXT, Ssl_cipher TEXT, Ssl_key TEXT, Ssl_verify_servert_cert BOOLEAN NOT NULL, Heartbeat FLOAT NOT NULL, Ignore_server_ids TEXT, Retry_count INTEGER UNSIGNED NOT NULL, PRIMARY KEY(master_id(128))) ENGINE=MYISAM COMMENT 'Master Information'; RELAY.INFO: CREATE TABLE IF NOT EXISTS slave_relay_log_info ( Master_id INTEGER UNSIGNED NOT NULL, Relay_log_name TEXT, Relay_log_pos INTEGER UNSIGNED NOT NULL, Master_log_name TEXT NOT NULL, Master_log_pos INTEGER UNSIGNED NOT NULL, PRIMARY KEY(master_id(128))) ENGINE=MYISAM COMMENT 'Relay Log Information'; For both tables UTF-8 is used as default. ----- NOTE: Changing these tables directly by the user is not recommended. Updating them while the slave is running will lead to unexpected/unpredictable behaviour, thus is not supported.
Copyright (c) 2000, 2024, Oracle Corporation and/or its affiliates. All rights reserved.