찾다
데이터 베이스MySQL 튜토리얼MySQL Multi-Master实现方式

MySQL Multi-Master实现方式

Mar 13, 2017 pm 01:46 PM
mysql콘텐츠성취하다방법

MySQL Mutil-Master Replication喊了很久了,但是MySQL一直没有去,虽然在MySQL源码中有注释将实现Multi-Master,mi结构体也为Multi-Master做好了准备,但是却一直不见MySQL发布。

但是Multi-Master –> Slave的Repliction确实非常有用,例如一台集中备份机备份所有Master的数据。

实现Multi-Master有几种思路:
1. 修改MySQL源码:修改sql_yacc.yy, sql_lex.cc支持多Master的CHANGE MASTER TO语法,然后修改slave相关的slave.cc,支持开启多个Slave, 将slave io/ slave thread线程扩展为一个slave_list。
2. 利用mysqlbinlog之类的工具,远程注册到Master获取binlog,导入本地Slave服务器。

从效率看,肯定第一种方式效率高,但是风险太大了,并且MySQL版本更新,可能需要变动自己的代码以适应新的MySQL Source, MySQL官方的实现方式肯定是第一种,从源码中的注释可以看出他们的设计思路。但是他们考虑的问题可能是多个Master复制如何处理冲突等异常,因而迟迟不发布。

为了避免过多的入侵MySQL,我采用第二种方式,用一个脚本或者程序等等,去调用mysqlbinlog,用-R远程请求到–to-last-log,然后稍微修改一下啊mysqlbinlog的源码,在日志切换后计数一下,在输出文件末尾打上切换日志的个数,例如:

insert into a values (8)/*!*/;
# at 1070#110114 16:16:11 server id 3  end_log_pos 1097 	Xid = 36COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;-- Rorate binlog count: 1

— Rorate binlog count: 1就是日志切换信息,表示切换了一次日志(即传入Master的日志号没有用完)然后tail末尾的end_pos来查看本次同步到哪里了,写到*.info的文件中。

我的脚本需要配置一个multi_master.conf文件,配好每个Master的信息,例如:

#cat multi_master.conf 
[master1]MASTER_HOST=1.2.3.4
MASTER_USER=plx
MASTER_PASSWORD=plx
MASTER_PORT=3306MASTER_LOG_NAME=mysql-bin
MASTER_LOG_IDX=000002
MASTER_LOG_POS=521RELAY_LOG_DIR=/tmp/RELAY_LOG_NAME=1-relay-bin
 [master2]MASTER_HOST=2.3.4.5
MASTER_USER=plx
MASTER_PASSWORD=plx
MASTER_PORT=3306MASTER_LOG_NAME=mysql-bin
MASTER_LOG_IDX=000002
MASTER_LOG_POS=581RELAY_LOG_DIR=/tmp/RELAY_LOG_NAME=2-relay-bin
 [slave]SLAVE_USER=plx
SLAVE_PASSWORD=plx

SLAVE默认导入本地,所以没有提供主机选项。
配置文件的含义是,定义了master1和master2两个Master,名称其实只要不是slave都行,[slave]中定义了本地导入的用户名和密码。
特有的参数我解释下,没解释的跟MySQL一样,
MASTER_LOG_NAME和MASTER_LOG_IDX组成MySQL中的Master_log_file,RELAY_LOG_DIR表示取回的binlog文件放哪个目录,RELAY_LOG_NAME是Relay文件的文件名,会加上标号,跟MySQL一样,这个脚本会自动处理。
一旦执行过一次,就会生成master1.info之类的文件,来表示当前同步到哪里了,例如下面这个例子:

MASTER_LOG_POS=1482NAME=master1
MASTER_USER=plx
RELAY_LOG_NAME=1-relay-bin
MASTER_LOG_IDX=2MASTER_HOST=1.2.3.4
MASTER_LOG_NAME=mysql-bin
MASTER_PORT=3306RELAY_LOG_DIR=/tmp/MASTER_PASSWORD=plx
RELAY_LOG_IDX=3

