Code Monkey home page Code Monkey logo

python-mysql-replication's People

Contributors

alex avatar baloo avatar bjoernhaeuser avatar chaoslawful avatar chungeun-choi avatar darnuria avatar dongwook-chan avatar ebang091 avatar etern avatar groom2hub avatar heehehe avatar idop-alooma avatar jaehyeonpy avatar julien-duponchelle avatar lxyu avatar mahadirz avatar mastak avatar mirageoasis avatar mjs1995 avatar oseemann avatar paulvic avatar phoenixluo avatar romuald avatar samira-el avatar sean-k1 avatar siddontang avatar soulee-dev avatar starcat37 avatar suhwan-cheon avatar why-arong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

python-mysql-replication's Issues

Upgrade GitHub Actions to Latest Versions (in Preparation for Node 16 EOL)

#46

Overview

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.

Description

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

Change

Updates GitHub Actions Versions:
From actions/checkout@v2 to actions/checkout@v4
From actions/setup-python@v2 to actions/setup-python@v4

Benefits

  • Keeps the Actions Up-to-date: Utilizes performance improvements and new features from the latest versions.
  • Future-proofs the Repository: Prepares the codebase for the end of support for Node 16.

References

CI enhancement

  • docker-compose mysql image 수정 및 추가
    • mysql 8 추가에 따른 테스트 개선
  • local에서 테스트할 수 있는 docker-compose 추가
    • github actions 동작 시 actions의 container가 아닌, docker-compose container 위에서 테스트 수행되도록 수정
  • test coverage & report 추가

로깅 추가

본 라이브러리의 사용자가 활용할 수 있는 어떠한 로그도 제공되고 있지 않습니다.
다음의 예시처럼 로깅 수준 별로 기록될 로그 항목들을 정하고
사용자가 보기 쉬운 포맷으로 제공하면 좋을 것 같습니다.

ERROR

CRC 체크를 통과하지 못한 경우

WARN

과제#2 이슈 케이스에 해당하는 경우

INFO

이벤트 스트림의 시작과 끝

DEBUG

주요 이벤트에 대한 간단한 덤프

로깅 내장 라이브러리 사용해보신 분들의 많은 참여 부탁드립니다.

TestCTLConnectionSettings Logic bug

Reproduce

TestCTLConnectionSettings Test

Current Behavior

제대로 동작하는것 처럼 보이지만, 실제로는 의도한 바와 다르게 동작중임

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_dbself.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으로 접속을 시도

Expected Behavior

3307 포트로 BinLogStreamReader가 접속하도록 변경

Comments

#11 테스트 작성중 발견

테스트 코드 리팩터링

기존과 다른 Master의 벤더, 버전, 시스템 변수 환경에서 테스트하기 위해서는 많은 코드 수정이 필요합니다.
리팩터링을 통해 최소한의 코드 수정으로 새로운 테스트 환경을 구축할 수 있도록 개선이 필요합니다.

린팅 혹은 오토포매팅 적용

아래 사안에 대해 논의해보면 좋을 것 같습니다.

린팅 vs 오토포매팅

린터를 사용해서 PEP8 미준수 사항이 있는지 보여줄지
오토포매팅을 사용해서 PEP8을 준수하도록 강제할지

적용 시점

린터/오토포매터 적용할 시점을 커밋/PR할지

린터 및 오토포매터 종류 선택하기

어떤 린터, 오토포매터를 사용할지

시간대에 종속적인 Datetime assertion Test

서버에서는 UTC 시간대를 사용하여 모든 Test가 문제 없이 통과하지만,
Local에서 테스트 할때는 Datetime이 KST(Korean Standard Time)에 보정 되어 9시의 시차가 발생해 테스트를 실패함.

중의적으로 쓰이는 컬럼값 `None`🤔

Rows 이벤트에서 컬럼값 None이 가지는 의미

  • 변경된 컬럼이 아닌 경우
  • 변경된 컬럼값이 NULL인 경우
  • MySQL에서 Date 혹은 Datetime형 컬럼값을 읽어왔는데 Python Datetime.Date 혹은 Datetime.Datetime으로 나타낼 수 없는 값인 경우 (표현 가능한 최솟값 미만이거나, 최댓값 초과)

