Advertisement
Guest User

Untitled

a guest
Apr 26th, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.53 KB | None | 0 0
  1. <?php
  2. class mysqlFailOver {
  3.     private $numServers = 0;
  4.     private $servers = array();
  5.     private $currentServer = array();
  6.     private $iCurrentServer = 0;
  7.     private $newReplicationChain = array();
  8.     function __construct($svrs) {
  9.         if ($newChain)
  10.             $this->BuildChain($svrs);
  11.         if (!is_array($svrs)) {
  12.             die("Failover Failure: Non array object passed to constructor.");
  13.         }
  14.         $this->numServers = count($svrs);
  15.         $this->servers    = $svrs;
  16.         if ($this->queryTest()) {
  17.             $this->rebuildReplicationChain();
  18.         }
  19.         return $this->link;
  20.     }
  21.     private function queryTest() {
  22.         $this->link = @mysqli_connect($this->servers[$this->iCurrentServer]['hostname'], $this->servers[$this->iCurrentServer]['username'], $this->servers[$this->iCurrentServer]['password'], $this->servers[$this->iCurrentServer]['database']);
  23.         $result     = @mysqli_query("SELECT 1 FROM DUAL", $this->link);
  24.         if (!$result) {
  25.             switch (mysqli_errno($this->link)) {
  26.                 case 2002:
  27.                 case 2003:
  28.                 case 2005:
  29.                     $this->servers[$this->iCurrentServer]['connection_error'] = true;
  30.                     if ($this->iCurrentServer == 0)
  31.                         $this->servers[$this->iCurrentServer]['was_master'] = true;
  32.                     $this->iCurrentServer++;
  33.                     if ($this->iCurrentServer < $this->numServers) {
  34.                         $this->queryTest();
  35.                     }
  36.                     break;
  37.                 default:
  38.                     die("Failover Failure: " . mysqli_error($this->link) . " is not a failover event.");
  39.             }
  40.         } else {
  41.             return true;
  42.         }
  43.     }
  44.     private function rebuildReplicationChain() {
  45.         $lastReplicationChain = $this->getLastReplicationChain();
  46.         $offlineNodes         = array();
  47.         $onlineNodes          = array();
  48.         foreach ($this->servers as $s) {
  49.             if ($s['connection_error']) {
  50.                 $offlineNodes[$s['hostname']] = $s;
  51.             } else {
  52.                 $onlineNodes[$s['hostname']] = $s;
  53.             }
  54.         }
  55.         foreach ($lastReplicationChain as $node) {
  56.             foreach ($onlineNodes as $replacement) {
  57.                 if ($replacement['hostname'] == $node['hostname']) {
  58.                     $newReplicationChain[] = $replacement;
  59.                 }
  60.             }
  61.         }
  62.         foreach ($lastReplicationChain as $node) {
  63.             foreach ($offlineNodes as $downedNode) {
  64.                 if ($downedNode['hostname'] == $node['hostname']) {
  65.                     $newReplicationChain[] = $downedNode;
  66.                 }
  67.             }
  68.         }
  69.         $this->newReplicationChain = $newReplicationChain;
  70.         $this->updateChainRole();
  71.     }
  72.     private function getLastReplicationChain() {
  73.         $lastReplicationChainQuery = mysqli_query("SELECT * FROM `mysql_replication_chain` ORDER BY `position` ASC", $this->link);
  74.         while ($chainData = mysqli_fetch_assoc($lastReplicationChainQuery)) {
  75.             $lastReplicationChain[] = $chainData;
  76.         }
  77.         return $lastReplicationChain;
  78.     }
  79.     private function updateChainRole($host, $position) {
  80.         $this->syncSlaves();
  81.         foreach ($this->newReplicationChain as $position => $node) {
  82.             mysqli_query("UPDATE `mysql_replication_chain` SET `position` = '" . $position . "' WHERE `hostname` = '" . $node['hostname'] . "'", $this->link);
  83.         }
  84.     }
  85.     private function syncSlaves() {
  86.         foreach ($this->newReplicationChain as $node) {
  87.             $nodeLink = @mysqli_connect($node['hostname'], $node['username'], $node['password'], $node['database']);
  88.             if ($nodeLink) {
  89.                 mysqli_query("STOP SLAVE IO_THREAD");
  90.                 $synced = false;
  91.                 while ($synced == false) {
  92.                     $result = mysqli_query("SHOW PROCESSLIST", $nodeLink);
  93.                     while ($process == mysqli_fetch_assoc($result)) {
  94.                         if (strstr($process['State'], 'Slave has read all relay log')) {
  95.                             $synced = true;
  96.                             break;
  97.                         }
  98.                     }
  99.                 }
  100.             } else {
  101.                 // TODO: Add more logic to rebuild chain recursivly if there are multiple failures.
  102.             }
  103.         }
  104.         //Set the next slave in line to master STOP SLAVE
  105.         $master   = $this->newReplicationChain[0];
  106.         $nodeLink = @mysqli_connect($master['hostname'], $master['username'], $master['password'], $master['database']);
  107.         mysqli_query("STOP SLAVE", $nodeLink);
  108.         mysqli_query("RESET MASTER", $nodeLink);
  109.         mysqli_close($nodeLink);
  110.         $changeMasterSQL = "CHANGE MASTER TO MASTER_HOST='" . $master['hostname'] . "',    MASTER_USER='" . $master['username'] . "', MASTER_PASSWORD='" . $master['password'] . "'";
  111.         for ($i = 0; $i < count($this->newReplicationChain); $i++) {
  112.             if (!isset($this->newReplicationChain[$i]['connection_error'])) {
  113.                 $slave     = $this->newReplicationChain[$i];
  114.                 $slaveLink = @mysqli_connect($slave['hostname'], $slave['username'], $slave['password'], $slave['database']);
  115.                 mysqli_query("STOP SLAVE", $slaveLink);
  116.                 mysqli_query($changeMasterSQL, $slaveLink);
  117.                 mysqli_query("START SLAVE", $slaveLink);
  118.                 mysqli_close($slaveLink);
  119.             }
  120.         }
  121.     }
  122. }
  123. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement