Статьи

Фильтры репликации и частичные изменения репликации в новом MySQL 5.7

shutterstock_253451584

MySQL 5.7 имеет множество улучшений и новых функций. Я суммировал этот список ранее в этом сообщении в блоге .

Добавление фильтров репликации в режиме онлайн является одной из функций MySQL 5.7, описанных в этом  руководстве . Тем не менее, я опишу и обобщу несколько примеров в этом посте.

Фильтрация событий репликации также известна как частичная репликация. Частичная репликация может быть сделана от ведущего или ведомого. Фильтрация событий на главном сервере через binlog-do-db и binlog-ignore-db не очень хорошая идея, как объясняется в этом посте . Однако, если вам это действительно нужно, лучше использовать частичную репликацию на ведомом устройстве. Наш генеральный директор Питер Зайцев  некоторое время назад написал подробный пост в блоге о фильтрованной репликации MySQL, который может оказаться полезным.

Частичная репликация работает по-разному для репликации на основе операторов и строк. Вы можете найти подробности в  руководстве и на этой странице руководства . Полезно знать, как MySQL оценивает правила частичной репликации.

До MySQL 5.7 добавление / изменение правил репликации требовало отказов сервера MySQL. В MySQL 5.7 добавление / изменение правил фильтра репликации становится оперативной операцией без перезапуска сервера MySQL с помощью команды CHANGE REPLICATION FILTER. Позвольте мне поделиться несколькими примерами:

В настоящее время подчиненный сервер работает без фильтрованной репликации, и это можно проверить по статусу подчиненного устройства и последним пяти переменным. Replicate_ * имеет пустое значение, что означает, что правила фильтра репликации не установлены.

mysql> show slave statusG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000002
          Read_Master_Log_Pos: 351
               Relay_Log_File: centos59-relay-bin.000003
                Relay_Log_Pos: 566
        Relay_Master_Log_File: master-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
.

Главный сервер базы данных содержит db1-db4. Давайте реплицируем только db1 и db2 из четырех баз данных. Это можно сделать с помощью опции replicate-do-db .

mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db1, db2);
ERROR 3017 (HY000): This operation cannot be performed with a running slave sql thread; run STOP SLAVE SQL_THREAD first

Эта ошибка CHANGE REPLICATION FILTER не поддерживается на работающем ведомом устройстве. Сначала нужно остановить подчиненный поток SQL и повторно запустить команду, чтобы установить параметр replicate-do-db. Проверка статуса подчиненного устройства подтвердила, что подчиненное устройство теперь реплицирует только базы данных db1 и db2 из четырех баз данных.

mysql> STOP SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db1, db2);
Query OK, 0 rows affected (0.00 sec)
mysql> show slave statusG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000002
          Read_Master_Log_Pos: 505
               Relay_Log_File: centos59-relay-bin.000003
                Relay_Log_Pos: 720
        Relay_Master_Log_File: master-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: db1,db2
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
.

Чтобы удалить этот фильтр, вам нужно пустое значение для имени фильтра; то есть, replicate-do-db, как показано ниже. Статус ведомого подтвердил, что для переменной replicate-do-db не заданы фильтры репликации.

mysql> STOP SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.03 sec)
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = ();
Query OK, 0 rows affected (0.00 sec)
mysql> START SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUSG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000002
          Read_Master_Log_Pos: 1629
               Relay_Log_File: centos59-relay-bin.000003
                Relay_Log_Pos: 1844
        Relay_Master_Log_File: master-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
.

Кроме того, несколько разных фильтров репликации могут быть установлены в одной команде и должны быть разделены запятой, как показано ниже:

mysql> STOP SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.03 sec)
mysql> CHANGE REPLICATION FILTER
REPLICATE_WILD_DO_TABLE = ('db1.db1_new%'),
REPLICATE_WILD_IGNORE_TABLE =  ('db1.db1_old%');
mysql> START SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUSG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000003
          Read_Master_Log_Pos: 448
               Relay_Log_File: centos59-relay-bin.000006
                Relay_Log_Pos: 663
        Relay_Master_Log_File: master-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table: db1.db1_new%
  Replicate_Wild_Ignore_Table: db1.db1_old1%
