Пример #1
0
 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
         }
     }
 }
Пример #2
0
 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;
 }
Пример #3
0
 /**
  * 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"];
     }
 }