yerofey/replicator

此软件包已被放弃,不再维护。未建议替代包。

PHP MySQL 复制

资助软件包维护!
Patreon

0.1.4 2020-04-04 00:00 UTC

This package is auto-updated.

Last update: 2023-08-17 19:02:28 UTC


README


Replicator

功能

  • 复制表列
  • 复制表索引
  • 复制表数据
  • 复制表校对

为什么不用默认的内置复制方法

默认复制有一些弱点

  • 它创建了一个大型的 binlog 文件(如果你有一个大数据库)——因此你需要大量的磁盘空间来处理这些 binlog
  • 它不支持触发器——触发器将被保存为 binlog 中的 SQL 查询,但如果你只想复制几个表——一些数据将会不正确。

如何设置

首先,你需要一个 Composer

如果你还没有安装它,请查看此指南

然后,将库添加到你的项目中

composer require yerofey/replicator

如果你想在同一服务器上复制

  1. 你可以创建一个工作进程,该进程将每分钟执行一次任务(examples/worker.php)。它可以与 crontab 配置。
  2. 你可以创建一个守护进程,该守护进程始终运行,并每 n 秒执行一次任务(examples/daemon.php)

如果你想在另一台服务器上复制

在辅助服务器(Linux)上

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

导航到以 bind-address 指令开始的行。默认情况下,此值设置为 127.0.0.1,这意味着服务器将仅查找本地连接。你需要将此指令更改为引用外部 IP 地址。为了故障排除的目的,你可以将此指令设置为通配符 IP 地址,例如 *, :: 或 0.0.0.0

bind-address            = 0.0.0.0

更改此行后,保存并关闭文件(如果您使用 nano 编辑,请按 CTRL + X,Y,然后按 ENTER)。

假设您已在数据库服务器上配置了防火墙,您还需要打开端口 3306——MySQL 的默认端口——以允许流量进入 MySQL。如果您仅计划从一台特定的机器访问数据库服务器,您可以使用以下命令授予该机器远程连接数据库的专用权限。请确保将 remote_IP_address 替换为您计划连接的机器的实际 IP 地址

sudo ufw allow from REMOTE_IP_ADDRESS to any port 3306

或者,您可以使用以下命令允许来自任何 IP 地址的连接到您的 MySQL 数据库

sudo ufw allow 3306

最后,重新启动 MySQL 服务以使您对 mysqld.cnf 所做的更改生效

sudo systemctl restart mysql

MySQL 安装指南来源: https://www.digitalocean.com/community/tutorials/how-to-allow-remote-access-to-mysql

然后创建一个用于工作脚本的文件夹

mkdir db-replicator
cd db-replicator

然后创建数据库配置文件

touch config.php

config.php 示例

<?php

require __DIR__ . '/vendor/autoload.php';

// load variables from ".env" file
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

if (!isset($_ENV['DB_REPLICATION_IS_ENABLED']) || $_ENV['DB_REPLICATION_IS_ENABLED'] == false) {
  exit();
}

$config_db_map = [
  'primary' => [
    'hostname' => $_ENV['DB_PRIMARY_HOST'],
    'database' => $_ENV['DB_PRIMARY_NAME'],
    'username' => $_ENV['DB_PRIMARY_USER'],
    'password' => $_ENV['DB_PRIMARY_PASS'],
  ],
  'secondary' => [
    'hostname' => $_ENV['DB_SECONDARY_HOST'],
    'database' => $_ENV['DB_SECONDARY_NAME'],
    'username' => $_ENV['DB_SECONDARY_USER'],
    'password' => $_ENV['DB_SECONDARY_PASS'],
  ],
];

然后创建一个工作脚本(一次性任务)

<?php

// one-time worker replication script

ini_set('memory_limit', '256M');
set_time_limit(300);

// your app root location
$app_dir = __DIR__ . '/..';

// log actions in "/replicator_log.txt"
$debug = true;
$log_file = $app_dir . '/replicator_log.txt';

// master table config key from "config.php"
$primary_db_key = 'primary';
// slave table config key from "config.php"
$secondary_db_key = 'secondary';

// specifed tables to watch OR use "*" to watch for all tables
$watch_tables = [
  'test_table',
];

// load Composer
require $app_dir . '/vendor/autoload.php';
// load DB config map
require __DIR__ . '/config.php';

use Yerofey\Replicator\Replicator;
use Yerofey\Replicator\ReplicatorException;
use Yerofey\Replicator\ReplicatorHelper;

if (!isset($config_db_map)) {
  exit();
}

// init helper
$helper = new ReplicatorHelper();

// init DB connections
try {
  $connections = [
    'primary'   => $helper->createConnection($config_db_map[$primary_db_key] ?? []),
    'secondary' => $helper->createConnection($config_db_map[$secondary_db_key] ?? []),
  ];
} catch (ReplicatorException $e) {
  exit($e->getMessage() . PHP_EOL);
}

// init Replicator
$replicator = new Replicator(
  $connections,
  $helper,
  $debug,
  $log_file
);

// run Replicator
try {
  $replicator->run($watch_tables);
} catch (ReplicatorException $e) {
  $replicator->saveLog($e->getMessage());
}

或者创建一个持续运行的后台进程

<?php

// daemon worker replication script

ini_set('memory_limit', '256M');
set_time_limit(0);

// your app root location
$app_dir = __DIR__ . '/..';

// log actions in "/replicator_log.txt"
$debug = true;
$log_file = $app_dir . '/replicator_log.txt';

// master table config key from "config.php"
$primary_db_key = 'primary';
// slave table config key from "config.php"
$secondary_db_key = 'secondary';

// specifed tables to watch OR use "*" to watch for all tables
$watch_tables = [
  'test_table',
];

// watch interval (sec)
$interval_seconds = 10;

// load Composer
require $app_dir . '/vendor/autoload.php';
// load DB config map
require __DIR__ . '/config.php';

use Yerofey\Replicator\Replicator;
use Yerofey\Replicator\ReplicatorException;
use Yerofey\Replicator\ReplicatorHelper;

if (!isset($config_db_map)) {
  exit();
}

// init helper
$helper = new ReplicatorHelper();

// init DB connections
try {
  $connections = [
    'primary'   => $helper->createConnection($config_db_map[$primary_db_key] ?? []),
    'secondary' => $helper->createConnection($config_db_map[$secondary_db_key] ?? []),
  ];
} catch (ReplicatorException $e) {
  exit($e->getMessage() . PHP_EOL);
}

// init Replicator
$replicator = new Replicator(
  $connections,
  $helper,
  $debug,
  $log_file
);

// run Replicator
while (true) {
  $time_start = microtime(true);

  try {
    $replicator->run($watch_tables);
  } catch (ReplicatorException $e) {
    $replicator->saveLog($e->getMessage());
  }

  $sleep = 0;
  $runtime = microtime(true) - $time_start;
  if ($runtime < $interval_seconds) {
    $sleep = $interval_seconds - $runtime;
  }

  sleep($sleep);
}

然后只需运行您的脚本

如果您一切都做对了,复制现在应该可以工作了。

作者

耶罗费·S.

许可证

本库根据 MIT 许可。