function InitStep() { global $DB; $wizard =& $this->GetWizard(); $node_id = intval($wizard->GetVar('node_id')); if (!CModule::IncludeModule('cluster')) { $this->SetError(GetMessage('CLUWIZ_NO_MODULE_ERROR')); } elseif ($DB->type != "MYSQL") { $this->SetError(GetMessage('CLUWIZ_DATABASE_NOT_SUPPORTED')); } elseif ($node_id <= 1) { $this->SetError(GetMessage('CLUWIZ_NO_NODE_ERROR')); } else { $this->arNode = CClusterDBNode::GetByID($node_id); if (!is_array($this->arNode)) { $this->SetError(GetMessage('CLUWIZ_NO_NODE_ERROR')); } else { // $arNode["ROLE_ID"] == "SLAVE" // $arNode["STATUS"] == "READY" $this->nodeDB = CDatabase::GetDBNodeConnection($this->arNode["ID"], true, false); if (!is_object($this->nodeDB)) { $this->SetError(GetMessage('CLUWIZ_NO_CONN_ERROR')); } } } }
function GetUpTime($node_id) { if ($node_id > 1) { ob_start(); $DB = CDatabase::GetDBNodeConnection($node_id, true, false); ob_end_clean(); } else { $DB = $GLOBALS["DB"]; } if (is_object($DB)) { $rs = $DB->Query("show status like 'Uptime'", false, '', array('fixed_connection' => true)); if ($ar = $rs->Fetch()) { return $ar["Value"]; } } return false; }
function InitStep() { global $DB; $wizard =& $this->GetWizard(); $node_id = intval($wizard->GetVar('node_id')); if (!CModule::IncludeModule('cluster')) { $this->SetError(GetMessage('CLUWIZ_NO_MODULE_ERROR')); } elseif ($DB->type != "MYSQL") { $this->SetError(GetMessage('CLUWIZ_DATABASE_NOT_SUPPORTED')); } elseif ($node_id <= 1) { $this->SetError(GetMessage('CLUWIZ_NO_NODE_ERROR')); } else { $this->arNode = CClusterDBNode::GetByID($node_id); if (!is_array($this->arNode)) { $this->SetError(GetMessage('CLUWIZ_NO_NODE_ERROR')); } else { // $arNode["ROLE_ID"] == "SLAVE" // $arNode["STATUS"] == "READY" $this->nodeDB = CDatabase::GetDBNodeConnection($this->arNode["ID"], true, false); if (!is_object($this->nodeDB)) { $this->SetError(GetMessage('CLUWIZ_NO_CONN_ERROR')); } else { $arGroup = CClusterGroup::GetArrayByID(intval($wizard->GetVar("group_id"))); if (!$arGroup) { $this->SetError(GetMessage('CLUWIZ_NO_GROUP_ERROR')); } else { $cData = new CClusterDBNode(); $rsData = $cData->GetList(array(), array("=ROLE_ID" => array("MAIN", "MASTER"), "=GROUP_ID" => $arGroup["ID"], "=STATUS" => "ONLINE")); $this->arMaster = $rsData->Fetch(); if (!$this->arMaster) { $this->SetError(GetMessage('CLUWIZ_NO_MASTER_ERROR')); } } } } } }
public function Query($strSql, $bIgnoreErrors = false, $error_position = "", $arOptions = array()) { global $DB; $this->DoConnect(); $this->db_Error = ""; if ($this->DebugToFile || $DB->ShowSqlStat) { $start_time = microtime(true); } //We track queries for DML statements //and when there is no one we can choose //to run query against master connection //or replicated one $connectionPool = \Bitrix\Main\Application::getInstance()->getConnectionPool(); if ($connectionPool->isMasterOnly()) { //We requested to process all queries //by master connection } elseif ($this->bModuleConnection) { //In case of dedicated module database //were is nothing to do } elseif (isset($arOptions["fixed_connection"])) { //We requested to process this query //by current connection } elseif ($this->bNodeConnection) { //It is node so nothing to do } else { if (isset($arOptions["ignore_dml"])) { $connectionPool->ignoreDml(true); } $connection = $connectionPool->getSlaveConnection($strSql); if (isset($arOptions["ignore_dml"])) { $connectionPool->ignoreDml(false); } if ($connection !== null) { if (!isset($this->obSlave)) { $nodeId = $connection->getNodeId(); ob_start(); $conn = CDatabase::GetDBNodeConnection($nodeId, true); ob_end_clean(); if (is_object($conn)) { $this->obSlave = $conn; } else { self::$arNodes[$nodeId]["ONHIT_ERROR"] = true; CClusterDBNode::SetOffline($nodeId); } } if (is_object($this->obSlave)) { return $this->obSlave->Query($strSql, $bIgnoreErrors, $error_position, $arOptions); } } } $result = $this->QueryInternal($strSql); if ($this->DebugToFile || $DB->ShowSqlStat) { /** @noinspection PhpUndefinedVariableInspection */ $exec_time = round(microtime(true) - $start_time, 10); if ($DB->ShowSqlStat) { $DB->addDebugQuery($strSql, $exec_time, $connectionPool->isSlavePossible() ? $this->node_id : -1); } if ($this->DebugToFile) { $this->startSqlTracker()->writeFileLog($strSql, $exec_time, "CONN: " . $this->getThreadId()); } } if (!$result) { $this->db_Error = $this->GetError(); $this->db_ErrorSQL = $strSql; if (!$bIgnoreErrors) { AddMessage2Log($error_position . " MySql Query Error: " . $strSql . " [" . $this->db_Error . "]", "main"); if ($this->DebugToFile) { $this->startSqlTracker()->writeFileLog("ERROR: " . $this->db_Error, 0, "CONN: " . $this->getThreadId()); } if ($this->debug || @session_start() && $_SESSION["SESS_AUTH"]["ADMIN"]) { echo $error_position . "<br><font color=#ff0000>MySQL Query Error: " . htmlspecialcharsbx($strSql) . "</font>[" . htmlspecialcharsbx($this->db_Error) . "]<br>"; } $error_position = preg_replace("#<br[^>]*>#i", "\n", $error_position); SendError($error_position . "\nMySQL Query Error:\n" . $strSql . " \n [" . $this->db_Error . "]\n---------------\n\n"); if (file_exists($_SERVER["DOCUMENT_ROOT"] . BX_PERSONAL_ROOT . "/php_interface/dbquery_error.php")) { include $_SERVER["DOCUMENT_ROOT"] . BX_PERSONAL_ROOT . "/php_interface/dbquery_error.php"; } elseif (file_exists($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/dbquery_error.php")) { include $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/dbquery_error.php"; } else { die("MySQL Query Error!"); } die; } return false; } $res = new CDBResult($result); $res->DB = $this; if ($DB->ShowSqlStat) { $res->SqlTraceIndex = count($DB->arQueryDebug) - 1; } return $res; }
function SlaveConnection() { if (!class_exists('cmodule') || !class_exists('csqlwhere')) { return null; } if (!CModule::IncludeModule('cluster')) { return false; } $arSlaves = CClusterSlave::GetList(); if (empty($arSlaves)) { return false; } $max_slave_delay = COption::GetOptionInt("cluster", "max_slave_delay", 10); if (isset($_SESSION["BX_REDIRECT_TIME"])) { $redirect_delay = time() - $_SESSION["BX_REDIRECT_TIME"] + 1; if ($redirect_delay > 0 && $redirect_delay < $max_slave_delay) { $max_slave_delay = $redirect_delay; } } $total_weight = 0; foreach ($arSlaves as $i => $slave) { if (defined("BX_CLUSTER_GROUP") && BX_CLUSTER_GROUP != $slave["GROUP_ID"]) { unset($arSlaves[$i]); } elseif ($slave["ROLE_ID"] == "SLAVE") { $arSlaveStatus = CClusterSlave::GetStatus($slave["ID"], true, false, false); if ($arSlaveStatus['Seconds_Behind_Master'] > $max_slave_delay || $arSlaveStatus['Last_SQL_Error'] != '' || $arSlaveStatus['Last_IO_Error'] != '' || $arSlaveStatus['Slave_SQL_Running'] === 'No') { unset($arSlaves[$i]); } else { $total_weight += $slave["WEIGHT"]; } } else { $total_weight += $slave["WEIGHT"]; } } $found = false; foreach ($arSlaves as $slave) { if (mt_rand(0, $total_weight) < $slave["WEIGHT"]) { $found = $slave; break; } } if (!$found || $found["ROLE_ID"] != "SLAVE") { return false; //use main connection } else { ob_start(); $conn = CDatabase::GetDBNodeConnection($found["ID"], true); ob_end_clean(); if (is_object($conn)) { return $conn; } else { self::$arNodes[$found["ID"]]["ONHIT_ERROR"] = true; CClusterDBNode::SetOffline($found["ID"]); return false; //use main connection } } }
require_once $_SERVER["DOCUMENT_ROOT"] . BX_ROOT . "/modules/main/include/epilog_after.php"; die; } require_once $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/classes/general/wizard.php"; $lang = $_REQUEST['lang']; if (!preg_match('/^[a-z0-9_]{2}$/i', $lang)) { $lang = 'en'; } $wizard = new CWizard("bitrix:cluster.slave_start"); $wizard->IncludeWizardLang("scripts/drop.php", $lang); CModule::IncludeModule('cluster'); $node_id = $_REQUEST["node_id"]; if ($node_id <= 1) { $nodeDB = false; } else { $nodeDB = CDatabase::GetDBNodeConnection($node_id, true, false); } if (!is_object($nodeDB)) { echo GetMessage('CLUWIZ_CONNECTION_ERROR'); } else { $arTablesToDelete = array(); $rsTables = $nodeDB->Query("show tables", false, '', array("fixed_connection" => true)); while ($arTable = $rsTables->Fetch()) { $arTablesToDelete[] = $arTable["Tables_in_" . $nodeDB->DBName]; } if (empty($arTablesToDelete)) { echo GetMessage("CLUWIZ_ALL_DONE"); echo '<script>EnableButton();</script>'; } else { $table_name = array_pop($arTablesToDelete); $nodeDB->Query("drop table " . $table_name, false, '', array("fixed_connection" => true));
/** * Returns module database connection. * Can be used only if module supports sharding. * * @param string $module_id * @param bool $bModuleInclude * @return bool|CDatabase */ public static function GetModuleConnection($module_id, $bModuleInclude = false) { $node_id = COption::GetOptionString($module_id, "dbnode_id", "N"); if (is_numeric($node_id)) { if ($bModuleInclude) { $status = COption::GetOptionString($module_id, "dbnode_status", "ok"); if ($status === "move") { return false; } } $moduleDB = CDatabase::GetDBNodeConnection($node_id, $bModuleInclude); if (is_object($moduleDB)) { $moduleDB->bModuleConnection = true; return $moduleDB; } //There was an connection error if ($bModuleInclude && CModule::IncludeModule('cluster')) { CClusterDBNode::SetOffline($node_id); } //TODO: unclear what to return when node went offline //in the middle of the hit. return false; } else { return $GLOBALS["DB"]; } }
function InitStep() { parent::InitStep(); $wizard =& $this->GetWizard(); $this->SetTitle(GetMessage('CLUWIZ_STEP2_TITLE')); $this->SetPrevStep("step1"); $this->SetStepID("step2"); $this->SetCancelStep("cancel"); if (count($this->GetErrors()) == 0) { $to_node_id = $wizard->GetVar('to_node_id'); if ($to_node_id < 2) { $this->nodeDB = $GLOBALS["DB"]; } else { $this->nodeDB = CDatabase::GetDBNodeConnection($to_node_id, true, false); } if (!is_object($this->nodeDB)) { $this->SetError(GetMessage('CLUWIZ_NO_CONN_ERROR')); } } }
function GetStatus($node_id, $bSlaveStatus = true, $bGlobalStatus = true, $bVariables = true) { global $DB; $arNode = CClusterDBNode::GetByID($node_id); if (!is_array($arNode)) { return false; } if ($node_id == 1) { $nodeDB = $DB; } else { ob_start(); $nodeDB = CDatabase::GetDBNodeConnection($node_id, true, false); $error = ob_get_contents(); ob_end_clean(); } if (!is_object($nodeDB)) { return false; } $arStatus = array('server_id' => null); if ($bVariables) { $rs = $nodeDB->Query("show variables like 'server_id'", false, "", array("fixed_connection" => true)); if ($ar = $rs->Fetch()) { $arStatus['server_id'] = $ar["Value"]; } } $rsSlaves = CClusterDBNode::GetList(array(), array("=MASTER_ID" => $node_id)); if ($rsSlaves->Fetch()) { $arStatus = array_merge($arStatus, array('File' => null, 'Position' => null)); if ($bSlaveStatus) { $rs = $nodeDB->Query("SHOW MASTER STATUS", true, "", array("fixed_connection" => true)); if (!$rs) { return GetMessage("CLU_NO_PRIVILEGES", array("#sql#" => "GRANT REPLICATION CLIENT on *.* to '" . $nodeDB->DBLogin . "'@'%';")); } $ar = $rs->Fetch(); if (is_array($ar)) { foreach ($ar as $key => $value) { if ($key == 'Last_Error') { $key = 'Last_SQL_Error'; } if (array_key_exists($key, $arStatus)) { $arStatus[$key] = $value; } } } } } if (strlen($arNode["MASTER_ID"])) { $arStatus = array_merge($arStatus, array('Slave_IO_State' => null, 'Slave_IO_Running' => null, 'Read_Master_Log_Pos' => null, 'Slave_SQL_Running' => null, 'Exec_Master_Log_Pos' => null, 'Seconds_Behind_Master' => null, 'Last_IO_Error' => null, 'Last_SQL_Error' => null, 'Com_select' => null)); if ($bSlaveStatus) { $rs = $nodeDB->Query("SHOW SLAVE STATUS", true, "", array("fixed_connection" => true)); if (!$rs) { return GetMessage("CLU_NO_PRIVILEGES", array("#sql#" => "GRANT REPLICATION CLIENT on *.* to '" . $nodeDB->DBLogin . "'@'%';")); } $ar = $rs->Fetch(); if (is_array($ar)) { foreach ($ar as $key => $value) { if ($key == 'Last_Error') { $key = 'Last_SQL_Error'; } if (array_key_exists($key, $arStatus)) { $arStatus[$key] = $value; } } } } if ($bGlobalStatus) { $rs = $nodeDB->Query("show global status where Variable_name in ('Com_select', 'Com_do')", true, "", array("fixed_connection" => true)); if (is_object($rs)) { while ($ar = $rs->Fetch()) { if ($ar['Variable_name'] == 'Com_do') { $arStatus['Com_select'] -= $ar['Value'] * 2; } else { $arStatus['Com_select'] += $ar['Value']; } } } else { $rs = $nodeDB->Query("show status like 'Com_select'", false, "", array("fixed_connection" => true)); $ar = $rs->Fetch(); if ($ar) { $arStatus['Com_select'] += $ar['Value']; } $rs = $nodeDB->Query("show status like 'Com_do'", false, "", array("fixed_connection" => true)); $ar = $rs->Fetch(); if ($ar) { $arStatus['Com_select'] -= $ar['Value'] * 2; } } } } return $arStatus; }
public static function BringOnline() { $rsOfflineNodes = CClusterDBNode::GetList(array(), array("=STATUS" => "OFFLINE"), array("ID")); if ($arNode = $rsOfflineNodes->Fetch()) { ob_start(); $nodeDB = CDatabase::GetDBNodeConnection($arNode["ID"], true, false); ob_end_clean(); if (is_object($nodeDB)) { CClusterDBNode::SetOnline($arNode["ID"]); } return "CClusterDBNode::BringOnline();"; } return ""; }
public function SlaveNodeForMaster($nodeDB) { global $DB; $result = array(); $arMasters = array(); $cData = new CClusterDBNode(); $rsData = $cData->GetList(array("ID" => "ASC"), array("=ROLE_ID" => array("MAIN", "MASTER"))); while ($arData = $rsData->Fetch()) { $arMasters[$arData["ID"]] = $arData; } $arMasters["v99"] = array(); //virtual connection must be alredy setup foreach ($arMasters as $node_id => $arNode) { if ($node_id == 1) { $nodeDB = $DB; } else { $nodeDB = CDatabase::GetDBNodeConnection($node_id, true); } $arMasters[$node_id]["DB"] = $nodeDB; } $auto_increment_increment = count($arMasters); $bIncIsOK = true; foreach ($arMasters as $node_id => $arNode) { $inc = $this->GetServerVariable($arNode["DB"], "auto_increment_increment"); if ($inc != $auto_increment_increment) { $bIncIsOK = false; if ($node_id == "v99") { $result[$node_id . "_auto_increment_increment"] = array("IS_OK" => CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_AUTO_INCREMENT_INCREMENT_NODE_ERR_MSG", array("#value#" => $auto_increment_increment, "#current#" => $inc)), "WIZ_REC" => GetMessage("CLU_AUTO_INCREMENT_INCREMENT_WIZREC", array("#value#" => $auto_increment_increment))); } else { $result[$node_id . "_auto_increment_increment"] = array("IS_OK" => CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_AUTO_INCREMENT_INCREMENT_ERR_MSG", array("#node_id#" => $node_id, "#value#" => $auto_increment_increment, "#current#" => $inc)), "WIZ_REC" => GetMessage("CLU_AUTO_INCREMENT_INCREMENT_WIZREC", array("#value#" => $auto_increment_increment))); } } } if ($bIncIsOK) { $result["_auto_increment_increment"] = array("IS_OK" => CClusterDBNodeCheck::OK, "MESSAGE" => GetMessage("CLU_AUTO_INCREMENT_INCREMENT_OK_MSG", array("#value#" => $auto_increment_increment)), "WIZ_REC" => ""); } $auto_increment_offset = array(); $bIncIsOK = true; foreach ($arMasters as $node_id => $arNode) { $offset = $this->GetServerVariable($arNode["DB"], "auto_increment_offset"); $mod = $offset % $auto_increment_increment; if (array_key_exists($mod, $auto_increment_offset)) { $bIncIsOK = false; if ($node_id == "v99") { $result[$node_id . "_auto_increment_offset"] = array("IS_OK" => CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_AUTO_INCREMENT_OFFSET_NODE_ERR_MSG", array("#current#" => $offset)), "WIZ_REC" => GetMessage("CLU_AUTO_INCREMENT_OFFSET_WIZREC", array("#current#" => $offset))); } else { $result[$node_id . "_auto_increment_offset"] = array("IS_OK" => CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_AUTO_INCREMENT_OFFSET_ERR_MSG", array("#node_id#" => $node_id, "#current#" => $offset)), "WIZ_REC" => GetMessage("CLU_AUTO_INCREMENT_OFFSET_WIZREC", array("#current#" => $offset))); } } else { $auto_increment_offset[$mod] = $node_id; } } if ($bIncIsOK) { $result["_auto_increment_offset"] = array("IS_OK" => CClusterDBNodeCheck::OK, "MESSAGE" => GetMessage("CLU_AUTO_INCREMENT_OFFSET_OK_MSG", array("#value#" => $auto_increment_increment)), "WIZ_REC" => ""); } $bRelayIsOK = true; foreach ($arMasters as $node_id => $arNode) { $relay_log = $this->GetServerVariable($arNode["DB"], "relay_log"); if (strlen($relay_log) <= 0) { $bIncIsOK = false; $result[$node_id . "_relay_log"] = array("IS_OK" => CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_RELAY_LOG_ERR_MSG", array("#node_id#" => $node_id, "#relay-log#" => $relay_log)), "WIZ_REC" => GetMessage("CLU_RELAY_LOG_WIZREC")); } } if ($bRelayIsOK) { $result["_relay_log"] = array("IS_OK" => CClusterDBNodeCheck::OK, "MESSAGE" => GetMessage("CLU_RELAY_LOG_OK_MSG", array("#value#" => $auto_increment_increment)), "WIZ_REC" => ""); } $log_bin = $this->GetServerVariable($nodeDB, "log_bin"); $is_ok = $log_bin === "ON"; $result["log_bin"] = array("IS_OK" => $is_ok ? CClusterDBNodeCheck::OK : CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_LOG_BIN_NODE_MSG", array("#log-bin#" => $log_bin)), "WIZ_REC" => GetMessage("CLU_LOG_BIN_WIZREC")); $skip_networking = $this->GetServerVariable($nodeDB, "skip_networking"); $is_ok = $skip_networking === "OFF"; $result["skip_networking"] = array("IS_OK" => $is_ok ? CClusterDBNodeCheck::OK : CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_SKIP_NETWORKING_NODE_MSG", array("#skip-networking#" => $skip_networking)), "WIZ_REC" => GetMessage("CLU_SKIP_NETWORKING_WIZREC")); $innodb_flush_log_at_trx_commit = $this->GetServerVariable($nodeDB, "innodb_flush_log_at_trx_commit"); $is_ok = $innodb_flush_log_at_trx_commit === '1'; $result["innodb_flush_log_at_trx_commit"] = array("IS_OK" => $is_ok ? CClusterDBNodeCheck::OK : CClusterDBNodeCheck::WARNING, "MESSAGE" => GetMessage("CLU_FLUSH_ON_COMMIT_MSG", array("#innodb_flush_log_at_trx_commit#" => $innodb_flush_log_at_trx_commit)), "WIZ_REC" => ""); $sync_binlog = $this->GetServerVariable($nodeDB, "sync_binlog"); $is_ok = $sync_binlog === '1'; $result["sync_binlog"] = array("IS_OK" => $is_ok ? CClusterDBNodeCheck::OK : CClusterDBNodeCheck::WARNING, "MESSAGE" => GetMessage("CLU_SYNC_BINLOG_MSG", array("#sync_binlog#" => $sync_binlog)), "WIZ_REC" => ""); $DatabaseName = $DB->DBName; $is_ok = false; $rsBinLogs = $nodeDB->Query("show master status", true, '', array("fixed_connection" => true)); if (!$rsBinLogs) { $result["master_status"] = array("IS_OK" => CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_MASTER_STATUS_MSG"), "WIZ_REC" => GetMessage("CLU_MASTER_STATUS_WIZREC", array("#sql#" => "GRANT REPLICATION CLIENT on *.* to 'user name'@'%';"))); } else { if ($ar = $rsBinLogs->Fetch()) { if ($ar["Binlog_Do_DB"] === $DatabaseName) { $is_ok = true; } } while ($ar = $rsBinLogs->Fetch()) { $is_ok = false; } $result["binlog_do_db"] = array("IS_OK" => $is_ok ? CClusterDBNodeCheck::OK : CClusterDBNodeCheck::ERROR, "MESSAGE" => GetMessage("CLU_SYNC_BINLOGDODB_MSG"), "WIZ_REC" => GetMessage("CLU_SYNC_BINLOGDODB_WIZREC", array("#database#" => $DatabaseName))); } return $result; }