Replication.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. /**
  3. * Replication helpers
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin;
  7. use function explode;
  8. use function mb_strtoupper;
  9. /**
  10. * PhpMyAdmin\Replication class
  11. */
  12. class Replication
  13. {
  14. /**
  15. * Extracts database or table name from string
  16. *
  17. * @param string $string contains "dbname.tablename"
  18. * @param string $what what to extract (db|table)
  19. *
  20. * @return string the extracted part
  21. */
  22. public function extractDbOrTable($string, $what = 'db')
  23. {
  24. $list = explode('.', $string);
  25. if ($what === 'db') {
  26. return $list[0];
  27. }
  28. return $list[1];
  29. }
  30. /**
  31. * Configures replication slave
  32. *
  33. * @param string $action possible values: START or STOP
  34. * @param string|null $control default: null,
  35. * possible values: SQL_THREAD or IO_THREAD or null.
  36. * If it is set to null, it controls both
  37. * SQL_THREAD and IO_THREAD
  38. * @param int $link mysql link
  39. *
  40. * @return mixed|int output of DatabaseInterface::tryQuery
  41. */
  42. public function slaveControl(string $action, ?string $control, int $link)
  43. {
  44. global $dbi;
  45. $action = mb_strtoupper($action);
  46. $control = $control !== null ? mb_strtoupper($control) : '';
  47. if ($action !== 'START' && $action !== 'STOP') {
  48. return -1;
  49. }
  50. if ($control !== 'SQL_THREAD' && $control !== 'IO_THREAD' && $control != null) {
  51. return -1;
  52. }
  53. return $dbi->tryQuery($action . ' SLAVE ' . $control . ';', $link);
  54. }
  55. /**
  56. * Changes master for replication slave
  57. *
  58. * @param string $user replication user on master
  59. * @param string $password password for the user
  60. * @param string $host master's hostname or IP
  61. * @param int $port port, where mysql is running
  62. * @param array $pos position of mysql replication,
  63. * array should contain fields File and Position
  64. * @param bool $stop shall we stop slave?
  65. * @param bool $start shall we start slave?
  66. * @param int $link mysql link
  67. *
  68. * @return string output of CHANGE MASTER mysql command
  69. */
  70. public function slaveChangeMaster(
  71. $user,
  72. $password,
  73. $host,
  74. $port,
  75. array $pos,
  76. bool $stop,
  77. bool $start,
  78. int $link
  79. ) {
  80. global $dbi;
  81. if ($stop) {
  82. $this->slaveControl('STOP', null, $link);
  83. }
  84. $out = $dbi->tryQuery(
  85. 'CHANGE MASTER TO ' .
  86. 'MASTER_HOST=\'' . $host . '\',' .
  87. 'MASTER_PORT=' . ($port * 1) . ',' .
  88. 'MASTER_USER=\'' . $user . '\',' .
  89. 'MASTER_PASSWORD=\'' . $password . '\',' .
  90. 'MASTER_LOG_FILE=\'' . $pos['File'] . '\',' .
  91. 'MASTER_LOG_POS=' . $pos['Position'] . ';',
  92. $link
  93. );
  94. if ($start) {
  95. $this->slaveControl('START', null, $link);
  96. }
  97. return $out;
  98. }
  99. /**
  100. * This function provides connection to remote mysql server
  101. *
  102. * @param string $user mysql username
  103. * @param string $password password for the user
  104. * @param string $host mysql server's hostname or IP
  105. * @param int $port mysql remote port
  106. * @param string $socket path to unix socket
  107. *
  108. * @return mixed mysql link on success
  109. */
  110. public function connectToMaster(
  111. $user,
  112. $password,
  113. $host = null,
  114. $port = null,
  115. $socket = null
  116. ) {
  117. global $dbi;
  118. $server = [];
  119. $server['user'] = $user;
  120. $server['password'] = $password;
  121. $server['host'] = Core::sanitizeMySQLHost($host);
  122. $server['port'] = $port;
  123. $server['socket'] = $socket;
  124. // 5th parameter set to true means that it's an auxiliary connection
  125. // and we must not go back to login page if it fails
  126. return $dbi->connect(DatabaseInterface::CONNECT_AUXILIARY, $server);
  127. }
  128. /**
  129. * Fetches position and file of current binary log on master
  130. *
  131. * @param int $link mysql link
  132. *
  133. * @return array an array containing File and Position in MySQL replication
  134. * on master server, useful for slaveChangeMaster()
  135. *
  136. * @phpstan-return array{'File'?: string, 'Position'?: string}
  137. */
  138. public function slaveBinLogMaster(int $link): array
  139. {
  140. global $dbi;
  141. $data = $dbi->fetchResult('SHOW MASTER STATUS', null, null, $link);
  142. $output = [];
  143. if (! empty($data)) {
  144. $output['File'] = $data[0]['File'];
  145. $output['Position'] = $data[0]['Position'];
  146. }
  147. return $output;
  148. }
  149. }