MysqlReplicator gem is a library for processing MySQL Binlog events with MySQL Replication Protocol.
And also, this is lightweight because only depend on the Ruby standard library.
- MySQL >= 8.0
- Ruby >= 3.3
Install the gem and add to the application's Gemfile by executing:
bundle add mysql_replicatorYou can of course add a gem call in your Gemfile yourself.
gem 'mysql_replicator'If bundler is not being used to manage dependencies, install the gem by executing:
gem install mysql_replicatorRun with convenience method.
# `run` method: Connect to MySQL server, and start to handle replication event
MysqlReplicator.run(
host: 'your_mysql_host', # default localhost
port: 3307, # default 3306
user: 'username', # default root
password: 'password', # default empty string
database: 'test' # default empty string
) do |binlog_event|
# write code to process binlog event
endOr run with interface manually.
# create connection to MySQL server
conn = MysqlReplicator::Connection.new(
host: 'your_mysql_host', # default localhost
port: 3307, # default 3306
user: 'username', # default root
password: 'password', # default empty string
database: 'test' # default empty string
)
# create binlog client
client = MysqlReplicator::BinlogClient.new(conn)
# set binlog event handler
client.on do |binlog_event|
# write code to process binlog event
end
# start replication
client.start_replicationIf you run a create table and insert query.
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255),
PRIMARY KEY (id)
);
INSERT INTO users VALUES ('alice');
MysqlReplicator received binlog_event with :WRITE_ROWS event.
When INSERT query, you can get inserted row data.
puts binlog_event
# =>
{
timestamp: "2025-12-01 12:00:00",
event_type: :WRITE_ROWS,
server_id: 1,
execution: {
table_id: 10,
flags: 0,
extra_data_length: 0,
column_count: 2,
rows: [
{
ordinal_position: 1,
data_type: 'int',
column_name: 'id',
value: 1,
primary_key: true
},
{
ordinal_position: 2,
data_type: 'varchar',
column_name: 'name',
value: 'alice',
primary_key: false
}
]
}
}If you run the update query.
UPDATE users SET name = 'bob' WHERE id = 1;
MysqlReplicator received binlog_event with :UPDATE_ROWS event.
When UPDATE query, you can get row data before and after the change.
puts binlog_event
# =>
{
timestamp: "2025-12-01 12:01:00",
event_type: :UPDATE_ROWS,
server_id: 1,
execution: {
table_id: 10,
flags: 0,
extra_data_length: 0,
column_count: 2,
rows: [
{
before: [
{
ordinal_position: 1,
data_type: 'int',
column_name: 'id',
value: 1,
primary_key: true
},
{
ordinal_position: 2,
data_type: 'varchar',
column_name: 'name',
value: 'alice', # before name
primary_key: false
}
],
after: [
{
ordinal_position: 1,
data_type: 'int',
column_name: 'id',
value: 1,
primary_key: true
},
{
ordinal_position: 2,
data_type: 'varchar',
column_name: 'name',
value: 'bob', # after name
primary_key: false
}
]
}
]
}
}If you run the delete query.
DELETE FROM users WHERE id = 1;
MysqlReplicator received binlog_event with :DELETE_ROWS event.
When DELETE query, you can get row data before and after the change.
puts binlog_event
# =>
{
timestamp: "2025-12-01 12:02:00",
event_type: :DELETE_ROWS,
server_id: 1,
execution: {
table_id: 10,
flags: 0,
extra_data_length: 0,
column_count: 2,
rows: [
{
ordinal_position: 1,
data_type: 'int',
column_name: 'id',
value: 1,
primary_key: true
},
{
ordinal_position: 2,
data_type: 'varchar',
column_name: 'name',
value: 'bob',
primary_key: false
}
]
}
}If you want to use your custom logger.
# Custom logger available
MysqlReplicator.logger = your_custom_logger| Event type | |
|---|---|
| ROTATE_EVENT | ✅ |
| FORMAT_DESCRIPTION_EVENT | ✅ |
| QUERY_EVENT | ✅ |
| TABLE_MAP_EVENT | ✅ |
| WRITE_ROWS_EVENT (V2) | ✅ |
| UPDATE_ROWS_EVENT (V2) | ✅ |
| DELETE_ROWS_EVENT (V2) | ✅ |
| XID_EVENT | ✅ |
| GTID_LOG_EVENT | ❌ |
| PREVIOUS_GTIDS_LOG_EVENT | ❌ |
| HEARTBEAT_LOG_EVENT | ❌ |
| STOP_EVENT | ❌ |
| MySQL type | |
|---|---|
| TINYINT | ✅ |
| SMALLINT | ✅ |
| MEDIUMINT | ✅ |
| INT | ✅ |
| BIGINT | ✅ |
| FLOAT | ✅ |
| DOUBLE | ✅ |
| DECIMAL | ✅ |
| BIT | ❌ |
| MySQL type | |
|---|---|
| CHAR | ✅ |
| VARCHAR | ✅ |
| TINYTEXT | ✅ |
| TEXT | ✅ |
| MEDIUMTEXT | ✅ |
| LONGTEXT | ✅ |
| ENUM | ✅ |
| SET | ❌ |
| MySQL type | |
|---|---|
| BINARY | ✅ |
| VARBINARY | ✅ |
| TINYBLOB | ✅ |
| BLOB | ✅ |
| MEDIUMBLOB | ✅ |
| LONGBLOB | ✅ |
| MySQL type | |
|---|---|
| DATE | ✅ |
| TIME | ✅ |
| DATETIME | ✅ |
| TIMESTAMP | ✅ |
| YEAR | ❌ |
| MySQL type | |
|---|---|
| JSON | ✅ |
| GEOMETRY | ❌ |
| JSON value type | |
|---|---|
| SMALL_OBJECT | ✅ |
| LARGE_OBJECT | ✅ |
| SMALL_ARRAY | ✅ |
| LARGE_ARRAY | ✅ |
| LITERAL (null / true / false) | ✅ |
| INT16 | ✅ |
| UINT16 | ✅ |
| INT32 | ✅ |
| UINT32 | ✅ |
| INT64 | ✅ |
| UINT64 | ✅ |
| DOUBLE | ✅ |
| STRING | ✅ |
| OPAQUE | ❌ |
Start MySQL server.
$ docker compose up
Start MysqlReplicator to check if local code works.
irb(main):001> MysqlReplicator.run(database: 'test') { |evt| puts evt }Submit sample DDL and query to MySQL server.
Check spec/supports/sql.
Run spec for test.
$ bundle exec rspec
Run rubocop for linter.
$ bundle exec rubocop
Run steep for type check.
$ bundle exec steep check
Bug reports and pull requests are welcome on GitHub at https://github.com/waka/mysql_replicator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the MysqlReplicator project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.