supermetrics-public / php-mysql-replication
MySQL复制协议的纯PHP实现。这允许您接收如插入、更新、删除等事件及其数据和原始SQL查询。
Requires
- php: ^8.1 || ^8.2 || ^8.3
- ext-bcmath: *
- ext-json: *
- ext-sockets: *
- doctrine/collections: ^1.8
- doctrine/dbal: ^3.8
- psr/log: ^1 || ^2 || ^3
- psr/simple-cache: ^1.0
- symfony/event-dispatcher: ^6.0|^7.0
Requires (Dev)
- kubawerlos/php-cs-fixer-custom-fixers: ^3.19
- monolog/monolog: ^3.5
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.5
- symplify/easy-coding-standard: ^12.1
- dev-master
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- dev-feature/mute-logging
- dev-feature/php-support
- dev-feature/cache-interface
- dev-bugfix/php-compatibility-fix
- dev-feature/psr-simple-cache
- dev-feature/composer-config-update
- dev-feature/update-composer-config
- dev-feature/update-readme
- dev-feature/downgrade-php-req
This package is auto-updated.
Last update: 2024-09-05 10:36:53 UTC
README
MySQL复制协议的纯PHP实现。这允许您接收如插入、更新、删除等事件及其数据和原始SQL查询。
基于以下创作者的出色工作:https://github.com/noplay/python-mysql-replication 和 https://github.com/fengxiangyun/mysql-replication
安装
在您的项目中
composer require supermetrics-public/php-mysql-replication
或独立使用
git clone https://github.com/supermetrics-public/php-mysql-replication.git composer install -o
兼容性(基于集成测试)
PHP
- php 8.1
- php 8.2
- php 8.3
MYSQL
- mysql 5.5
- mysql 5.6
- mysql 5.7
- mysql 8.0(支持mysql_native_password和caching_sha2_password)
- mariadb 5.5
- mariadb 10.0
- mariadb 10.1
- 可能是基于原生MySQL的percona版本
MySQL服务器设置
在您的MySQL服务器配置文件中,您需要启用复制
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
binlog-format = row #Very important if you want to receive write, update and delete row events
MySQL复制事件解释 https://dev.mysqlserver.cn/doc/internals/en/event-meanings.html
MySQL用户权限
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'user'@'host';
GRANT SELECT ON `dbName`.* TO 'user'@'host';
配置
使用ConfigBuilder或ConfigFactory创建配置。可用选项
'user' - 您的MySQL用户(必填)
'ip'或'host' - 您的MySQL主机/IP(必填)
'password' - 您的MySQL密码(必填)
'port' - 您的MySQL主机端口号(默认3306)
'charset' - 数据库连接字符集(默认utf8)
'gtid' - 从哪个GTID标记开始(格式9b1c8d18-2a76-11e5-a26b-000c2976f3f3:1-177592)
'mariaDbGtid' - 从哪个MariaDB GTID标记开始(格式1-1-3,0-1-88)
'slaveId' - 用于识别的脚本从属id(默认: 666)(SHOW SLAVE HOSTS)
'binLogFileName' - 从哪个bin日志文件开始
'binLogPosition' - 从哪个bin日志位置开始
'eventsOnly' - 要监听的事件数组(完整列表在ConstEventType.php 文件中)
'eventsIgnore' - 要忽略的事件数组(完整列表在ConstEventType.php 文件中)
'tablesOnly' - 只监听给定表的数组(默认所有表)
'databasesOnly' - 只监听给定数据库的数组(默认所有数据库)
'tableCacheSize' - 一些数据从信息模式收集,这些数据被缓存。
'custom' - 如果某些参数必须在扩展/实现自己的类中设置
'heartbeatPeriod' - 设置复制心跳之间的秒间隔。每当主服务器的二进制日志更新为事件时,下一个心跳的等待期就会重置。间隔是一个范围在0到4294967的十进制值,分辨率为毫秒;最小非零值是0.001。只有在二进制日志文件中超过间隔的时间没有未发送的事件时,主服务器才会发送心跳。
'saveUuid' - 设置从属uuid用于识别(默认: 0015d2b6-8a06-4e5e-8c07-206ef3fbd274)
类似项目
Ruby: https://github.com/y310/kodama
Java: https://github.com/shyiko/mysql-binlog-connector-java
GO: https://github.com/siddontang/go-mysql
Python: https://github.com/noplay/python-mysql-replication
.NET: https://github.com/rusuly/MySqlCdc
示例
所有示例都在 示例目录 中
此示例将所有复制事件转储到控制台
请记得更改配置以适应您的用户、主机和密码。
用户应具有复制权限 [ REPLICATION CLIENT, SELECT]
php example/dump_events.php
用于测试 SQL 事件
CREATE DATABASE php_mysql_replication; use php_mysql_replication; CREATE TABLE test4 (id int NOT NULL AUTO_INCREMENT, data VARCHAR(255), data2 VARCHAR(255), PRIMARY KEY(id)); INSERT INTO test4 (data,data2) VALUES ("Hello", "World"); UPDATE test4 SET data = "World", data2="Hello" WHERE id = 1; DELETE FROM test4 WHERE id = 1;
输出将类似于这个(取决于示例配置,例如 GTID 开/关)
=== Event format description ===
Date: 2017-07-06T13:31:11+00:00
Log position: 0
Event size: 116
Memory usage 2.4 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803092
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13675
Memory usage 2.42 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803237
Event size: 145
Database: php_mysql_replication
Execution time: 0
Query: CREATE DATABASE php_mysql_replication
Memory usage 2.45 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803285
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13676
Memory usage 2.45 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803500
Event size: 215
Database: php_mysql_replication
Execution time: 0
Query: CREATE TABLE test4 (id int NOT NULL AUTO_INCREMENT, data VARCHAR(255), data2 VARCHAR(255), PRIMARY KEY(id))
Memory usage 2.45 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803548
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13677
Memory usage 2.45 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803637
Event size: 89
Database: php_mysql_replication
Execution time: 0
Query: BEGIN
Memory usage 2.45 MB
=== Event tableMap ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803708
Event size: 71
Table: test4
Database: php_mysql_replication
Table Id: 866
Columns amount: 3
Memory usage 2.71 MB
=== Event write ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803762
Event size: 54
Table: test4
Affected columns: 3
Changed rows: 1
Values: Array
(
[0] => Array
(
[id] => 1
[data] => Hello
[data2] => World
)
)
Memory usage 2.74 MB
=== Event xid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803793
Event size: 31
Transaction ID: 662802
Memory usage 2.75 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803841
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13678
Memory usage 2.75 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803930
Event size: 89
Database: php_mysql_replication
Execution time: 0
Query: BEGIN
Memory usage 2.76 MB
=== Event tableMap ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804001
Event size: 71
Table: test4
Database: php_mysql_replication
Table Id: 866
Columns amount: 3
Memory usage 2.75 MB
=== Event update ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804075
Event size: 74
Table: test4
Affected columns: 3
Changed rows: 1
Values: Array
(
[0] => Array
(
[before] => Array
(
[id] => 1
[data] => Hello
[data2] => World
)
[after] => Array
(
[id] => 1
[data] => World
[data2] => Hello
)
)
)
Memory usage 2.76 MB
=== Event xid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804106
Event size: 31
Transaction ID: 662803
Memory usage 2.76 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804154
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13679
Memory usage 2.76 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804243
Event size: 89
Database: php_mysql_replication
Execution time: 0
Query: BEGIN
Memory usage 2.76 MB
=== Event tableMap ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804314
Event size: 71
Table: test4
Database: php_mysql_replication
Table Id: 866
Columns amount: 3
Memory usage 2.76 MB
=== Event delete ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804368
Event size: 54
Table: test4
Affected columns: 3
Changed rows: 1
Values: Array
(
[0] => Array
(
[id] => 1
[data] => World
[data2] => Hello
)
)
Memory usage 2.77 MB
=== Event xid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804399
Event size: 31
Transaction ID: 662804
Memory usage 2.77 MB
基准测试
在虚拟机上测试
Debian 8.7
PHP 5.6.30
Percona 5.6.35
inxi
CPU(s)~4 Single core Intel Core i5-2500Ks (-SMP-) clocked at 5901 Mhz Kernel~3.16.0-4-amd64 x86_64 Up~1 day Mem~1340.3/1996.9MB HDD~41.9GB(27.7% used) Procs~122 Client~Shell inxi~2.1.28
php example/benchmark.php
Start insert data
7442 event by seconds (1000 total)
7679 event by seconds (2000 total)
7914 event by seconds (3000 total)
7904 event by seconds (4000 total)
7965 event by seconds (5000 total)
8006 event by seconds (6000 total)
8048 event by seconds (7000 total)
8038 event by seconds (8000 total)
8040 event by seconds (9000 total)
8055 event by seconds (10000 total)
8058 event by seconds (11000 total)
8071 event by seconds (12000 total)
常见问题解答
首先,MYSQL 不提供异步调用。通常您需要在自己的应用程序中编程此操作(通过事件分派并向某个队列系统添加,如果您的数据库有多个入口点,如 Web、后端或其他微服务,那么向所有这些添加处理并不总是便宜的。但使用 MYSQL 复制协议,您可以监听写事件,并异步处理它们(最佳组合是将项目添加到某个队列系统,如 rabbitmq、redis 或 kafka)。此外,在无效化缓存、搜索引擎复制、实时分析和审计方面。
首先,您需要知道,可能会通过许多事件,例如,如果您在 "bar" 表中更新 1 000 000 条记录,并且您需要从 "foo" 表中获取这个插入,那么所有这些都必须由脚本处理,并且您需要等待数据。这是正常的,这就是它的工作方式。您可以使用 配置选项 来加速。此外,如果脚本崩溃,您需要不时地将 binlog(或 gtid)的位置保存下来,以便在再次运行此脚本时从该位置开始,以避免重复。
如我在第 1 点中提到的,使用队列系统,如 rabbitmq、redis 或 kafka,它们将使您能够通过多个脚本处理数据。
创建一个 问题 我会尽量在业余时间解决这个问题 :)
它像任何其他 MYSQL 从属模式一样工作,并且带来了相同的工作量。
要解决这个问题,最好是增加数据库配置 net_read_timeout
和 net_write_timeout
到 3600。(感谢 Bijimon)
在 my.conf 中设置 binlog_row_image=full
以修复只接收部分更新的问题。
在 my.conf 中设置 log_slave_updates=on
以修复此问题 (#71)(#66)
默认 MYSQL 设置生成一个大的流块,这需要更多的 RAM/CPU,您可以使用变量 binlog_row_event_max_size
[ https://dev.mysqlserver.cn/doc/refman/8.0/en/replication-options-binary-log.html#sysvar_binlog_row_event_max_size ] 来将其拆分为更小的块