python-mysql-replication-kr / python-mysql-replication Goto Github PK
View Code? Open in Web Editor NEWThis project forked from julien-duponchelle/python-mysql-replication
MySQL Replication Protocol Client in Python
This project forked from julien-duponchelle/python-mysql-replication
MySQL Replication Protocol Client in Python
This PR updates GitHub Actions to use the latest versions of actions/checkout and actions/setup-python in preparation for the end-of-life of Node 16 in September 2023.
The default runtime of Node 16 will reach its end-of-life on 11 Sep 2023. To adapt to this change and benefit from the features and optimizations in the newer GitHub Actions versions
Updates GitHub Actions Versions:
From actions/checkout@v2 to actions/checkout@v4
From actions/setup-python@v2 to actions/setup-python@v4
Mypy?
https://dev.mysql.com/doc/dev/mysql-server/latest/classbinary__log_1_1Table__map__event.html
의 optional metadata를 구현합니다.
컬럼명, pk 등의 데이터 포함하고 있는 필드이며, Master에서 2개 system variable에 대한 세팅을 후에 데이터를 받아올 수 있습니다.
3조에서 초기 구현 끝나셨고 테스트 코드 작성 중이십니다.
https://readthedocs.org/projects/python-mysql-replication/builds/
Latest Build is 4 Years Old
본 라이브러리의 사용자가 활용할 수 있는 어떠한 로그도 제공되고 있지 않습니다.
다음의 예시처럼 로깅 수준 별로 기록될 로그 항목들을 정하고
사용자가 보기 쉬운 포맷으로 제공하면 좋을 것 같습니다.
CRC 체크를 통과하지 못한 경우
과제#2 이슈 케이스에 해당하는 경우
이벤트 스트림의 시작과 끝
주요 이벤트에 대한 간단한 덤프
로깅 내장 라이브러리 사용해보신 분들의 많은 참여 부탁드립니다.
README 사용 사례 추가
TestCTLConnectionSettings Test
제대로 동작하는것 처럼 보이지만, 실제로는 의도한 바와 다르게 동작중임
def setUp(self):
super(TestCTLConnectionSettings, self).setUp()
self.stream.close()
ctl_db = copy.copy(self.database)
ctl_db["db"] = None
ctl_db["port"] = 3307
self.ctl_conn_control = pymysql.connect(**ctl_db)
self.ctl_conn_control.cursor().execute("DROP DATABASE IF EXISTS pymysqlreplication_test")
self.ctl_conn_control.cursor().execute("CREATE DATABASE pymysqlreplication_test")
self.ctl_conn_control.close()
ctl_db["db"] = "pymysqlreplication_test"
self.ctl_conn_control = pymysql.connect(**ctl_db)
# PRINT ADDED FOR DEBUGGING
print(ctl_db)
print(self.database)
# PRINT ADDED FOR DEBUGGING
self.stream = BinLogStreamReader(
self.database,
ctl_connection_settings=ctl_db,
server_id=1024,
only_events=(WriteRowsEvent,),
fail_on_table_metadata_unavailable=True
)
ctl_db
와 self.database
를 출력해주는 print를 추가후 실행
> {'host': 'localhost', 'user': 'root', 'passwd': '', 'port': 3307, 'use_unicode': True, 'charset': 'utf8', 'db': 'pymysqlreplication_test'}
> {'host': 'localhost', 'user': 'root', 'passwd': '', 'port': 3306, 'use_unicode': True, 'charset': 'utf8', 'db': 'pymysqlreplication_test'}
원래 테스트의 목적은 self.database
라는 dict를 copy.copy
를 통해 shallow copy하고 포트를 변경해 3307로 접속하려는 것으로 추정
하지만 BinLogStreamReader
에 들어가는 self.database
는 부모 클래스의 기본값인 3306으로 접속을 시도
3307 포트로 BinLogStreamReader
가 접속하도록 변경
#11 테스트 작성중 발견
event(MariadbGtidListEvent) 구현
기존과 다른 Master의 벤더, 버전, 시스템 변수 환경에서 테스트하기 위해서는 많은 코드 수정이 필요합니다.
리팩터링을 통해 최소한의 코드 수정으로 새로운 테스트 환경을 구축할 수 있도록 개선이 필요합니다.
아래 사안에 대해 논의해보면 좋을 것 같습니다.
린터를 사용해서 PEP8 미준수 사항이 있는지 보여줄지
오토포매팅을 사용해서 PEP8을 준수하도록 강제할지
린터/오토포매터 적용할 시점을 커밋/PR할지
어떤 린터, 오토포매터를 사용할지
서버에서는 UTC 시간대를 사용하여 모든 Test가 문제 없이 통과하지만,
Local에서 테스트 할때는 Datetime이 KST(Korean Standard Time)에 보정 되어 9시의 시차가 발생해 테스트를 실패함.
Rows 이벤트에서 컬럼값 None
이 가지는 의미
Date
혹은 Datetime
형 컬럼값을 읽어왔는데 Python Datetime.Date
혹은 Datetime.Datetime
으로 나타낼 수 없는 값인 경우 (표현 가능한 최솟값 미만이거나, 최댓값 초과)
위 경우 모두 사용자에게 컬럼값이 None
으로 전달되는데,
사용자 입장에서 세 가지 경우를 구분할 수 있는 방법이 없다.
세 가지 케이스를 구분할 수 있도록 개선해주세요.
개선이 불가능한 경우에도 Documentation의 Limitation 항목에 이슈를 적고, 우회책이 있다면 함께 적어주세요.
MySQL로부터 이벤트를 받아오기 위해 다음 코드를 실행했습니다.
from pymysqlreplication import BinLogStreamReader
stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
blocking=True,
)
for binlogevent in stream:
pass
이슈가 발생한 MySQL은 다음과 같은 특성이 있습니다.
코드가 실행된 후에 MySQL의 Innodb_history_list_length
값이 꾸준히 증가하고 있습니다.
Innodb_history_list_length
의 증가로 인해 MySQL에 다음과 같은 영향이 있을 것으로 예상됩니다.
위 코드를 실행하더라도 Innodb_history_list_length
가 증가하지 않도록 본 패키지 코드를 수정해주세요.
ROWS_QUERY_LOG_EVENTS
pymysqlreplication.tests.test_data_type.test_partition_id
테스트가 의도대로 작동하기 위해서는 MySQL 8.0.16 버전 이상의 컨테이너가 필요합니다.
해당 테스트에 대한 상세한 내용은 PR을 참고해주세요
많은 분들이 의견주신대로 docker-compose에 버전/벤더별로 많은 서비스들이 추가될 수 있을 것 같은데요,
제가 예전에 작성했던 테스트 돌리려면 적어도 MySQL 8.0.16 이상 서비스 1개는 추가되어야 할 것 같네요
YAML anchor 기능을 활용해서 공통 되는 설정값들을 간소하게/깔끔하게 표현할 수 있을 것 같아서 다음과 같이 수정하고 원본 reop에 PR 넣어보려고 합니다.
충은님(@cucuridas)이 깔끔하게 작성해주신 docker-compose.yml에 영감을 받아 숟가락 얹어 봅니다.
수정 전
version: '3.2'
services:
percona-5.7:
image: percona:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: true
ports:
- 3306:3306
command: mysqld --log-bin=mysql-bin.log --server-id 1 --binlog-format=row --gtid_mode=on --enforce-gtid-consistency=on --log_slave_updates
percona-5.7-ctl:
image: percona:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: true
ports:
- 3307:3307
command: mysqld --log-bin=mysql-bin.log --server-id 1 --binlog-format=row --gtid_mode=on --enforce-gtid-consistency=on --log_slave_updates -P 3307
percona-8.0.16:
image: percona:8.0.16
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: true
ports:
- 3309:3307
command: mysqld --log-bin=mysql-bin.log --server-id 1 --binlog-format=row --gtid_mode=on --enforce-gtid-consistency=on --log_slave_updates -P 3307
mariadb-10.6:
image: mariadb:10.6
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
ports:
- "3308:3306"
command: |
--server-id=1
--default-authentication-plugin=mysql_native_password
--log-bin=master-bin
--binlog-format=row
--log-slave-updates=on
수정 후
version: '3.2'
x-mysql: &mysql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: true
command: >
mysqld
--log-bin=mysql-bin.log
--server-id 1
--binlog-format=row
--gtid_mode=on
--enforce-gtid-consistency=on
--log_slave_updates
x-mariadb: &mariadb
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
command: |
--server-id=1
--default-authentication-plugin=mysql_native_password
--log-bin=master-bin
--binlog-format=row
--log-slave-updates=on
services:
percona-5.7:
<<: *mysql
image: percona:5.7
ports:
- 3306:3306
percona-5.7-ctl:
<<: *mysql
image: percona:5.7
ports:
- 3307:3306
percona-8.0.16:
<<: *mysql
image: percona:8.0.16
ports:
- 3309:3306
mariadb-10.6:
<<: *mariadb
image: mariadb:10.6
ports:
- 3308:3306
x-
로 시작하는 element들은 docker-compose의 extension 기능을 활용한 것으로, 실제로 실행되는 부분은 아닙니다.--log_slave_updates
는 필요 없는 인자인 것 같아서 원본 repo에 삭제 예고(?) 해놓았습니다.이와 같이 MySQL 8.0.22 버전 이후 변경된 복제 관련 명령어들을 찾고 버전 별 분기 처리를 추가하여 수정합니다.
https://dev.mysql.com/doc/refman/8.0/en/show-slave-hosts.html
Detected increasing handler_read_rnd.
This can lead to an increase in I/O operations, as the system needs to read through potentially large amounts of data. This can strain the disk subsystem and lead to increased latency for other operations.
Also, Sequentially reading through rows can lead to increased CPU usage, especially if the dataset is large.
This can be done by removing 'ORDER BY' statement in table_map event.
MySQL로부터 이벤트를 받아오기 위해 다음 코드를 실행했습니다.
from pymysqlreplication import BinLogStreamReader
stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
blocking=True,
)
for binlogevent in stream:
pass
이슈가 발생한 MySQL은 다음과 같은 특성이 있습니다.
코드가 실행된 후에 MySQL의 Handler_read_rnd
값이 급증한 후 유지되고 있습니다.
Handler_read_rnd
의 급증으로 인해 MySQL에 다음과 같은 영향이 있을 것으로 예상됩니다.
위 코드를 실행한 후에도 Handler_read_rnd
값이 실행 이전과 동일하도록 본 패키지 코드를 수정해주세요.
현재 멘토님께서 조언해주신대로 PEP8 (PEP 257)을 따르는 주석으로 수정하다가, 전체적인 주석이 그러한 상태라는 걸 알고나서 전반적으로 수정하고 싶다고 생각했습니다.
동참하고 싶으신 분이 계시거나, 코드를 읽다가 이렇게 수정했으면 좋겠다는 의견이 있으셨다면 들려주신다면 감사할 것 같습니다.
위와 같은 식으로 바꾸려고 합니다. (예시입니다.)
멘토님께서 공유해주신 문서 를 참고할 예정입니다.
같이 할 분이 계셔도 너무 좋을 거 같습니다 ㅎㅎ
학부생들만이 구현할 수 있는 🔥CRC🔥 이슈입니다.
직장인들의 뇌가 얼마나 녹슬었는지 증명해주시기 바랍니다.
이 이벤트에는 다음과 같은 정보가 포함됩니다.
위 정보들을 저장할 수 있게 구현하려고 합니다.
관심있으신 분은 의견 주시면 함께 구현해도 너무 좋을 것 같습니다!
Near Zero Downtime Migration from MySQL to DynamoDB (by YongSeong Lee, Amazon Web Services)
현재 기록중인 binary log file에서만 찾기 때문에 발생하는 문제 해결
...
def isMariaDB(self):
if self.__is_mariaDB is None:
self.__is_mariaDB = "MariaDB" in self.execute("SELECT VERSION()").fetchone()
return self.__is_mariaDB
...
columns_present_bitmap
/ columns_present_bitmap2
columns_present_bitmap_before
/ columns_present_bitmap_after
등으로 더 이해하기 쉬운 변수명으로 변경A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.