.

Состояние ведомого устройства проверяет, что есть несколько установленных фильтров репликации, где db1.db1_new реплицирует двоичные события журнала на ведомое устройство, которое игнорирует события репликации на ведомом устройстве для таблиц db1.db1_old согласно фильтру Replicate_Wild_Ignore_Table . Кроме того, если имя базы данных или таблицы не содержит каких-либо специальных символов, тогда нет необходимости указывать в качестве значения для фильтра. Однако Replicate_Wild_Do_Table и Replicate_Wild_Ignore_Table являются строковыми выражениями и могут содержать символы подстановки, поэтому их необходимо заключать в кавычки.

С помощью команды CHANGE REPLICATION FILTER вы не можете установить одно и то же правило фильтрации несколько раз, в отличие от поведения, когда вы можете установить несколько фильтров для одного и того же правила в файле my.cnf, указав его несколько раз. С помощью команды CHANGE REPLICATION FILTER, если вы попытаетесь установить несколько фильтров для одного и того же правила, будет активировано только последнее правило, а все вышеперечисленные правила будут проигнорированы, как показано в следующем примере:

mysql> SELECT * FROM db1.db1_old;
Empty set (0.00 sec)
mysql> STOP SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.03 sec)
mysql> CHANGE REPLICATION FILTER
REPLICATE_WILD_DO_TABLE = ('db2.db2_tbl1%'),
REPLICATE_WILD_DO_TABLE =  ('db2.db2_tbl2%');
mysql> START SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUSG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000003
          Read_Master_Log_Pos: 980
               Relay_Log_File: centos59-relay-bin.000006
                Relay_Log_Pos: 1195
        Relay_Master_Log_File: master-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table: db2.db2_tbl2%
  Replicate_Wild_Ignore_Table:
.

Как видите, таблица db2.db2_tbl1 игнорируется и активируется только последнее правило для таблицы db2.db2_tbl2.

Как я упоминал ранее, чтобы отменить фильтры любого типа, вам нужно установить этот конкретный фильтр на пустое значение. В приведенном ниже примере будет отключен фильтр Replicate_Wild_Do_Table.

mysql> CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ();

Однако вы можете установить несколько фильтров в одной команде, разделяя каждое правило запятой, как в предыдущем примере с Replicate_Do_DB. Давайте установим несколько правил для опции Replicate_Wild_Do_Table с помощью команды CHANGE REPLICATION FILTER.

mysql> STOP SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.03 sec)
mysql> CHANGE REPLICATION FILTER
REPLICATE_WILD_DO_TABLE = ('db2.db2_tbl1%','db2.db2_tbl2%');
Query OK, 0 rows affected (0.00 sec)
mysql> START SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUSG
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000008
          Read_Master_Log_Pos: 154
               Relay_Log_File: centos59-relay-bin.000013
                Relay_Log_Pos: 369
        Relay_Master_Log_File: master-bin.000008
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table: db2.db2_tbl1%,db2.db2_tbl2%
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
.
.

Вывод:
частичная репликация не является хорошим решением в большинстве случаев. Все параметры replicate-do-table, replicate-ignore-table , replicate-wild-do-table и replicate-wild- do-table  и  replicate-wild-ignore-table работают по-разному. Вам нужно использовать базу данных по умолчанию для нормальной работы фильтрации, и она ведет себя по-разному в другом формате binlog. Фильтры, отличные от replicate-wild-do-table и replicate-wild-ignore-table, могут работать не так, как ожидалось, и события с wild% фильтрами хранимых процедур и хранимых функций могут быть несовместимыми .

[Эта статья была написана Мухаммедом Ирфаном в Перконе]