위 경우 모두 사용자에게 컬럼값이 None으로 전달되는데,
사용자 입장에서 세 가지 경우를 구분할 수 있는 방법이 없다.

세 가지 케이스를 구분할 수 있도록 개선해주세요.
개선이 불가능한 경우에도 Documentation의 Limitation 항목에 이슈를 적고, 우회책이 있다면 함께 적어주세요.


`Innodb_history_list_length` 증가

시나리오

MySQL로부터 이벤트를 받아오기 위해 다음 코드를 실행했습니다.

from pymysqlreplication import BinLogStreamReader

stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                blocking=True,
                                )

for binlogevent in stream:
    pass

MySQL의 특성

이슈가 발생한 MySQL은 다음과 같은 특성이 있습니다.

  • DML이 빈번히 발생 중

이슈

코드가 실행된 후에 MySQL의 Innodb_history_list_length 값이 꾸준히 증가하고 있습니다.
Innodb_history_list_length의 증가로 인해 MySQL에 다음과 같은 영향이 있을 것으로 예상됩니다.

  • 사용자의 쿼리에 대한 응답 시간 증대

요구 사항

위 코드를 실행하더라도 Innodb_history_list_length가 증가하지 않도록 본 패키지 코드를 수정해주세요.

인프라 구축 - MariaDB binlog event Test를 위한 구축

필요성: 아래 이미지와 같이 maria DB 테스트 코드는 maria DB가 아닐 경우 스킵되기 때문에 테스트 환경 구축필요
image

  1. Docker-compose를 활용하여 MariaDB binlog event 테스트 케이스를 실행 시킬 인프라 환경 구축
  2. .github/workflows 파일 수정을 통한 Git Action 자동화

`docker-compose.yml` 간소화

많은 분들이 의견주신대로 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 기능을 활용한 것으로, 실제로 실행되는 부분은 아닙니다.
  • Anchor 적용하면 어떤 모습인지는 https://yaml-online-parser.appspot.com 에서 확인 가능하십니다~
  • --log_slave_updates는 필요 없는 인자인 것 같아서 원본 repo에 삭제 예고(?) 해놓았습니다.

Fix commands that change since MySQL 8.0.22

이슈

  • MySQL 8.0.22 이후 변경된 복제 관련 명령어 및 파라미터들이 존재합니다.
  • MySQL 8.0.22 이전에 동일한 기능을 하는 명령어 및 파라미터들은 아직 사용할 수 있지만 추후 버전 업데이트에 따라 사라질 수 있습니다.

예시

Show slave hosts

스크린샷 2023-07-23 오후 2 03 27

slave_uuid

  • 변경 전
    스크린샷 2023-07-23 오후 2 08 06
  • 변경 후
    스크린샷 2023-07-23 오후 2 03 39

추후 문제가 발생할 수 있는 코드

https://github.com/23-OSSCA-python-mysql-replication/python-mysql-replication/blob/92d3e6651657d7d2f2d941cd33e45fbd1437cab9/pymysqlreplication/binlogstream.py#L302-L305


요구사항

이와 같이 MySQL 8.0.22 버전 이후 변경된 복제 관련 명령어들을 찾고 버전 별 분기 처리를 추가하여 수정합니다.


참고자료

https://dev.mysql.com/doc/refman/8.0/en/show-slave-hosts.html

decimal 타입 읽을 때 에러발생

# 379 (테스트 케이스를 조금 더 받아봐야함)

UserVarEvent를 구현하다가 발견한 에러로

현재 row_event의 deciaml type을 읽을 때 에러가 발생하는 거 같습니다.

관련 테스트 케이스

  • raw_decimal = b"n\xa3\xf2\x08~\x9b\xfa('"
  • precision = 14
  • decimals = 10

현재 소스코드 구현은 완료 되었으며 기존 row_event의 __read_new_decimal의 코드를 수정하여 PR올리고자 합니다.

increasing handler_read_rnd

Problem

Detected increasing handler_read_rnd.
스크린샷 2023-08-25 오후 4 33 04

Concerns

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.

Solution

This can be done by removing 'ORDER BY' statement in table_map event.

스크린샷 2023-08-25 오후 4 43 56

`Handler_read_rnd` 증가

시나리오

MySQL로부터 이벤트를 받아오기 위해 다음 코드를 실행했습니다.

from pymysqlreplication import BinLogStreamReader