只有找不到*.info的时候,才会使用multi_master.conf。

现在每次调度multi_master_repl.pl都只会运行一次,可以不断的调度multi_master_repl.pl,因为还没有完全搞定KILL信号在Perl脚本的处理,用C重写后会解决,不能暴力kill -9,会导致不知道复制到哪里了。

这是下载地址,切勿用在生产环境,这只是个验证想法的程序。

Note: There is a file embedded within this post, please visit this post to download the file.

下一步我想用C重新实现,在mysqlbinlog源码基础上修改,获取到的日志直接写入到sock或直接导入远程mysql,避免多写一次文件,也欢迎提供新思路。

这是一次执行的日志:

#./multi_master_repl.pl 
(DEBUG) Enter: get_config()
	Info: begin
	(DEBUG) get_config --> master1
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_HOST=1.2.3.4
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_USER=plx
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_PASSWORD=plx
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_PORT=3306
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_LOG_NAME=mysql-bin
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_LOG_IDX=000002
	(DEBUG) get_config --> multi_master.conf --> master1:MASTER_LOG_POS=521
	(DEBUG) get_config --> multi_master.conf --> master1:RELAY_LOG_DIR=/tmp/
	(DEBUG) get_config --> multi_master.conf --> master1:RELAY_LOG_NAME=1-relay-bin
	(DEBUG) get_config --> Found master1.info, Read it
	(DEBUG) get_config --> master1.info --> master1:MASTER_LOG_POS=1097
	(DEBUG) get_config --> master1.info --> master1:NAME=master1
	(DEBUG) get_config --> master1.info --> master1:MASTER_USER=plx
	(DEBUG) get_config --> master1.info --> master1:RELAY_LOG_NAME=1-relay-bin
	(DEBUG) get_config --> master1.info --> master1:MASTER_LOG_IDX=2
	(DEBUG) get_config --> master1.info --> master1:MASTER_HOST=1.2.3.4
	(DEBUG) get_config --> master1.info --> master1:MASTER_LOG_NAME=mysql-bin
	(DEBUG) get_config --> master1.info --> master1:MASTER_PORT=3306
	(DEBUG) get_config --> master1.info --> master1:RELAY_LOG_DIR=/tmp/
	(DEBUG) get_config --> master1.info --> master1:MASTER_PASSWORD=plx
	(DEBUG) get_config --> master1.info --> master1:RELAY_LOG_IDX=2
	(DEBUG) get_config --> Push[master1] to Master_Info_List
	(DEBUG) get_config --> master2
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_HOST=2.3.4.5
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_USER=plx
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_PASSWORD=plx
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_PORT=3306
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_LOG_NAME=mysql-bin
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_LOG_IDX=000002
	(DEBUG) get_config --> multi_master.conf --> master2:MASTER_LOG_POS=581
	(DEBUG) get_config --> multi_master.conf --> master2:RELAY_LOG_DIR=/tmp/
	(DEBUG) get_config --> multi_master.conf --> master2:RELAY_LOG_NAME=2-relay-bin
	(DEBUG) get_config --> Found master2.info, Read it
	(DEBUG) get_config --> master2.info --> master2:MASTER_LOG_POS=1541
	(DEBUG) get_config --> master2.info --> master2:NAME=master2
	(DEBUG) get_config --> master2.info --> master2:MASTER_USER=plx
	(DEBUG) get_config --> master2.info --> master2:RELAY_LOG_NAME=2-relay-bin
	(DEBUG) get_config --> master2.info --> master2:MASTER_LOG_IDX=2
	(DEBUG) get_config --> master2.info --> master2:MASTER_HOST=2.3.4.5
	(DEBUG) get_config --> master2.info --> master2:MASTER_LOG_NAME=mysql-bin
	(DEBUG) get_config --> master2.info --> master2:MASTER_PORT=3306
	(DEBUG) get_config --> master2.info --> master2:RELAY_LOG_DIR=/tmp/
	(DEBUG) get_config --> master2.info --> master2:MASTER_PASSWORD=plx
	(DEBUG) get_config --> master2.info --> master2:RELAY_LOG_IDX=2
	(DEBUG) get_config --> Push[master2] to Master_Info_List
	(DEBUG) get_config --> multi_master.conf --> slave:SLAVE_USER=plx
	(DEBUG) get_config --> multi_master.conf --> slave:SLAVE_PASSWORD=plx
(DEBUG) Enter: get_config()
	Info: exit
(DEBUG) Enter: create_slave_threads()
	Info: begin
	(DEBUG) create_slave_threads --> Creating run_slave Threads...
(DEBUG) Enter: run_slave()
	Info: begin [tid: 1]
	(DEBUG) run_slave(0) --> NO KILL SIGNAL --> g_is_killed =>0
	(DEBUG) run_slave --> mysqlbinlog: ./mysqlbinlog -h1.2.3.4 -uplx -pplx -R -t --start-position=1097 mysql-bin.000002 > /tmp/1-relay-bin.000002
Warning: ./mysqlbinlog: unknown variable 'loose_default-character-set=utf8'
	(DEBUG) run_slave(0) --> NO KILL SIGNAL --> g_is_killed =>0
(DEBUG) Enter: import_to_slave()
	Info: begin [Param: p_master_idx=>0]
	(DEBUG) import_to_slave(0) --> NO KILL SIGNAL --> g_is_killed =>0
	(DEBUG) import_to_slave(0) --> Importing Relay Log /tmp/1-relay-bin.000002 To Slave...
	(DEBUG) create_slave_threads --> Created 2 run_slave Threads
(DEBUG) Enter: run_slave()
	Info: begin [tid: 2]
	(DEBUG) run_slave(1) --> NO KILL SIGNAL --> g_is_killed =>0
	(DEBUG) run_slave --> mysqlbinlog: ./mysqlbinlog -h2.3.4.5 -uplx -pplx -R -t --start-position=1541 mysql-bin.000002 > /tmp/2-relay-bin.000002
Warning: ./mysqlbinlog: unknown variable 'loose_default-character-set=utf8'
	(DEBUG) run_slave(1) --> NO KILL SIGNAL --> g_is_killed =>0
(DEBUG) Enter: import_to_slave()
	Info: begin [Param: p_master_idx=>1]
	(DEBUG) import_to_slave(1) --> NO KILL SIGNAL --> g_is_killed =>0
	(DEBUG) import_to_slave(1) --> Importing Relay Log /tmp/2-relay-bin.000002 To Slave...
(DEBUG) Enter: update_master_info()
	Info: begin [Param: p_master_idx=>0]
(DEBUG) Enter: update_master_info()
	Info: begin [Param: p_master_idx=>1]
	(DEBUG) update_master_info(0) --> Now Master-Log is mysql-bin.000002 Pos is 1482
(DEBUG) Enter: update_master_info_file()
	Info: begin [Param: p_master_idx=>0]
	(DEBUG) update_master_info_file(0) --> NO KILL SIGNAL --> g_is_killed =>0
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_LOG_POS=1482
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> NAME=master1
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_USER=plx
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> RELAY_LOG_NAME=1-relay-bin
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_LOG_IDX=2
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_HOST=1.2.3.4
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_LOG_NAME=mysql-bin
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_PORT=3306
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> RELAY_LOG_DIR=/tmp/
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> MASTER_PASSWORD=plx
	(DEBUG) update_master_info_file(0) --> Writing master1.info --> RELAY_LOG_IDX=3
	(DEBUG) update_master_info_file(0) --> Created master1.info
(DEBUG) Enter: update_master_info_file(0)
	Info: exit
(DEBUG) Enter: update_master_info(0)
	Info: exit
(DEBUG) Enter: import_to_slave(0)
	Info: exit
(DEBUG) Enter: run_slave(0)
	Info: exit
	(DEBUG) update_master_info(1) --> Now Master-Log is mysql-bin.000002 Pos is 2120
(DEBUG) Enter: update_master_info_file()
	Info: begin [Param: p_master_idx=>1]
	(DEBUG) update_master_info_file(1) --> NO KILL SIGNAL --> g_is_killed =>0
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_LOG_POS=2120
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> NAME=master2
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_USER=plx
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> RELAY_LOG_NAME=2-relay-bin
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_LOG_IDX=2
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_HOST=2.3.4.5
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_LOG_NAME=mysql-bin
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_PORT=3306
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> RELAY_LOG_DIR=/tmp/
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> MASTER_PASSWORD=plx
	(DEBUG) update_master_info_file(1) --> Writing master2.info --> RELAY_LOG_IDX=3
	(DEBUG) update_master_info_file(1) --> Created master2.info
(DEBUG) Enter: update_master_info_file(1)
	Info: exit
(DEBUG) Enter: update_master_info(1)
	Info: exit
(DEBUG) Enter: import_to_slave(1)
	Info: exit
(DEBUG) Enter: run_slave(1)
	Info: exit
(DEBUG) Enter: create_slave_threads()
	Info: exit
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
MySQL에서 느린 쿼리를 식별하고 최적화하는 방법은 무엇입니까? (느린 쿼리 로그, Performance_schema)MySQL에서 느린 쿼리를 식별하고 최적화하는 방법은 무엇입니까? (느린 쿼리 로그, Performance_schema)Apr 10, 2025 am 09:36 AM

MySQL 느린 쿼리를 최적화하려면 SlowQueryLog 및 Performance_Schema를 사용해야합니다. 1. SlowQueryLog 및 Set Stresholds를 사용하여 느린 쿼리를 기록합니다. 2. Performance_schema를 사용하여 쿼리 실행 세부 정보를 분석하고 성능 병목 현상을 찾고 최적화하십시오.

MySQL 및 SQL : 개발자를위한 필수 기술MySQL 및 SQL : 개발자를위한 필수 기술Apr 10, 2025 am 09:30 AM

MySQL 및 SQL은 개발자에게 필수적인 기술입니다. 1.MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템이며 SQL은 데이터베이스를 관리하고 작동하는 데 사용되는 표준 언어입니다. 2.MYSQL은 효율적인 데이터 저장 및 검색 기능을 통해 여러 스토리지 엔진을 지원하며 SQL은 간단한 문을 통해 복잡한 데이터 작업을 완료합니다. 3. 사용의 예에는 기본 쿼리 및 조건 별 필터링 및 정렬과 같은 고급 쿼리가 포함됩니다. 4. 일반적인 오류에는 구문 오류 및 성능 문제가 포함되며 SQL 문을 확인하고 설명 명령을 사용하여 최적화 할 수 있습니다. 5. 성능 최적화 기술에는 인덱스 사용, 전체 테이블 스캔 피하기, 조인 작업 최적화 및 코드 가독성 향상이 포함됩니다.

MySQL 비동기 마스터 슬레이브 복제 프로세스를 설명하십시오.MySQL 비동기 마스터 슬레이브 복제 프로세스를 설명하십시오.Apr 10, 2025 am 09:30 AM

MySQL 비동기 마스터 슬레이브 복제는 Binlog를 통한 데이터 동기화를 가능하게하여 읽기 성능 및 고 가용성을 향상시킵니다. 1) 마스터 서버 레코드는 Binlog로 변경됩니다. 2) 슬레이브 서버는 I/O 스레드를 통해 Binlog를 읽습니다. 3) 서버 SQL 스레드는 데이터를 동기화하기 위해 Binlog를 적용합니다.

MySQL : 쉽게 학습하기위한 간단한 개념MySQL : 쉽게 학습하기위한 간단한 개념Apr 10, 2025 am 09:29 AM

MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 1) 데이터베이스 및 테이블 작성 : CreateAbase 및 CreateTable 명령을 사용하십시오. 2) 기본 작업 : 삽입, 업데이트, 삭제 및 선택. 3) 고급 운영 : 가입, 하위 쿼리 및 거래 처리. 4) 디버깅 기술 : 확인, 데이터 유형 및 권한을 확인하십시오. 5) 최적화 제안 : 인덱스 사용, 선택을 피하고 거래를 사용하십시오.

MySQL : 데이터베이스에 대한 사용자 친화적 인 소개MySQL : 데이터베이스에 대한 사용자 친화적 인 소개Apr 10, 2025 am 09:27 AM

MySQL의 설치 및 기본 작업에는 다음이 포함됩니다. 1. MySQL 다운로드 및 설치, 루트 사용자 비밀번호를 설정하십시오. 2. SQL 명령을 사용하여 CreateAbase 및 CreateTable과 같은 데이터베이스 및 테이블을 만듭니다. 3. CRUD 작업을 실행하고 삽입, 선택, 업데이트, 명령을 삭제합니다. 4. 성능을 최적화하고 복잡한 논리를 구현하기 위해 인덱스 및 저장 절차를 생성합니다. 이 단계를 사용하면 MySQL 데이터베이스를 처음부터 구축하고 관리 할 수 ​​있습니다.

InnoDB 버퍼 풀은 어떻게 작동하며 성능에 중요한 이유는 무엇입니까?InnoDB 버퍼 풀은 어떻게 작동하며 성능에 중요한 이유는 무엇입니까?Apr 09, 2025 am 12:12 AM

innodbbufferpool은 데이터와 색인 페이지를 메모리에로드하여 MySQL 데이터베이스의 성능을 향상시킵니다. 1) 데이터 페이지가 버퍼 풀에로드되어 디스크 I/O를 줄입니다. 2) 더러운 페이지는 정기적으로 디스크로 표시되고 새로 고침됩니다. 3) LRU 알고리즘 관리 데이터 페이지 제거. 4) 읽기 메커니즘은 가능한 데이터 페이지를 미리로드합니다.

MySQL : 초보자를위한 데이터 관리의 용이성MySQL : 초보자를위한 데이터 관리의 용이성Apr 09, 2025 am 12:07 AM

MySQL은 설치가 간단하고 강력하며 데이터를 쉽게 관리하기 쉽기 때문에 초보자에게 적합합니다. 1. 다양한 운영 체제에 적합한 간단한 설치 및 구성. 2. 데이터베이스 및 테이블 작성, 삽입, 쿼리, 업데이트 및 삭제와 같은 기본 작업을 지원합니다. 3. 조인 작업 및 하위 쿼리와 같은 고급 기능을 제공합니다. 4. 인덱싱, 쿼리 최적화 및 테이블 파티셔닝을 통해 성능을 향상시킬 수 있습니다. 5. 데이터 보안 및 일관성을 보장하기위한 지원 백업, 복구 및 보안 조치.

MySQL에서 인덱스를 사용하는 것보다 전체 테이블 스캔이 더 빠를 수 있습니까?MySQL에서 인덱스를 사용하는 것보다 전체 테이블 스캔이 더 빠를 수 있습니까?Apr 09, 2025 am 12:05 AM

전체 테이블 스캔은 MySQL에서 인덱스를 사용하는 것보다 빠를 수 있습니다. 특정 사례는 다음과 같습니다. 1) 데이터 볼륨은 작습니다. 2) 쿼리가 많은 양의 데이터를 반환 할 때; 3) 인덱스 열이 매우 선택적이지 않은 경우; 4) 복잡한 쿼리시. 쿼리 계획을 분석하고 인덱스 최적화, 과도한 인덱스를 피하고 정기적으로 테이블을 유지 관리하면 실제 응용 프로그램에서 최상의 선택을 할 수 있습니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기