MySQL 마스터 슬레이브에서 마스터를 결정하는 방법


17

MySQL 마스터-슬레이브 복제를 설정하고 슬레이브를 마스터로 승격시키는 장애 조치 상황 (마스터가 다운되는 경우)을 처리하는 방법을 알아 내려고 노력 중입니다.

내 응용 프로그램 서버는 모든 쓰기 작업을 현재 마스터로 보내야하지만 두 db 서버가 다른 물리적 위치에서 완전히 다른 서브넷에 있기 때문에 마스터와 슬레이브 (하트 비트, 연결 유지)간에 서버 수준 HA를 사용할 수 없습니다.

나는 이것이 응용 프로그램 수준에서 처리해야한다고 생각합니다. 두 서버를 쿼리하고 어느 서버가 마스터인지 물어 본 다음 해당 서버에 대한 모든 쿼리를 수행 할 수 있습니다.

MySQL에 현재 서버가 마스터-슬레이브 복제본의 마스터인지 확인하는 쿼리가 있습니까?


??? 어떤 버전의 MySQL을 사용하고 있습니까 ???
RolandoMySQLDBA

이것은 mysql 출력입니다Server version: 5.5.23 MySQL Community Server (GPL)
Ethan Hayon

답변:


13

@RolandoMySQLDBA는이 질문에 정확하게 대답했지만 ... 그의 솔루션은 "빠르고 더러운"것이라고 지적했습니다.

그리고 그것은 매우 진실한 진술입니다. :)

여기에 관심이있는 것은 그 대답에 관한 것이 아니라 원래의 질문이 잘못된 가정을하는 것처럼 보입니다.

두 서버를 쿼리하고 어느 서버가 마스터인지 물어 본 다음 해당 서버에 대한 모든 쿼리를 수행 할 수 있습니다.

문제는 MySQL 복제에서 마스터가 마스터임을 실제로 인식하지 못한다는 것입니다.

"마스터로의 승격"이라는 개념은 실제로 MySQL 비동기 복제의 개념이 아닙니다. MySQL 서버를 마스터 역할로 "승격"하는 것은 MySQL 서버에 "내부"발생하는 것과 달리 MySQL 서버에 "외부"발생하는 것입니다.

기술적으로 말하자면 바이너리 로깅이 활성화 된 모든 MySQL 서버는 슬레이브가없는 경우에도 마스터이므로 모든 서버 프로비저닝에서 "마스터로 승격"이 수행되지 않습니다. SHOW MASTER STATUS정확히 같은 방식으로 작동하고 정확히 동일한 결과를 반환합니다. 슬레이브 여부에 관계없이 2 개의 슬레이브가있는 마스터는 1 개의 슬레이브가 있거나 0 개의 슬레이브가있는 마스터보다 많거나 적습니다. 마찬가지로 슬레이브가 모두 오프라인 인 마스터는 여전히 마스터입니다. 슬레이브가 온라인으로 돌아 오면 중단 된 곳에서 복제를 수행하기 때문입니다.

어떤 의미에서 서버의 유일한 "인식"은 그것이 마스터인지 아닌 것이 아니라 슬레이브인지 아닌지입니다.

이것이 바로 롤란도의 해결책입니다. "당신은 노예입니까?" 대답이 '아니오'인 경우 이것이 마스터 여야한다고 가정합니다. 또한 그는 STOP SLAVE;발행 된 경우 결함이있는 가정으로 지적되었습니다 . 그러나 멈춘 노예는 여전히 노예이므로 "언제나 노예가 아니다"는 "주인이되는 것과"같지 않습니다.

추정 마스터에서 비슷한 테스트를 수행 할 수 있습니다.

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';

또는

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';

값이 0이면 슬레이브의 IO 스레드가 연결되지 않은 것입니다. 이 테스트는 비슷한 결함이 있습니다. 슬레이브가 관리 상으로 연결이 끊어 지거나 분리되거나 실패하면 연결되지 않습니다. 따라서 이것은 실제로 아무것도 해결하지 못합니다.

그럼에도 불구하고 information_schema.processlist "table"은 선택할 때마다 구체화되는 가상 테이블이며 시간과 비용이 소요됩니다. 각 스레드의 활동을 피어링해야하기 때문에 서버 사용량이 많을수록 비용이 더 많이 듭니다.

보다 가벼운 솔루션은 다음과 같습니다.

SELECT @@global.read_only;

슬레이브에서는 전역 변수를 설정하여 권한이없는 read_only사용자가 SUPER실수로 변수에 쓸 수 없도록 할 수 있습니다 (응용 프로그램에는 SUPER). 슬레이브를 마스터 역할로 수동으로 "승격" SET GLOBAL read_only = OFF하면 쓰기를 활성화 할 수 있습니다. (복제본은 설정 방법에 관계없이 항상 슬레이브에 쓸 수 있습니다).

그러나 이것은 여전히 ​​중요한 점을 놓친 것 같습니다.

응용 프로그램이 마스터 / 슬레이브 설정에서이 결정을 휴리스틱하게 만들어서는 안되며, 연결별로하지 말 것을 제안합니다. 응용 프로그램은 하드 구성 옵션을 사용하거나 응용 프로그램을 인식하지 못하고 데이터베이스 연결 대상을 다른 것으로 처리해야합니다.

또는 최소한 마스터가 실패 할 때까지 응용 프로그램을 전환해서는 안되며 절대 다시 전환해서는 안됩니다.

내가 말한 이유는 다음과 같습니다. "누가 또는 다른 사람에 의해 다른 서버를 마스터로 만들기 위해"결정 "을 한 후에는 온라인으로 돌아온 후에도 어떤 이유로 든 응용 프로그램을 원래 마스터로 다시 전환 할 수 없습니다. 개입없이.

버그가 발생하여 소프트웨어에 의한 충돌이 있다고 가정 해 봅시다. mysqld_safe정식으로 다시 시작 mysqld하고 InnoDB 응급 복구는 완벽하게 수행됩니다. 그러나 몇 분이 걸립니다.

한편, 마스터는 다운되었으므로 애플리케이션이 슬레이브로 전환되었습니다. 시스템이 무엇이든 거래가 이루어지고, 주문이 이루어지고, 자금이 이체되고, 의견이 게시되고, 블로그가 편집되었습니다.

이제 원래 마스터가 온라인으로 돌아옵니다.

응용 프로그램이 원래 마스터로 다시 전환되는 경우, 다음으로 일어날 수있는 일은 불일치로 인해 복제가 중지되기 때문입니다. 응용 프로그램이 평균적으로 슬레이브의 데이터를 변경했기 때문입니다. 시각. 일치하지 않는 데이터가있는 두 개의 데이터베이스 서버가 있으므로 수동으로 조정해야합니다. 달러 나 포인트 또는 크레딧이 관련된 경우 이제 잔액이 일치하지 않습니다.

따라서 사용자 개입없이 애플리케이션을 원래 마스터로 다시 전환 할 수 없도록하는 것이 중요합니다.

잠깐,이 시나리오에서 설명한대로 문제를 발견 했습니까? 마스터가 실패했지만 슬레이브가 여전히 슬레이브가 아니라 마스터라고 생각하기 때문에 응용 프로그램에서 슬레이브를 사용하지 않습니다 ... information_schema.processlist마스터 서버의 전원이 꺼져도 슬레이브 의 쿼리는 여전히 0이 아닌 값을 반환합니다 .

따라서이 STOP SLAVE테스트가 유용하기 위해서는 수동으로 테스트 해야하기 때문에 애플리케이션에서 아무것도 발견하지 않아도됩니다 .

응용 프로그램을 전환 할 수있게하려는 경우 더 나은 방법은 순환 복제로 서버를 구성하는 것입니다.

순환 복제에는 고유 한 문제가 있지만 응용 프로그램이 항상 한 번에 하나의 서버에만 쓰는 한 대부분의 문제는 문제가되지 않습니다. 다시 말해, 두 머신 모두 복제 의미에서 항상 동시에 마스터와 슬레이브 모두입니다. 그러나 일부 메커니즘을 통해 응용 프로그램은 항상 한 번에 한 머신 만 "마스터"로 가리키고 쓸 수 있어야합니다. .

분리로 인해 MySQL 서버에 HA 도구를 배치 할 수 없지만 애플리케이션 서버에서 HAProxy를 실행하여 구현할 수 있습니다. 응용 프로그램은 로컬 호스트의 "MySQL"에 연결합니다. 이는 MySQL이 아니지만 실제로 HAProxy입니다. TCP 연결을 적절한 MySQL 시스템으로 전달합니다.

HAProxy는 MySQL 서버에 대한 연결을 테스트하고 연결을 수락하고 인증을 허용하는 MySQL 시스템에 대한 트래픽 만 제공 할 수 있습니다.

애플리케이션 서버에서 실행되는 HAProxy의 조합 (리소스에 대한 수요는 애플리케이션 서버가해야하는 모든 것에 비해 크지 않음-소켓을 함께 묶고 페이로드를 무시하는 것) ...와 MySQL 순환 복제 질문에서 알려진 것을 기반 으로이 인스턴스에서 취할 수있는 접근 방식입니다.

또는 수동으로 엄격하게 설정하려면 애플리케이션 서버 /etc/hosts가 MySQL에 연결하는 데 사용하는 호스트 이름으로 앱 서버 파일 의 항목을 입력하는 것과 같이 "검색"보다 훨씬 간단한 방법을 사용하십시오. 마스터는 수동 프로세스입니다.

또는 Percona XtraDB Cluster를 사용하는 것이 더 복잡한 것입니다. 그러나 PXC에 3 개의 노드가있는 경우 2 대의 서버가 서로 볼 수 있지만 1 대의 서버와 격리되는 경우 (세 개의 서버가 모두 계속 실행중인 경우) 2 대의 서버는 계속 실행되지만 세 번째 서버를 추가해야합니다. 1 서버는 작은 공으로 말리면서 이상한 서버라는 것을 깨달았 기 때문에 아무것도하지 않습니다. 2는 네트워크 분할 이전에 온라인 상태였던 노드의 대부분을 여전히 구성하고 1은 그렇지 않다는 것을 인식하기 때문에 작동합니다. PXC를 사용하면 응용 프로그램이 어떤 서버에 연결되어 있는지는 중요하지 않습니다.

나는이 모든 것이 "응용 프로그램이 어느 서버가 마스터인지 확인하기 위해 서버를 폴링하지 말아야한다"고 말하고 싶다고 말합니다. 왜냐하면 그것은 당신을 물게 될 것이고 물린 날까지 성능을 떨어 뜨릴 것이기 때문입니다.


우선, 잘 작성된 답변에 감사드립니다. 나는 당신이 좋은 해결책을 제안했다고 생각합니다. 과거에는 순환 복제를 사용하는 것에 대해 생각했지만 안정성과 관련하여 나쁜 점을 읽었습니다. 그러나 auto_increment_increment, auto_increment_offset 등을 수정하면 이러한 문제를 대부분 예방할 수 있습니다. 응용 프로그램 서버에서 로컬로 HAProxy를 사용하면 (장애 조치로만) 응용 프로그램을 수정할 필요가 없으므로 장애 조치를 추상화 할 수 있습니다. 애플리케이션 계층에서 멀리 떨어진 로직. HAProxy 구성에 대해 살펴 보겠습니다. 감사합니다.
Ethan Hayon

1
기쁘다. 아직 투표하지 않은 경우 투표권이 있습니다. 순환 복제는 작동 방식을 이해하고 현명하게 사용하는 한 마스터 / 슬레이브만큼 안정적입니다 (두 기술을 모두 사용하는 동일한 기술입니다). 서버가 올바르게 동기화되고 응용 프로그램이 한 번에 하나의 서버에만 쓰는 한 문제가 없습니다. auto_increment_*변수는 "단지의 경우."여전히이 시나리오에서 사용하는 것이 좋다 또한, 사용하는 것을 기억 binlog_format= row또는 mixed-하지 statement(당신이 원하고 있지 않더라도).
Michael-sqlbot

이 자세한 설명을 통해 시스템을보다 견고하게 재구성 할 수 있었기 때문에 수용된 답변을 순전히 변경했습니다. @RolandoMySQLDBA의 답변은 여전히 ​​정확하며 처음 설명한 문제를 해결합니다. 감사!
에단 하욘

10

Master / Slave 만 사용하는 경우 다음은 빠르고 더러운 것입니다.

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

이것이 무엇을 말합니까?

  • 경우 SlaveThreadCount= 0, 당신은 주인이
  • 경우 SlaveThreadCount0>, 당신은 노예가

주의 사항 : 실행하지 않는 한 작동합니다.STOP SLAVE;

시도해야 할 또 다른 것은 : 슬레이브에서 바이너리 로깅을 비활성화하고 실행하는 경우 SHOW MASTER STATUS; 하면 마스터가 현재 이진 로그를 제공합니다. 노예는 당신에게 아무것도주지 않습니다.


굉장히, 이것이 바로 내가 필요한 것입니다. 이것이 문제에 대한 지저분한 해결책이라고 생각하십니까? 내가 상상할 수있는 유일한 문제는 두 서버 모두 마스터로 승격되는 것이지만 실제로는 발생하지 않아야합니다.
Ethan Hayon

이 답변이 필요한 경우 내 답변의 확인 표시를 클릭하여 수락 한 것으로 표시하십시오.
RolandoMySQLDBA

다시 5 분 동안 허용 된 것으로 표시 할 수 없습니다. :
Ethan Hayon

문제 없어요. 나는 내가 도울 수있어서 기뻤다 !!!
RolandoMySQLDBA

0

mysql 프롬프트에서이 문장을 실행
mysql> show slave status;

슬레이브에서는 많은 매개 변수와 해당 값 / 상태를 표시하고 마스터에서는 빈 세트를 표시합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.