Skip to content

Commit c997c3b

Browse files
authored
Fixed MariaDB collation error (#26)
1 parent d5fa119 commit c997c3b

File tree

8 files changed

+96
-10
lines changed

8 files changed

+96
-10
lines changed

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,21 @@ For realtime data sync from MySQL to ClickHouse:
4949
# ... other settings ...
5050
gtid_mode = on
5151
enforce_gtid_consistency = 1
52-
default_authentication_plugin = mysql_native_password
52+
binlog_expire_logs_seconds = 864000
53+
max_binlog_size = 500M
54+
binlog_format = ROW
55+
```
56+
- For MariaDB use following settings:
57+
```ini
58+
[mysqld]
59+
# ... other settings ...
60+
gtid_strict_mode = ON
61+
gtid_domain_id = 0
62+
server_id = 1
63+
log_bin = /var/log/mysql/mysql-bin.log
64+
binlog_expire_logs_seconds = 864000
65+
max_binlog_size = 500M
5366
binlog_format = ROW
54-
5567
```
5668

5769
For `AWS RDS` you need to set following settings in `Parameter groups`:

docker-compose-tests.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ services:
3131
volumes:
3232
- ./test_mysql.cnf:/etc/my.cnf:ro
3333

34+
mariadb_db:
35+
image: mariadb:11.5.2
36+
environment:
37+
- MARIADB_DATABASE=admin
38+
- MARIADB_ROOT_HOST=%
39+
- MARIADB_ROOT_PASSWORD=admin
40+
networks:
41+
default:
42+
ports:
43+
- 9307:3306
44+
volumes:
45+
- ./test_mariadb.cnf:/etc/mysql/my.cnf:ro # Adjust path to MariaDB config location if needed
46+
3447
replicator:
3548
image: python:3.12.4-slim-bookworm
3649
command: bash -c "pip install -r /app/requirements.txt && pip install -r /app/requirements-dev.txt && touch /tmp/ready && tail -f /dev/null"

mysql_ch_replicator/binlog_replicator.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,6 @@ def run(self):
411411
if type(event) not in (DeleteRowsEvent, UpdateRowsEvent, WriteRowsEvent, QueryEvent):
412412
continue
413413

414-
assert event.packet.log_pos == self.stream.log_pos
415-
416414
log_event = LogEvent()
417415
if hasattr(event, 'table'):
418416
log_event.table_name = event.table

mysql_ch_replicator/mysql_api.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,21 @@ def reconnect_if_required(self):
2121
curr_time = time.time()
2222
if curr_time - self.last_connect_time < MySQLApi.RECONNECT_INTERVAL:
2323
return
24-
#print('(re)connecting to mysql')
25-
self.db = mysql.connector.connect(
24+
conn_settings = dict(
2625
host=self.mysql_settings.host,
2726
port=self.mysql_settings.port,
2827
user=self.mysql_settings.user,
2928
passwd=self.mysql_settings.password,
3029
)
30+
try:
31+
self.db = mysql.connector.connect(**conn_settings)
32+
except mysql.connector.errors.DatabaseError as e:
33+
if 'Unknown collation' in str(e):
34+
conn_settings['charset'] = 'utf8mb4'
35+
conn_settings['collation'] = 'utf8mb4_general_ci'
36+
self.db = mysql.connector.connect(**conn_settings)
37+
else:
38+
raise
3139
self.cursor = self.db.cursor()
3240
if self.database is not None:
3341
self.cursor.execute(f'USE {self.database}')

test_mariadb.cnf

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[client]
2+
default-character-set = utf8mb4
3+
4+
[mysql]
5+
default-character-set = utf8mb4
6+
7+
[mysqld]
8+
# The defaults from /etc/my.cnf
9+
user = mysql
10+
11+
# Custom settings
12+
collation-server = utf8mb4_unicode_ci # Changed to a collation supported by MariaDB
13+
character-set-server = utf8mb4
14+
default_authentication_plugin = mysql_native_password
15+
init_connect = 'SET NAMES utf8mb4'
16+
skip-host-cache
17+
skip-name-resolve
18+
# information_schema_stats_expiry is not available in MariaDB and has been removed.
19+
20+
# Replication settings for MariaDB
21+
gtid_strict_mode = ON
22+
gtid_domain_id = 0
23+
server_id = 1
24+
log_bin = /var/log/mysql/mysql-bin.log
25+
binlog_expire_logs_seconds = 864000
26+
max_binlog_size = 500M
27+
binlog_format = ROW

test_mysql.cnf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ information_schema_stats_expiry = 0
2424
# replication
2525
gtid_mode = on
2626
enforce_gtid_consistency = 1
27+
binlog_expire_logs_seconds = 864000
28+
max_binlog_size = 500M
29+
binlog_format = ROW #Very important if you want to receive write, update and delete row events

test_mysql_ch_replicator.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44
import subprocess
55
import json
6+
import pytest
67

78
from mysql_ch_replicator import config
89
from mysql_ch_replicator import mysql_api
@@ -14,6 +15,7 @@
1415

1516

1617
CONFIG_FILE = 'tests_config.yaml'
18+
CONFIG_FILE_MARIADB = 'tests_config_mariadb.yaml'
1719
TEST_DB_NAME = 'replication_test_db'
1820
TEST_TABLE_NAME = 'test_table'
1921
TEST_TABLE_NAME_2 = 'test_table_2'
@@ -70,9 +72,13 @@ def prepare_env(
7072
assert_wait(lambda: db_name not in ch.get_databases())
7173

7274

73-
def test_e2e_regular():
75+
@pytest.mark.parametrize('config_file', [
76+
CONFIG_FILE,
77+
CONFIG_FILE_MARIADB,
78+
])
79+
def test_e2e_regular(config_file):
7480
cfg = config.Settings()
75-
cfg.load(CONFIG_FILE)
81+
cfg.load(config_file)
7682

7783
mysql = mysql_api.MySQLApi(
7884
database=None,
@@ -103,9 +109,9 @@ def test_e2e_regular():
103109
)
104110
mysql.execute(f"INSERT INTO {TEST_TABLE_NAME} (name, age) VALUES ('Peter', 33);", commit=True)
105111

106-
binlog_replicator_runner = BinlogReplicatorRunner()
112+
binlog_replicator_runner = BinlogReplicatorRunner(cfg_file=config_file)
107113
binlog_replicator_runner.run()
108-
db_replicator_runner = DbReplicatorRunner(TEST_DB_NAME)
114+
db_replicator_runner = DbReplicatorRunner(TEST_DB_NAME, cfg_file=config_file)
109115
db_replicator_runner.run()
110116

111117
assert_wait(lambda: TEST_DB_NAME in ch.get_databases())

tests_config_mariadb.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
mysql:
3+
host: 'localhost'
4+
port: 9307
5+
user: 'root'
6+
password: 'admin'
7+
8+
clickhouse:
9+
host: 'localhost'
10+
port: 9123
11+
user: 'default'
12+
password: 'admin'
13+
14+
binlog_replicator:
15+
data_dir: '/app/binlog/'
16+
records_per_file: 100000
17+
18+
databases: '*test*'
19+
log_level: 'debug'

0 commit comments

Comments
 (0)