@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를 사용하면 응용 프로그램이 어떤 서버에 연결되어 있는지는 중요하지 않습니다.
나는이 모든 것이 "응용 프로그램이 어느 서버가 마스터인지 확인하기 위해 서버를 폴링하지 말아야한다"고 말하고 싶다고 말합니다. 왜냐하면 그것은 당신을 물게 될 것이고 물린 날까지 성능을 떨어 뜨릴 것이기 때문입니다.