Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- class mysqlFailOver {
- private $numServers = 0;
- private $servers = array();
- private $currentServer = array();
- private $iCurrentServer = 0;
- private $newReplicationChain = array();
- function __construct($svrs) {
- if ($newChain)
- $this->BuildChain($svrs);
- if (!is_array($svrs)) {
- die("Failover Failure: Non array object passed to constructor.");
- }
- $this->numServers = count($svrs);
- $this->servers = $svrs;
- if ($this->queryTest()) {
- $this->rebuildReplicationChain();
- }
- return $this->link;
- }
- private function queryTest() {
- $this->link = @mysqli_connect($this->servers[$this->iCurrentServer]['hostname'], $this->servers[$this->iCurrentServer]['username'], $this->servers[$this->iCurrentServer]['password'], $this->servers[$this->iCurrentServer]['database']);
- $result = @mysqli_query("SELECT 1 FROM DUAL", $this->link);
- if (!$result) {
- switch (mysqli_errno($this->link)) {
- case 2002:
- case 2003:
- case 2005:
- $this->servers[$this->iCurrentServer]['connection_error'] = true;
- if ($this->iCurrentServer == 0)
- $this->servers[$this->iCurrentServer]['was_master'] = true;
- $this->iCurrentServer++;
- if ($this->iCurrentServer < $this->numServers) {
- $this->queryTest();
- }
- break;
- default:
- die("Failover Failure: " . mysqli_error($this->link) . " is not a failover event.");
- }
- } else {
- return true;
- }
- }
- private function rebuildReplicationChain() {
- $lastReplicationChain = $this->getLastReplicationChain();
- $offlineNodes = array();
- $onlineNodes = array();
- foreach ($this->servers as $s) {
- if ($s['connection_error']) {
- $offlineNodes[$s['hostname']] = $s;
- } else {
- $onlineNodes[$s['hostname']] = $s;
- }
- }
- foreach ($lastReplicationChain as $node) {
- foreach ($onlineNodes as $replacement) {
- if ($replacement['hostname'] == $node['hostname']) {
- $newReplicationChain[] = $replacement;
- }
- }
- }
- foreach ($lastReplicationChain as $node) {
- foreach ($offlineNodes as $downedNode) {
- if ($downedNode['hostname'] == $node['hostname']) {
- $newReplicationChain[] = $downedNode;
- }
- }
- }
- $this->newReplicationChain = $newReplicationChain;
- $this->updateChainRole();
- }
- private function getLastReplicationChain() {
- $lastReplicationChainQuery = mysqli_query("SELECT * FROM `mysql_replication_chain` ORDER BY `position` ASC", $this->link);
- while ($chainData = mysqli_fetch_assoc($lastReplicationChainQuery)) {
- $lastReplicationChain[] = $chainData;
- }
- return $lastReplicationChain;
- }
- private function updateChainRole($host, $position) {
- $this->syncSlaves();
- foreach ($this->newReplicationChain as $position => $node) {
- mysqli_query("UPDATE `mysql_replication_chain` SET `position` = '" . $position . "' WHERE `hostname` = '" . $node['hostname'] . "'", $this->link);
- }
- }
- private function syncSlaves() {
- foreach ($this->newReplicationChain as $node) {
- $nodeLink = @mysqli_connect($node['hostname'], $node['username'], $node['password'], $node['database']);
- if ($nodeLink) {
- mysqli_query("STOP SLAVE IO_THREAD");
- $synced = false;
- while ($synced == false) {
- $result = mysqli_query("SHOW PROCESSLIST", $nodeLink);
- while ($process == mysqli_fetch_assoc($result)) {
- if (strstr($process['State'], 'Slave has read all relay log')) {
- $synced = true;
- break;
- }
- }
- }
- } else {
- // TODO: Add more logic to rebuild chain recursivly if there are multiple failures.
- }
- }
- //Set the next slave in line to master STOP SLAVE
- $master = $this->newReplicationChain[0];
- $nodeLink = @mysqli_connect($master['hostname'], $master['username'], $master['password'], $master['database']);
- mysqli_query("STOP SLAVE", $nodeLink);
- mysqli_query("RESET MASTER", $nodeLink);
- mysqli_close($nodeLink);
- $changeMasterSQL = "CHANGE MASTER TO MASTER_HOST='" . $master['hostname'] . "', MASTER_USER='" . $master['username'] . "', MASTER_PASSWORD='" . $master['password'] . "'";
- for ($i = 0; $i < count($this->newReplicationChain); $i++) {
- if (!isset($this->newReplicationChain[$i]['connection_error'])) {
- $slave = $this->newReplicationChain[$i];
- $slaveLink = @mysqli_connect($slave['hostname'], $slave['username'], $slave['password'], $slave['database']);
- mysqli_query("STOP SLAVE", $slaveLink);
- mysqli_query($changeMasterSQL, $slaveLink);
- mysqli_query("START SLAVE", $slaveLink);
- mysqli_close($slaveLink);
- }
- }
- }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement