Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-32215

Add Mariabackup option to set gtid_slave_pos to original server's gtid_current_pos during prepare

Details

    • Task
    • Status: Open (View Workflow)
    • Major
    • Resolution: Unresolved
    • None
    • None
    • None

    Description

      This was originally created as MDEV-18405.

      Many users use Mariabackup to build slaves using the process outlined in the following documentation page:

      https://mariadb.com/kb/en/library/setting-up-a-replication-slave-with-mariabackup/

      One problem with this process is that Mariabackup doesn't back up and restore the original server's entire GTID state, which can be considered to be the value of gtid_current_pos.

      https://mariadb.com/kb/en/library/gtid/#gtid_current_pos

      The value of gtid_current_pos is constructed from the values of two other system variables--gtid_slave_pos and gtid_binlog_pos.

      https://mariadb.com/kb/en/library/gtid/#gtid_slave_pos

      https://mariadb.com/kb/en/library/gtid/#gtid_binlog_pos

      Mariabackup does back up and restores the original server's value for gtid_slave_pos, because that information is stored in mysql.gtid_slave_pos, which is an InnoDB table.

      https://mariadb.com/kb/en/library/mysqlgtid_slave_pos-table/

      Mariabackup does not currently back up and restore the original server's gtid_binlog_pos, because that information is stored in the binary logs, which are not backed up.

      This means that a server restored from a backup is missing some GTID state by default.

      Mariabackup does back up the original server's value of gtid_current_pos in the xtrabackup_binlog_info file.

      https://mariadb.com/kb/en/library/files-created-by-mariabackup/#xtrabackup_binlog_info

      This means that if a user wants to build a slave using a backup, then they can restore the backup, and then they can extract the original server's gtid_current_pos from xtrabackup_binlog_info:

      $ cat xtrabackup_binlog_info
      mariadb-bin.000096 568 0-1-2
      

      And then the user would need to use this value to set the value of gtid_slave_pos, and then they could set up replication:

      SET GLOBAL gtid_slave_pos='0-1-2';
      CHANGE MASTER TO
        ...
        MASTER_USE_GTID=slave_pos;
      

      Some users would prefer if the value of gtid_slave_pos would automatically be set to the original server's gtid_current_pos when a backup was prepared. That way, users would not have to worry about manually fixing the GTID state, and they could just set up replication from a slave created from a backup by doing something like this:

      CHANGE MASTER TO
        ...
        MASTER_USE_GTID=slave_pos;
      

      And the slave would automatically know where to start replicating from.

      Attachments

        Issue Links

          Activity

            Elkin Andrei Elkin added a comment - - edited

            > Both gtid_binlog_pos / gtid_binlog_state and gtid_slave_pos would be included somewhere in the backup.
            That was the idea. gtid_current_pos would not be saved, as I considered that on the recipient side the above two would suffice.
            But actually they can't compose the like of gtid_current_pos for Recipient ({R), e.g when Donor (D) is another slave that locally changed its gtid_binlog_state with a transaction g. Then even though R.gtid_binlog_state possesses g, R.gtid_current_pos does not which clearly is a problem (rather the very problem).

            So I'd rather we go with your plan, GeoffMontee. Why won't we just set the slave and binlog state on the recipient from the donor's
            current one that is provided by backup configuration: R.gtid_slave_pos = R.gtid_binlog_state = backup.gtid_current_pos ? (I don't write D.gtid_current_pos on purpose, avoiding to refer the variable to be possibly deprecated). Such R would be set to work in either role.

            Elkin Andrei Elkin added a comment - - edited > Both gtid_binlog_pos / gtid_binlog_state and gtid_slave_pos would be included somewhere in the backup. That was the idea. gtid_current_pos would not be saved, as I considered that on the recipient side the above two would suffice. But actually they can't compose the like of gtid_current_pos for Recipient ({ R ), e.g when Donor ( D ) is another slave that locally changed its gtid_binlog_state with a transaction g . Then even though R.gtid_binlog_state possesses g , R.gtid_current_pos does not which clearly is a problem (rather the very problem). So I'd rather we go with your plan, GeoffMontee . Why won't we just set the slave and binlog state on the recipient from the donor's current one that is provided by backup configuration: R.gtid_slave_pos = R.gtid_binlog_state = backup.gtid_current_pos ? (I don't write D.gtid_current_pos on purpose, avoiding to refer the variable to be possibly deprecated). Such R would be set to work in either role.
            Elkin Andrei Elkin added a comment -

            More to

            Both gtid_binlog_pos / gtid_binlog_state and gtid_slave_pos would be included

            I think they should be added to the backup configuration (xtrabackup_binlog_info) at least for flexibility.
            We could also consider another backup restore feature which would make g:s of my previous comment to migrate from
            backup.gtid_binlog_state into R.gtid_slave_pos which is an equivalent solution to the current issue.

            Elkin Andrei Elkin added a comment - More to Both gtid_binlog_pos / gtid_binlog_state and gtid_slave_pos would be included I think they should be added to the backup configuration (xtrabackup_binlog_info) at least for flexibility. We could also consider another backup restore feature which would make g :s of my previous comment to migrate from backup.gtid_binlog_state into R.gtid_slave_pos which is an equivalent solution to the current issue.

            Hi Elkin,

            Why won't we just set the slave and binlog state on the recipient from the donor's current one that is provided by backup configuration: R.gtid_slave_pos = R.gtid_binlog_state = backup.gtid_current_pos ?

            If I understand correctly, this approach sounds a bit different than what I am suggesting.

            It sounds like you are suggesting to implement it like this:

            1.) The customer backs up their primary server:

            $ mariadb-backup --backup \
               --target-dir=/var/mariadb/backup/ \
               --user=mariabackup --password=mypassword
            

            In the new implementation:

            • Both gtid_binlog_state and gtid_slave_pos would be included somewhere in the backup.

            2.) The customer prepares the backup, and provides an option to set both gtid_slave_pos and gtid_binlog_state:

            $ mariadb-backup --prepare \
               --set-gtid-pos \
               --target-dir=/var/mariadb/backup/
            

            In the new implementation:

            • MariaDB Backup would prepare the backup, as normal.
            • MariaDB Backup would set gtid_slave_pos to the the value of gtid_slave_pos from the backup.
            • MariaDB Backup would set gtid_binlog_state to the the value of gtid_binlog_state from the backup.

            Unfortunately, I don't think this approach will be a viable solution for the problems reported by some customers.

            The problem with this approach is the same problem described by MDEV-18404. When you are setting up a brand new slave from a backup of the master, the new slave is going to have a different server_id value. If you try to set gtid_binlog_state on the new slave to the same value retrieved from the master, it will have an entirely different effect on the new slave bcause of the different server_id value. On the new slave, the GTIDs in gtid_binlog_state will not effect replication, regardless of whether you specify MASTER_USE_GTID=current_pos or MASTER_USE_GTID=slave_pos:

            • The GTIDs in gtid_binlog_state will not effect replication with MASTER_USE_GTID=current_pos, because the GTIDs with different server_id values in gtid_binlog_state will not affect the position of gtid_current_pos). This is shown by the example in MDEV-18404.
            • The GTIDs in gtid_binlog_state will not effect replication with MASTER_USE_GTID=slave_pos, because the GTIDs in gtid_binlog_state do not affect the position of gtid_slave_pos at all. This is expected behavior.

            Since the GTIDs in gtid_binlog_state will not be used for replication, this proposal does not seem to provide the solution requested by this Jira issue, which is to make it easier to configure new replication slaves from a backup of the master.

            Am I understanding your proposal correctly? If so, what specific use case is your proposal designed to solve?

            We could also consider another backup restore feature which would make g:s of my previous comment to migrate from backup.gtid_binlog_state into R.gtid_slave_pos which is an equivalent solution to the current issue.

            If we want to make it easier to configure new replication slaves from a backup of the master, then I think this is the approach we should take. If the old master's GTIDs are not migrated from gtid_binlog_state to gtid_slave_pos, then even if we restore gtid_binlog_state on the new slave, those GTIDs in gtid_binlog_state will not be used for replication at all, regardless of whether you specify MASTER_USE_GTID=current_pos or MASTER_USE_GTID=slave_pos.

            In my opinion, it makes the most sense to migrate gtid_binlog_state to gtid_slave_pos. However, you may have other use cases in mind than I do.

            Thanks!

            GeoffMontee Geoff Montee (Inactive) added a comment - Hi Elkin , Why won't we just set the slave and binlog state on the recipient from the donor's current one that is provided by backup configuration: R.gtid_slave_pos = R.gtid_binlog_state = backup.gtid_current_pos ? If I understand correctly, this approach sounds a bit different than what I am suggesting. It sounds like you are suggesting to implement it like this: 1.) The customer backs up their primary server: $ mariadb-backup --backup \ --target-dir=/var/mariadb/backup/ \ --user=mariabackup --password=mypassword In the new implementation: Both gtid_binlog_state and gtid_slave_pos would be included somewhere in the backup. 2.) The customer prepares the backup, and provides an option to set both gtid_slave_pos and gtid_binlog_state : $ mariadb-backup --prepare \ --set-gtid-pos \ --target-dir=/var/mariadb/backup/ In the new implementation: MariaDB Backup would prepare the backup, as normal. MariaDB Backup would set gtid_slave_pos to the the value of gtid_slave_pos from the backup. MariaDB Backup would set gtid_binlog_state to the the value of gtid_binlog_state from the backup. Unfortunately, I don't think this approach will be a viable solution for the problems reported by some customers. The problem with this approach is the same problem described by MDEV-18404 . When you are setting up a brand new slave from a backup of the master, the new slave is going to have a different server_id value. If you try to set gtid_binlog_state on the new slave to the same value retrieved from the master, it will have an entirely different effect on the new slave bcause of the different server_id value. On the new slave, the GTIDs in gtid_binlog_state will not effect replication, regardless of whether you specify MASTER_USE_GTID=current_pos or MASTER_USE_GTID=slave_pos : The GTIDs in gtid_binlog_state will not effect replication with MASTER_USE_GTID=current_pos , because the GTIDs with different server_id values in gtid_binlog_state will not affect the position of gtid_current_pos ). This is shown by the example in MDEV-18404 . The GTIDs in gtid_binlog_state will not effect replication with MASTER_USE_GTID=slave_pos , because the GTIDs in gtid_binlog_state do not affect the position of gtid_slave_pos at all. This is expected behavior. Since the GTIDs in gtid_binlog_state will not be used for replication, this proposal does not seem to provide the solution requested by this Jira issue, which is to make it easier to configure new replication slaves from a backup of the master. Am I understanding your proposal correctly? If so, what specific use case is your proposal designed to solve? We could also consider another backup restore feature which would make g:s of my previous comment to migrate from backup.gtid_binlog_state into R.gtid_slave_pos which is an equivalent solution to the current issue. If we want to make it easier to configure new replication slaves from a backup of the master, then I think this is the approach we should take. If the old master's GTIDs are not migrated from gtid_binlog_state to gtid_slave_pos , then even if we restore gtid_binlog_state on the new slave, those GTIDs in gtid_binlog_state will not be used for replication at all, regardless of whether you specify MASTER_USE_GTID=current_pos or MASTER_USE_GTID=slave_pos . In my opinion, it makes the most sense to migrate gtid_binlog_state to gtid_slave_pos . However, you may have other use cases in mind than I do. Thanks!
            Elkin Andrei Elkin added a comment -

            GeoffMontee, thanks for a pretty detailed reply! To clear out some questions, in
            R.gtid_slave_pos = R.gtid_binlog_state = backup.gtid_current_pos

            I intended to set both recipient's gtid states to the same value of the current gtid pos computed as if the computation happened to the donor's side variable (that is on the donor).
            I thought that such way set slave gtid state of R allows for MASTER_USE_GTID=slave_pos slave role.

            But it's rude actually. What if D is a slave that updated binlog locally so gained gtid:s which were not replicated.
            Those must not contribute to R.gtid_slave_pos, and then the D side gtid_current_pos computation rule turns to be critical.

            And I was not really correct on the master role safety. E.g should binlog files also be copied with the backup image/configuration, possibly not-binlogged (log-slave-updates=0) slave role GTID:s would not be found.

            Considering what you said and the above I still strive for the idea that you seem to support:

            it makes the most sense to migrate gtid_binlog_state to gtid_slave_pos.

            Let backup --prepare sets straight R.gtid_binlog_state = D.gtid_binlog_state and
            optionally computes R.gtid_slave_pos = backup.gtid_current_pos (D.server_id must be provided in the backup conf file for computing that).
            The user should also be warned that
            MASTER_USE_GTID=current_pos is not an option on the backup-restored server.

            The new option applies to:

            • If D is a master server possibly having a slice of the slave state (e.g from some past time), R.gtid_slave_pos will reflect the total gtid D's state correctly.
            • If D is a slave server, not having anything logged locally the computed R's gtid slave state reflects the D total gtid state too, for both {{log-slave-updates=0,1}.

            but not

            • If D is a slave server that had some "own" local updates binlogged, while R is going to take on the slave role itself. These ones were not supposed to be replicated, so could not be found on any master.
            • if D is a master server that bin-logged "foreign" server_id GTID:s - (SET @@server_id="foreign_id" e.g by mysqlbinlog). While those would/could be replicated, computation of backup.gtid_current_pos by backup --prepare would not involve them.
              Since such GTID:s would be part of a part of D.gtid_binlog_state, we may consider to force them info backup.gtid_current_pos. Seems yet another option is necessary. I need to return to this case later.

            Could you please review this. Cheers!

            Elkin Andrei Elkin added a comment - GeoffMontee , thanks for a pretty detailed reply! To clear out some questions, in R.gtid_slave_pos = R.gtid_binlog_state = backup.gtid_current_pos I intended to set both recipient's gtid states to the same value of the current gtid pos computed as if the computation happened to the donor's side variable (that is on the donor). I thought that such way set slave gtid state of R allows for MASTER_USE_GTID=slave_pos slave role. But it's rude actually. What if D is a slave that updated binlog locally so gained gtid :s which were not replicated. Those must not contribute to R.gtid_slave_pos , and then the D side gtid_current_pos computation rule turns to be critical. And I was not really correct on the master role safety. E.g should binlog files also be copied with the backup image/configuration, possibly not-binlogged (log-slave-updates=0) slave role GTID :s would not be found. Considering what you said and the above I still strive for the idea that you seem to support: it makes the most sense to migrate gtid_binlog_state to gtid_slave_pos. Let backup --prepare sets straight R.gtid_binlog_state = D.gtid_binlog_state and optionally computes R.gtid_slave_pos = backup.gtid_current_pos (D.server_id must be provided in the backup conf file for computing that). The user should also be warned that MASTER_USE_GTID=current_pos is not an option on the backup-restored server. The new option applies to: If D is a master server possibly having a slice of the slave state (e.g from some past time), R.gtid_slave_pos will reflect the total gtid D 's state correctly. If D is a slave server, not having anything logged locally the computed R 's gtid slave state reflects the D total gtid state too, for both {{log-slave-updates=0,1}. but not If D is a slave server that had some "own" local updates binlogged, while R is going to take on the slave role itself. These ones were not supposed to be replicated, so could not be found on any master. if D is a master server that bin-logged "foreign" server_id GTID :s - ( SET @@server_id="foreign_id" e.g by mysqlbinlog ). While those would/could be replicated, computation of backup.gtid_current_pos by backup --prepare would not involve them. Since such GTID :s would be part of a part of D.gtid_binlog_state , we may consider to force them info backup.gtid_current_pos . Seems yet another option is necessary. I need to return to this case later. Could you please review this. Cheers!
            serg Sergei Golubchik added a comment - - edited

            GeoffMontee, I'm leaning towards the thought that it's not mariabackup job to do. mariabackup is a backup/restore tool. Its job is to back the data up and to restore it, as close as possible to the original, ideally 1:1. Intentionally modifying tables as a part of the restore (that is, making changes in mysql.gtid_slave_pos table) is contrary to what a backup/restore is. It could be a different tool or a mariabackup wrapper, like "restore a backup and prepare the slave for replication". But I think these are two different steps. First one restores a backup, getting an identical copy of the original, then one prepares it for replication, which causes the data no longer be an "identical copy of the original", so, technically, not a restored backup anymore.

            serg Sergei Golubchik added a comment - - edited GeoffMontee , I'm leaning towards the thought that it's not mariabackup job to do. mariabackup is a backup/restore tool. Its job is to back the data up and to restore it, as close as possible to the original, ideally 1:1. Intentionally modifying tables as a part of the restore (that is, making changes in mysql.gtid_slave_pos table) is contrary to what a backup/restore is. It could be a different tool or a mariabackup wrapper, like "restore a backup and prepare the slave for replication". But I think these are two different steps. First one restores a backup , getting an identical copy of the original, then one prepares it for replication , which causes the data no longer be an "identical copy of the original", so, technically, not a restored backup anymore.

            People

              michael.amadi Michael Amadi
              cole.busby Cole Busby (Inactive)
              Votes:
              2 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.