92 if ($arMasterNode[
'ID'] == 1)
98 $DB = CDatabase::GetDBNodeConnection($arMasterNode[
'ID'],
true);
104 $is_ok = $server_id > 0;
107 'MESSAGE' =>
GetMessage(
'CLU_SERVER_ID_MSG', [
'#server-id#' => $server_id]),
108 'WIZ_REC' =>
GetMessage(
'CLU_SERVER_ID_WIZREC'),
112 $is_ok = $log_bin ===
'ON';
115 'MESSAGE' =>
GetMessage(
'CLU_LOG_BIN_MSG', [
'#log-bin#' => $log_bin]),
116 'WIZ_REC' =>
GetMessage(
'CLU_LOG_BIN_WIZREC'),
120 $is_ok = $skip_networking ===
'OFF';
123 'MESSAGE' =>
GetMessage(
'CLU_SKIP_NETWORKING_MSG', [
'#skip-networking#' => $skip_networking]),
124 'WIZ_REC' =>
GetMessage(
'CLU_SKIP_NETWORKING_WIZREC'),
127 $innodb_flush_log_at_trx_commit = $this->
GetServerVariable(
$DB,
'innodb_flush_log_at_trx_commit');
128 $is_ok = $innodb_flush_log_at_trx_commit ===
'1';
129 $result[
'innodb_flush_log_at_trx_commit'] = [
131 'MESSAGE' =>
GetMessage(
'CLU_FLUSH_ON_COMMIT_MSG', [
'#innodb_flush_log_at_trx_commit#' => $innodb_flush_log_at_trx_commit]),
136 $is_ok = $sync_binlog ===
'1';
139 'MESSAGE' =>
GetMessage(
'CLU_SYNC_BINLOG_MSG', [
'#sync_binlog#' => $sync_binlog]),
144 $isSuperRequred = version_compare($master_version,
'8.0') < 0;
147 $rs =
$DB->Query(
'SHOW GRANTS FOR CURRENT_USER');
148 while (
$ar =
$rs->Fetch())
150 $privilege = array_pop(
$ar);
151 if (preg_match(
'/^GRANT (.+?) ON/', $privilege, $match))
153 $privileges = array_merge($privileges, array_map(
'trim', explode(
',', $match[1])));
158 if ($isSuperRequred && !in_array(
'SUPER', $privileges,
true))
160 $grantList[] =
'SUPER';
162 if (!in_array(
'REPLICATION CLIENT', $privileges,
true))
164 $grantList[] =
'REPLICATION CLIENT';
166 if (!$isSuperRequred && !in_array(
'REPLICATION_SLAVE_ADMIN', $privileges,
true))
168 $grantList[] =
'REPLICATION_SLAVE_ADMIN';
173 'MESSAGE' =>
GetMessage(
'CLU_SLAVE_PRIVILEGE_MSG'),
174 'WIZ_REC' => ($grantList ?
GetMessage(
'CLU_MASTER_STATUS_WIZREC', [
175 '#sql#' =>
'GRANT ' . implode(
', ', $grantList) .
" on *.* to '" .
$DB->DBLogin .
"'@'%';",
179 $DatabaseName =
$DB->DBName;
181 $rsBinLogs =
$DB->Query(
'show master status',
true,
'', [
'fixed_connection' =>
true]);
186 'MESSAGE' =>
GetMessage(
'CLU_MASTER_STATUS_MSG'),
187 'WIZ_REC' =>
GetMessage(
'CLU_MASTER_STATUS_WIZREC', [
'#sql#' =>
"GRANT REPLICATION CLIENT on *.* to '" .
$DB->DBLogin .
"'@'%';"]),
192 if (
$ar = $rsBinLogs->Fetch())
194 $Binlog_Do_DB = implode(
',', array_keys(array_flip(explode(
',',
$ar[
'Binlog_Do_DB']))));
195 if ($Binlog_Do_DB === $DatabaseName)
200 if ($rsBinLogs->Fetch())
207 'MESSAGE' =>
GetMessage(
'CLU_SYNC_BINLOGDODB_MSG'),
208 'WIZ_REC' =>
GetMessage(
'CLU_SYNC_BINLOGDODB_WIZREC', [
'#database#' => $DatabaseName]),
226 '=ROLE_ID' => [
'MAIN',
'MASTER'],
229 while ($arData =
$rsData->Fetch())
231 $arMasters[$arData[
'ID']] = $arData;
234 foreach ($arMasters as $node_id => $arNode)
242 $nodeDB = CDatabase::GetDBNodeConnection($node_id,
true);
244 $arMasters[$node_id][
'DB'] = $nodeDB;
247 $auto_increment_increment =
count($arMasters) + 1;
249 foreach ($arMasters as $node_id => $arNode)
252 if ($inc != $auto_increment_increment)
255 $result[$node_id .
'_auto_increment_increment'] = [
257 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_ERR_MSG', [
'#node_id#' => $node_id,
'#value#' => $auto_increment_increment,
'#current#' => $inc]),
258 'WIZ_REC' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_WIZREC', [
'#value#' => $auto_increment_increment]),
264 $result[
'_auto_increment_increment'] = [
266 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_OK_MSG', [
'#value#' => $auto_increment_increment]),
271 $auto_increment_offset = [];
273 foreach ($arMasters as $node_id => $arNode)
276 $mod = $offset % $auto_increment_increment;
277 if (array_key_exists(
$mod, $auto_increment_offset))
280 $result[$node_id .
'_auto_increment_offset'] = [
282 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_ERR_MSG', [
'#node_id#' => $node_id,
'#current#' => $offset]),
283 'WIZ_REC' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_WIZREC', [
'#current#' => $offset]),
288 $auto_increment_offset[
$mod] = $node_id;
293 $result[
'_auto_increment_offset'] = [
295 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_OK_MSG', [
'#value#' => $auto_increment_increment]),
301 foreach ($arMasters as $node_id => $arNode)
304 if ($relay_log ==
'')
307 $result[$node_id .
'_relay_log'] = [
309 'MESSAGE' =>
GetMessage(
'CLU_RELAY_LOG_ERR_MSG', [
'#node_id#' => $node_id,
'#relay-log#' => $relay_log]),
310 'WIZ_REC' =>
GetMessage(
'CLU_RELAY_LOG_WIZREC'),
318 'MESSAGE' =>
GetMessage(
'CLU_RELAY_LOG_OK_MSG'),
323 $bSlaveUpdatesIsOK =
true;
324 foreach ($arMasters as $node_id => $arNode)
326 $log_slave_updates = $this->
GetServerVariable($arNode[
'DB'],
'log_slave_updates');
327 if ($log_slave_updates !==
'ON')
329 $bSlaveUpdatesIsOK =
false;
330 $result[$node_id .
'_log_slave_updates'] = [
332 'MESSAGE' =>
GetMessage(
'CLU_LOG_SLAVE_UPDATES_MSG', [
'#node_id#' => $node_id,
'#log-slave-updates#' => $log_slave_updates]),
333 'WIZ_REC' =>
GetMessage(
'CLU_LOG_SLAVE_UPDATES_WIZREC', [
'#value#' => 1]),
337 if ($bSlaveUpdatesIsOK)
339 $result[
'_log_slave_updates'] = [
341 'MESSAGE' =>
GetMessage(
'CLU_LOG_SLAVE_UPDATES_OK_MSG'),
354 'STATUS' =>
'ONLINE',
355 'DB_HOST' => $db_host,
356 'DB_NAME' => $db_name,
357 'DB_LOGIN' => $db_login,
358 'DB_PASSWORD' => $db_password,
364 $nodeDB = CDatabase::GetDBNodeConnection($node_id,
true);
365 $error = ob_get_contents();
368 catch (\
Bitrix\Main\DB\ConnectionException $e)
371 $error = $e->getMessage();
374 if (is_object($nodeDB))
377 $rs = $nodeDB->Query(
'show slave status',
true,
'', [
'fixed_connection' =>
true]);
380 if (
$ar &&
$ar[
'Slave_IO_State'] <>
'')
382 if (
$ar[
'Master_Host'] == $master_host &&
$ar[
'Master_Port'] == $master_port)
402 public function SlaveNodeConnection($db_host, $db_name, $db_login, $db_password, $master_host=
false, $master_port=
false, $master_id = 1)
409 'STATUS' =>
'ONLINE',
410 'DB_HOST' => $db_host,
411 'DB_NAME' => $db_name,
412 'DB_LOGIN' => $db_login,
413 'DB_PASSWORD' => $db_password,
419 $nodeDB = CDatabase::GetDBNodeConnection($node_id,
true);
420 $error = ob_get_contents();
423 catch (\
Bitrix\Main\DB\ConnectionException $e)
426 $error = $e->getMessage();
429 if (is_object($nodeDB))
432 $bSkipSecondTest =
false;
434 $rs = $nodeDB->Query(
'show slave status',
true,
'', [
'fixed_connection' =>
true]);
438 if (
$ar[
'Slave_IO_State'] <>
'')
440 if (
$ar[
'Master_Host'] != $master_host ||
$ar[
'Master_Port'] != $master_port)
446 $bSkipSecondTest =
true;
451 if ($nodeDB->TableExists(
'b_cluster_dbnode') && !$bSkipSecondTest)
454 $uniqid = md5(mt_rand());
455 $DB->Query(
"UPDATE b_cluster_dbnode SET UNIQID='" . $uniqid .
"' WHERE ID=1",
false,
'', [
'fixed_connection' =>
true]);
456 $rs = $nodeDB->Query(
'SELECT UNIQID FROM b_cluster_dbnode WHERE ID=1',
true);
461 if (
$ar[
'UNIQID'] == $uniqid)
469 if ($master_host !==
false && $master_port !==
false)
476 'STATUS' =>
'ONLINE',
477 'DB_HOST' => $master_host .
':' . $master_port,
478 'DB_NAME' =>
$DB->DBName,
479 'DB_LOGIN' =>
$DB->DBLogin,
480 'DB_PASSWORD' =>
$DB->DBPassword,
485 $node_id = $master_id;
489 $masterDB = CDatabase::GetDBNodeConnection($node_id,
true);
490 $error = ob_get_contents();
492 if (is_object($masterDB))
495 if (!$masterDB->TableExists(
'b_cluster_dbnode'))
501 $uniqid = md5(mt_rand());
502 $DB->Query(
"UPDATE b_cluster_dbnode SET UNIQID='" . $uniqid .
"' WHERE ID=1",
false,
'', [
'fixed_connection' =>
true]);
504 $Seconds_Behind_Master = 1;
505 $rs = $masterDB->Query(
'SHOW SLAVE STATUS');
508 if (
$ar[
'Seconds_Behind_Master'] > 0)
510 $Seconds_Behind_Master +=
$ar[
'Seconds_Behind_Master'];
513 sleep($Seconds_Behind_Master);
515 $rs = $masterDB->Query(
'SELECT UNIQID FROM b_cluster_dbnode WHERE ID=1',
true,
'', [
'fixed_connection' =>
true]);
527 if (
$ar[
'UNIQID'] != $uniqid)
551 $main_character_set_server = $this->
GetServerVariable($DB,
'character_set_server');
554 $arCharset = static::GetServerVariables($nodeDB, [
555 'character_set_server' =>
'',
556 'character_set_database' =>
'',
557 'character_set_connection' =>
'',
558 'character_set_client' =>
'',
559 ],
'character_set%');
561 $arCollation = static::GetServerVariables($nodeDB, [
562 'collation_server' =>
'',
563 'collation_database' =>
'',
564 'collation_connection' =>
'',
567 $is_ok = $main_character_set_server === $arCharset[
'character_set_server']
568 && $main_collation_server === $arCollation[
'collation_server']
570 $is_ok = $is_ok || (defined(
'BX_CLUSTER_SKIP_CHARSET_CHECK') && constant(
'BX_CLUSTER_SKIP_CHARSET_CHECK') ===
true);
573 'MESSAGE' =>
GetMessage(
'CLU_MASTER_CHARSET_MSG'),
574 'WIZ_REC' =>
GetMessage(
'CLU_MASTER_CHARSET_WIZREC', [
575 '#character_set_server#' => $arCharset[
'character_set_server'],
576 '#collation_server#' => $arCollation[
'collation_server'],
580 $is_ok = $arCharset[
'character_set_server'] !==
''
581 && $arCharset[
'character_set_server'] === $arCharset[
'character_set_database']
582 && $arCharset[
'character_set_database'] === $arCharset[
'character_set_connection']
583 && $arCharset[
'character_set_connection'] === $arCharset[
'character_set_client']
585 $is_ok = $is_ok || (defined(
'BX_CLUSTER_SKIP_CHARSET_CHECK') && constant(
'BX_CLUSTER_SKIP_CHARSET_CHECK') ===
true);
589 'WIZ_REC' =>
GetMessage(
'CLU_CHARSET_WIZREC', [
590 '#character_set_server#' => $arCharset[
'character_set_server'],
591 '#character_set_database#' => $arCharset[
'character_set_database'],
592 '#character_set_connection#' => $arCharset[
'character_set_connection'],
593 '#character_set_client#' => $arCharset[
'character_set_client'],
597 $is_ok = $arCollation[
'collation_server'] !==
''
598 && $arCollation[
'collation_server'] === $arCollation[
'collation_database']
599 && $arCollation[
'collation_database'] === $arCollation[
'collation_connection']
601 $is_ok = $is_ok || (defined(
'BX_CLUSTER_SKIP_CHARSET_CHECK') && constant(
'BX_CLUSTER_SKIP_CHARSET_CHECK') ===
true);
605 'WIZ_REC' =>
GetMessage(
'CLU_COLLATION_WIZREC', [
606 '#collation_server#' => $arCollation[
'collation_server'],
607 '#collation_database#' => $arCollation[
'collation_database'],
608 '#collation_connection#' => $arCollation[
'collation_connection'],
613 0 =>
'drop table b_cluster_test',
614 'sql_create' =>
'create table b_cluster_test(column1 int)',
615 'sql_insert' =>
'insert into b_cluster_test (column1) values (1)',
616 'sql_select' =>
'select * from b_cluster_test',
617 'sql_update' =>
'update b_cluster_test set column1=2 where column1=1',
618 'sql_delete' =>
'delete from b_cluster_test where column1=2',
619 'sql_drop' =>
'drop table b_cluster_test',
622 $sql_erorrs_list =
'';
623 foreach ($arTestSQL as $id => $sql)
625 $res = $nodeDB->Query($sql,
true);
626 if (!
$res && $id !== 0)
629 $sql_erorrs_list .=
'<br /> ' . $sql .
': ' . $nodeDB->db_Error .
"\n";
636 '#sql_erorrs_list#' => $sql_erorrs_list,
640 $required_version =
'5.0.0';
642 $is_ok = version_compare($required_version, $slave_version) <= 0;
645 'MESSAGE' =>
GetMessage(
'CLU_SLAVE_VERSION_MSG', [
646 '#slave-version#' => $slave_version,
647 '#required-version#' => $required_version,
649 'WIZ_REC' =>
GetMessage(
'CLU_VERSION_WIZREC'),
663 $is_ok = $node_server_id > 0 && $main_server_id != $node_server_id;
667 '=SERVER_ID' => $node_server_id,
668 '!=MASTER_ID' =>
false,
670 $is_ok2 = !is_array($rsNodes->Fetch());
679 'MESSAGE' =>
GetMessage(
'CLU_SERVER_ID_MSG', [
'#server-id#' => $node_server_id]),
680 'WIZ_REC' => ($is_ok ?
'' :
GetMessage(
'CLU_SERVER_ID_WIZREC1')) .
' '
681 . ($is_ok2 ?
'' :
GetMessage(
'CLU_SERVER_ID_WIZREC2')) .
' '
686 $master_max_allowed_packet = $this->
GetServerVariable($DB,
'max_allowed_packet');
687 $slave_max_allowed_packet = $this->
GetServerVariable($nodeDB,
'max_allowed_packet');
688 $is_ok = $slave_max_allowed_packet >= $master_max_allowed_packet;
689 $result[
'max_allowed_packet'] = [
691 'MESSAGE' =>
GetMessage(
'CLU_MAX_ALLOWED_PACKET_MSG'),
692 'WIZ_REC' =>
GetMessage(
'CLU_MAX_ALLOWED_PACKET_WIZREC'),
697 $is_ok = version_compare($master_version, $slave_version) <= 0;
701 '#slave-version#' => $slave_version,
702 '#master-version#' => $master_version,
704 'WIZ_REC' =>
GetMessage(
'CLU_VERSION_WIZREC'),
708 $is_ok = $relay_log <>
'';
711 'MESSAGE' =>
GetMessage(
'CLU_SLAVE_RELAY_LOG_MSG'),
712 'WIZ_REC' =>
GetMessage(
'CLU_RELAY_LOG_WIZREC'),
715 $isSuperRequred = version_compare($slave_version,
'8.0') < 0;
718 $rs = $nodeDB->Query(
'SHOW GRANTS FOR CURRENT_USER');
719 while (
$ar =
$rs->Fetch())
721 $privilege = array_pop(
$ar);
722 if (preg_match(
'/^GRANT (.+?) ON/', $privilege, $match))
724 $privileges = array_merge($privileges, array_map(
'trim', explode(
',', $match[1])));
729 if ($isSuperRequred && !in_array(
'SUPER', $privileges,
true))
731 $grantList[] =
'SUPER';
733 if (!in_array(
'REPLICATION CLIENT', $privileges,
true))
735 $grantList[] =
'REPLICATION CLIENT';
737 if (!in_array(
'REPLICATION SLAVE', $privileges,
true))
739 $grantList[] =
'REPLICATION SLAVE';
741 if (!$isSuperRequred && !in_array(
'REPLICATION_SLAVE_ADMIN', $privileges,
true))
743 $grantList[] =
'REPLICATION_SLAVE_ADMIN';
748 'MESSAGE' =>
GetMessage(
'CLU_SLAVE_PRIVILEGE_MSG'),
749 'WIZ_REC' => ($grantList ?
GetMessage(
'CLU_MASTER_STATUS_WIZREC', [
750 '#sql#' =>
'GRANT ' . implode(
', ', $grantList) .
" on *.* to '" . $nodeDB->DBLogin .
"'@'%';",
769 '=ROLE_ID' => [
'MAIN',
'MASTER'],
772 while ($arData =
$rsData->Fetch())
774 $arMasters[$arData[
'ID']] = $arData;
777 $arMasters[
'v99'] = [];
779 foreach ($arMasters as $node_id => $arNode)
787 $nodeDB = CDatabase::GetDBNodeConnection($node_id,
true);
789 $arMasters[$node_id][
'DB'] = $nodeDB;
792 $auto_increment_increment =
count($arMasters);
794 foreach ($arMasters as $node_id => $arNode)
797 if ($inc != $auto_increment_increment)
800 if ($node_id ==
'v99')
802 $result[$node_id .
'_auto_increment_increment'] = [
804 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_NODE_ERR_MSG', [
'#value#' => $auto_increment_increment,
'#current#' => $inc]),
805 'WIZ_REC' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_WIZREC', [
'#value#' => $auto_increment_increment]),
810 $result[$node_id .
'_auto_increment_increment'] = [
812 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_ERR_MSG', [
'#node_id#' => $node_id,
'#value#' => $auto_increment_increment,
'#current#' => $inc]),
813 'WIZ_REC' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_WIZREC', [
'#value#' => $auto_increment_increment]),
820 $result[
'_auto_increment_increment'] = [
822 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_INCREMENT_OK_MSG', [
'#value#' => $auto_increment_increment]),
827 $auto_increment_offset = [];
829 foreach ($arMasters as $node_id => $arNode)
832 $mod = $offset % $auto_increment_increment;
834 if (array_key_exists(
$mod, $auto_increment_offset))
837 if ($node_id ==
'v99')
839 $result[$node_id .
'_auto_increment_offset'] = [
841 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_NODE_ERR_MSG', [
'#current#' => $offset]),
842 'WIZ_REC' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_WIZREC', [
'#current#' => $offset]),
847 $result[$node_id .
'_auto_increment_offset'] = [
849 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_ERR_MSG', [
'#node_id#' => $node_id,
'#current#' => $offset]),
850 'WIZ_REC' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_WIZREC', [
'#current#' => $offset]),
856 $auto_increment_offset[
$mod] = $node_id;
861 $result[
'_auto_increment_offset'] = [
863 'MESSAGE' =>
GetMessage(
'CLU_AUTO_INCREMENT_OFFSET_OK_MSG', [
'#value#' => $auto_increment_increment]),
869 foreach ($arMasters as $node_id => $arNode)
872 if ($relay_log ==
'')
875 $result[$node_id .
'_relay_log'] = [
877 'MESSAGE' =>
GetMessage(
'CLU_RELAY_LOG_ERR_MSG', [
'#node_id#' => $node_id,
'#relay-log#' => $relay_log]),
878 'WIZ_REC' =>
GetMessage(
'CLU_RELAY_LOG_WIZREC'),
886 'MESSAGE' =>
GetMessage(
'CLU_RELAY_LOG_OK_MSG', [
'#value#' => $auto_increment_increment]),
892 $is_ok = $log_bin ===
'ON';
895 'MESSAGE' =>
GetMessage(
'CLU_LOG_BIN_NODE_MSG', [
'#log-bin#' => $log_bin]),
896 'WIZ_REC' =>
GetMessage(
'CLU_LOG_BIN_WIZREC'),
900 $is_ok = $skip_networking ===
'OFF';
903 'MESSAGE' =>
GetMessage(
'CLU_SKIP_NETWORKING_NODE_MSG', [
'#skip-networking#' => $skip_networking]),
904 'WIZ_REC' =>
GetMessage(
'CLU_SKIP_NETWORKING_WIZREC'),
907 $innodb_flush_log_at_trx_commit = $this->
GetServerVariable($nodeDB,
'innodb_flush_log_at_trx_commit');
910 $is_ok = $innodb_flush_log_at_trx_commit ===
'1';
911 $result[
'innodb_flush_log_at_trx_commit'] = [
913 'MESSAGE' =>
GetMessage(
'CLU_FLUSH_ON_COMMIT_MSG', [
'#innodb_flush_log_at_trx_commit#' => $innodb_flush_log_at_trx_commit]),
921 $is_ok = $sync_binlog ===
'1';
924 'MESSAGE' =>
GetMessage(
'CLU_SYNC_BINLOG_MSG', [
'#sync_binlog#' => $sync_binlog]),
929 $DatabaseName =
$DB->DBName;
931 $rsBinLogs = $nodeDB->Query(
'show master status',
true,
'', [
'fixed_connection' =>
true]);
936 'MESSAGE' =>
GetMessage(
'CLU_MASTER_STATUS_MSG'),
937 'WIZ_REC' =>
GetMessage(
'CLU_MASTER_STATUS_WIZREC', [
'#sql#' =>
"GRANT REPLICATION CLIENT on *.* to '" . $nodeDB->DBLogin .
"'@'%';"]),
942 if (
$ar = $rsBinLogs->Fetch())
944 $Binlog_Do_DB = implode(
',', array_keys(array_flip(explode(
',',
$ar[
'Binlog_Do_DB']))));
945 if ($Binlog_Do_DB === $DatabaseName)
950 if ($rsBinLogs->Fetch())
957 'MESSAGE' =>
GetMessage(
'CLU_SYNC_BINLOGDODB_MSG'),
958 'WIZ_REC' =>
GetMessage(
'CLU_SYNC_BINLOGDODB_WIZREC', [
'#database#' => $DatabaseName]),