stream = BinLogStreamReader(connection_settings=MYSQL_SETTINGS,
                                blocking=True,
                                )

for binlogevent in stream:
    pass

MySQL의 특성

이슈가 발생한 MySQL은 다음과 같은 특성이 있습니다.

  • binary log가 빈번히 rotate됨
  • 테이블 개수가 많으며, 테이블 당 컬럼 개수가 많음
  • DML이 빈번히 발생 중 (특정 테이블에 몰리지 않고, 전체 테이블에 골고루 DML 발생)

이슈

코드가 실행된 후에 MySQL의 Handler_read_rnd 값이 급증한 후 유지되고 있습니다.
Handler_read_rnd의 급증으로 인해 MySQL에 다음과 같은 영향이 있을 것으로 예상됩니다.

  • Disk IO 증대
  • 사용자의 쿼리에 대한 응답 시간 증대

요구 사항

위 코드를 실행한 후에도 Handler_read_rnd값이 실행 이전과 동일하도록 본 패키지 코드를 수정해주세요.

Docstring 수정

현재 멘토님께서 조언해주신대로 PEP8 (PEP 257)을 따르는 주석으로 수정하다가, 전체적인 주석이 그러한 상태라는 걸 알고나서 전반적으로 수정하고 싶다고 생각했습니다.

동참하고 싶으신 분이 계시거나, 코드를 읽다가 이렇게 수정했으면 좋겠다는 의견이 있으셨다면 들려주신다면 감사할 것 같습니다.

제 계획은 우선 다음과 같습니다 :

1. event.py 등 각 py 파일의 docstring을 랜더링 시 개행된 형태로 수정합니다.

스크린샷 2023-08-06 오후 9 10 50

꼴의 주석을
스크린샷 2023-08-06 오후 9 10 07

위와 같은 식으로 바꾸려고 합니다. (예시입니다.)
멘토님께서 공유해주신 문서 를 참고할 예정입니다.

2. 가능하면 가독성을 높이는 쪽으로 Raises, Params 와 관련된 부분도 수정하려고 합니다.

같이 할 분이 계셔도 너무 좋을 거 같습니다 ㅎㅎ

이벤트 footer를 활용한 CRC

학부생들만이 구현할 수 있는 🔥CRC🔥 이슈입니다.
직장인들의 뇌가 얼마나 녹슬었는지 증명해주시기 바랍니다.

event 구현 - transaction_context_event

https://dev.mysql.com/doc/dev/mysql-server/latest/classbinary__log_1_1Transaction__context__event.html

이 이벤트에는 다음과 같은 정보가 포함됩니다.

  • 서버 UUID: 이벤트를 생성한 서버의 UUID.
  • 스레드 ID: 이벤트를 생성한 서버에서 트랜잭션을 실행하는 스레드의 ID.
  • 접속 상태: 트랜잭션의 접속 상태를 나타내는 플래그.

위 정보들을 저장할 수 있게 구현하려고 합니다.
관심있으신 분은 의견 주시면 함께 구현해도 너무 좋을 것 같습니다!

event 구현 - MariadbAnnotateRowsEvent

  1. 해당 event 수집을 위한 BinLogStreamReader 클래스의 파라미터 추가
    -> flag 값이 2로 설정되어있어야 master로 부터 event 전달
  2. event(MariadbAnnotateRowsEvent) 구현

bug - PyMySQLReplicationTestCase.isMariaDB() 정상 동작하지 않음

bug - PyMySQLReplicationTestCase.isMariaDB() 정상 동작하지 않음


  • 함수 설명
    해당 함수를 통해서 test 때 연결되어진 DBMS가 mysql 인지 mariaDB 인지 구별할 수 있습니다
    ...
    def isMariaDB(self):
        if self.__is_mariaDB is None:
            self.__is_mariaDB = "MariaDB" in self.execute("SELECT VERSION()").fetchone()
        return self.__is_mariaDB
    ...
  • 문제
    fechone() 함수를 통해 실행시킨 결과 값은 tuple 형태로 전달 받고 있지만 현재 "MariaDB" in self.execute("SELECT VERSION()").fetchone() 구문은 string 타입의 데이터를 확인하고 있음에 따라 isMariaDB 함수는 항상 False를 반환하는 에러가 존재합니다
    image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.