WL#9110: Add RESET MASTER TO x to allow specification of binlog file number

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

With this extension to RESET MASTER, user will be able to specify which binary
log file index number to start from once the reset happens, instead of starting
from .000001.

1. BACKGROUND:

We have a " RESET MASTER " command in Replication, what happens on execution of
this command is it deletes all binary log files listed in the index file,
resets the binary log index file to be empty, and creates a new binary log file.
This is just same as starting a server from scratch.
So every time you issue this command the new index of binary log file will
be 000001, and there was no way to customize that index.

2. GOALS:

To introduce a new parameter in RESET MASTER command where you can specify the
index number you would like to start your binary log file from,
and the old behavior shall remain the same, which is if no extra option is
provided in RESET MASTER start the binary log index from 000001.

3. USER STORIES:

As a MySQL DBA, I want to be able to specify the index of the fresh binary log file
when issuing 'RESET MASTER' command, so that my failover procedure will be simpler,
less complete and more efficient, by replacing FLUSH BINARY LOGS + PURGE BINARY
LOGS TO
with a single 'RESET MASTER' command.

4. PROPOSED CHANGES:

Modify the change 'RESET MASTER' command to accept an argument which specifies the
index of the new binary log file in use.
Functional Requirements:

FR1. The behavior of the command 'RESET MASTER' SHALL NOT be changed.

FR2. 'RESET MASTER TO N' SHALL be a one shot operation, i.e.,
     the next 'RESET MASTER TO N' or 'RESET MASTER' will change the
     index of the fresh binary log file.

FR3. 'RESET MASTER' SHALL be an alias to 'RESET MASTER TO 1' .
     In practice this means that 'RESET MASTER' will set the
     index of the fresh binary log file to 1.

FR4. The accepted N value in RESET MASTER TO MUST be an UNSIGNED INTEGER.
     Any other value SHALL result in a RESET MASTER error.

FR5. The boundaries of N in RESET MASTER TO are [1, 2^31-1].

Non-functional Requirements:

NFR1. 'RESET MASTER TO N' MUST only affect the binary log files
      and the binary log index file, i.e., the same files that
      'RESET MASTER' affects.

NFR2. The changes SHALL NOT introdcue any performance degradation
      to the 'RESET MASTER' command nor to the act of deleting
      and initializing binary log files.

The RESET MASTER command was extended to cover the
requirements stated above. The extensions are:

1. Syntax extension

RESET MASTER accepts now a clause "TO <N>". Thence
the user may issue the following command:

mysql> RESET MASTER TO 1000;

2. The N in RESET MASTER TO <N>

N is an UNSIGNED INTEGER that has its range set to
[1,2^32-1]

Below is an example of the new behavior:


mysql>SHOW BINARY LOGS;
+-------------------+-----------+
| Log_name          | File_size |
+-------------------+-----------+
| master-bin.000001 |       154 |
+-------------------+-----------+
1 row in set (0.02 sec)

mysql> RESET MASTER TO 1234;
Query OK, 0 rows affected (0.05 sec)

mysql> SHOW BINARY LOGS;
+-------------------+-----------+
| Log_name          | File_size |
+-------------------+-----------+
| master-bin.001234 |       154 |
+-------------------+-----------+
1 row in set (0.00 sec)

mysql> flush logs;
Query OK, 0 rows affected (0.04 sec)

mysql> SHOW BINARY LOGS;
+-------------------+-----------+
| Log_name          | File_size |
+-------------------+-----------+
| master-bin.001234 |       202 |
| master-bin.001235 |       154 |
+-------------------+-----------+
2 rows in set (0.00 sec)

And if we execute again RESET MASTER the binary index should be set to default
which was .000001

mysql> RESET MASTER;
Query OK, 0 rows affected (0.03 sec)

mysql> SHOW BINARY LOGS;
+-------------------+-----------+
| Log_name          | File_size |
+-------------------+-----------+
| master-bin.000001 |       154 |
+-------------------+-----------+
1 row in set (0.00 sec)

Upgrade/Downgrade
-----------------
The users that upgrade MySQL Server, will not have to change their scripts
that rely on existing 'RESET MASTER' behavior, because the original behavior
is kept as it was before. We are just extending it.
On the low level design we have the following changes introduced in the code:

- Added a new integer attribute in the struct LEX, which will hold the
  extra argument introduced by this WL for the command RESET MASTER.

sql/sql_lex.h

@@ -3398,6 +3398,7 @@ public:
   bool all_privileges;
   bool contains_plaintext_password;
   enum_keep_diagnostics keep_diagnostics;
+  uint32 next_binlog_file_nr;

 private:
   bool m_broken; ///< see mark_broken()

- All the methods which are involved in creating binary log file are passed an
  extra parameter (new_index_number).

@@ -497,10 +497,12 @@class MYSQL_BIN_LOG: public TC_LOG
  bool open(
#ifdef HAVE_PSI_INTERFACE
             PSI_file_key log_file_key,
#endif
             const char *log_name,
-            const char *new_name);
+            const char *new_name,
+            uint32 new_index_number);

   bool init_and_set_log_file_name(const char *log_name,
-                                  const char *new_name);
-  int generate_new_name(char *new_name, const char *log_name);
+                                  const char *new_name,
+                                  uint32 new_index_number);
+  int generate_new_name(char *new_name, const char *log_name, uint32
new_index_number);

 public:
   const char *generate_name(const char *log_name, const char *suffix,
@@ -811,7 +813,8 @@ public:
  bool open_binlog(const char *log_name,
                    const char *new_name,
                    ulong max_size_arg,
                    bool null_created_arg,
                    bool need_lock_index, bool need_sid_lock,
-                   Format_description_log_event *extra_description_event);
+                   Format_description_log_event *extra_description_event,
+                   uint32 new_index_number);
   bool open_index_file(const char *index_file_name_arg,
                        const char *log_name, bool need_lock_index);
   /* Use this to start writing a new log file */


- When we call open_binlog from reset_logs() method we pass the attribute added
  in the lex structure

@@ -5567,7 +5573,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool delete_only)
                             max_size, false,
                             false/*need_lock_index=false*/,
                             false/*need_sid_lock=false*/,
-                            NULL)))
+                            NULL,
+                            thd->lex->next_binlog_file_nr)))
       goto err;
   }
   my_free((void *) save_name);

- At all other places we pass 0 for that extra parameter introduced in open_binlog()
  and consecutively it is passed to other methods where this extra parameter was
  added.

For example:

sql/binlog.cc
-------------

@@ -6617,7 +6624,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock_log,
Format_description_log_even
     new file name in the current binary log file.
   */
   new_name_ptr= new_name;
-  if ((error= generate_new_name(new_name, name)))
+  if ((error= generate_new_name(new_name, name, 0)))
   {
     // Use the old name if generation of new name fails.
     strcpy(new_name, name);
@@ -6709,7 +6716,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock_log,
Format_description_log_even
                        max_size, true/*null_created_arg=true*/,
                        false/*need_lock_index=false*/,
                        true/*need_sid_lock=true*/,
-                       extra_description_event);
+                       extra_description_event, 0);
   }

   /* handle reopening errors */
@@ -7878,7 +7885,7 @@ int MYSQL_BIN_LOG::open_binlog(const char *opt_name)
     open_binlog(opt_name, 0, max_binlog_size, false,
                 true/*need_lock_index=true*/,
                 true/*need_sid_lock=true*/,
-                NULL);
+                NULL, 0);