@RolandoMySQLDBA đã trả lời chính xác câu hỏi ... nhưng anh ấy cũng chỉ ra rằng giải pháp của anh ấy là "nhanh và bẩn".
Và đó là một tuyên bố rất đúng. :)
Điều liên quan đến tôi ở đây không phải là với câu trả lời đó, mà là câu hỏi ban đầu dường như đưa ra một giả định không chính xác:
Tôi có thể truy vấn hai máy chủ và hỏi cái nào là chủ, sau đó thực hiện tất cả các truy vấn đến máy chủ đó.
Vấn đề là trong bản sao của MySQL, chủ không bao giờ thực sự biết rằng đó là chủ.
Khái niệm "thăng hạng thành chủ" không thực sự là một khái niệm trong nhân rộng không đồng bộ của MySQL. "Thúc đẩy" máy chủ MySQL lên vai trò chủ là điều gì đó xảy ra "bên ngoài" máy chủ MySQL, trái ngược với điều gì đó xảy ra "bên trong" máy chủ MySQL.
"Khuyến mãi làm chủ" không được thực hiện bởi bất kỳ loại cung cấp máy chủ nào, bởi vì, về mặt kỹ thuật, mọi máy chủ MySQL có bật ghi nhật ký nhị phân đều là chủ, ngay cả khi nó không bao giờ có nô lệ. SHOW MASTER STATUS
hoạt động chính xác theo cùng một cách và trả về chính xác cùng một kết quả, nô lệ hay không, và một chủ có 2 nô lệ không nhiều hơn một chủ so với chủ có 1 nô lệ hoặc 0 nô lệ. Tương tự, một chủ nhân có nô lệ là tất cả ngoại tuyến vẫn giống như một chủ, bởi vì khi những nô lệ trở lại trực tuyến, họ sẽ chọn sao chép nơi họ rời đi.
Theo một nghĩa nào đó, "nhận thức" duy nhất trên một trong hai máy chủ không phải là liệu nó có phải là chủ hay không, mà là, nó có phải là nô lệ (hay "không").
Đó là những gì giải pháp của Rolando hỏi: "bạn có phải là nô lệ không?" Nếu câu trả lời là không, thì giả định rằng đây phải là chủ nhân ... mà ông cũng chỉ ra là một giả định thiếu sót nếu STOP SLAVE;
được ban hành. Nhưng một nô lệ bị dừng lại vẫn là một nô lệ, vì vậy "không phải là nô lệ" (tại bất kỳ thời điểm nào) không đồng nghĩa với việc "trở thành chủ nhân".
Một thử nghiệm tương tự có thể được thực hiện trên tổng thể giả định:
SELECT COUNT(1) FROM information_schema.processlist
WHERE user = 'the_username_used_by_the_slave';
hoặc là
SELECT COUNT(1) FROM information_schema.processlist
WHERE command = 'binlog dump';
Nếu giá trị bằng 0, thì luồng IO của nô lệ không được kết nối. Thử nghiệm này có một khiếm khuyết tương tự, trong đó nếu nô lệ bị ngắt kết nối về mặt hành chính, bị cô lập hoặc thất bại, thì nó sẽ không được kết nối. Vì vậy, điều này cũng không thực sự giải quyết bất cứ điều gì.
Tệ hơn nữa (đối với một trong hai trường hợp này), "bảng" information_schema. Processlist là một bảng ảo được vật chất hóa mỗi khi nó được chọn, và điều này làm mất thời gian và chi phí tài nguyên. Máy chủ của bạn càng bận thì chi phí càng cao, bởi vì mỗi hoạt động của luồng phải được đưa vào.
Một giải pháp nhẹ hơn sẽ là:
SELECT @@global.read_only;
Trên một nô lệ, bạn có thể / nên đặt biến toàn cục read_only
để người dùng không có SUPER
đặc quyền không thể vô tình ghi vào nó (và ứng dụng của bạn không nên có SUPER
). Nếu bạn "quảng bá" thủ công thành vai trò chủ, bạn SET GLOBAL read_only = OFF
cho phép ghi. (Bản sao luôn có thể ghi vào nô lệ, bất kể nó được đặt như thế nào).
Nhưng điều này vẫn còn, tôi nghĩ, bỏ lỡ một điểm quan trọng:
Tôi sẽ đề xuất rằng ứng dụng không nên đưa ra quyết định này một cách tự nhiên trong một thiết lập chủ / nô lệ, và chắc chắn không phải trên cơ sở kết nối theo kết nối. Ứng dụng nên sử dụng tùy chọn cấu hình cứng hoặc ứng dụng sẽ không biết và có đích kết nối cơ sở dữ liệu được xử lý bởi một thứ khác.
Hoặc, tối thiểu, ứng dụng không bao giờ nên chuyển đổi cho đến khi bản gốc bị lỗi, và sau đó nó không bao giờ nên tự bật lại.
Đây là lý do tại sao tôi nói rằng: một khi "quyết định" được đưa ra - bởi bất kỳ ai hay bất cứ điều gì - để biến một máy chủ khác thành chủ, ứng dụng không thể được cho phép vì bất kỳ lý do nào để quay trở lại bản gốc, ngay cả khi nó trở lại trực tuyến , không cần can thiệp.
Giả sử bạn gặp lỗi và có sự cố bắt buộc bằng phần mềm; mysqld_safe
khởi động lại một cách cẩn thận mysqld
và phục hồi sự cố InnoDB thực hiện hoàn hảo. Nhưng điều đó mất một vài phút.
Trong khi đó, chủ bị hỏng nên ứng dụng của bạn đã chuyển sang nô lệ. Giao dịch đã được tạo, đơn đặt hàng, tiền được chuyển, bình luận được đăng, blog được chỉnh sửa, bất cứ hệ thống nào của bạn làm.
Bây giờ, chủ gốc trở lại trực tuyến.
Nếu ứng dụng của bạn quay trở lại bản gốc, bạn đang ở trong một thế giới bị tổn thương tuyệt đối, bởi vì điều tiếp theo rất có thể xảy ra là việc sao chép dừng lại do sự không nhất quán, vì ứng dụng của bạn đã thay đổi dữ liệu về nô lệ. thời gian. Bây giờ bạn có hai máy chủ cơ sở dữ liệu với dữ liệu không nhất quán mà bạn sẽ phải đối chiếu thủ công. Nếu có đô la hoặc điểm hoặc tín dụng liên quan, bây giờ bạn có số dư không khớp.
Vì vậy, điều quan trọng là ứng dụng không được phép chuyển trở lại bản gốc mà không cần sự can thiệp của bạn.
Đợi đã, bạn vừa tìm thấy vấn đề với kịch bản này như tôi đã mô tả? Chủ đã thất bại nhưng ứng dụng của bạn sẽ không sử dụng nô lệ, vì nó nghĩ rằng nô lệ vẫn là nô lệ và không phải là chủ ... information_schema.processlist
truy vấn trên nô lệ vẫn sẽ trả về khác không ngay cả khi máy chủ chính bị tắt .
Vì vậy, không có nhiều điểm trong ứng dụng khám phá bất cứ điều gì, vì bạn sẽ phải làm thủ công STOP SLAVE
để thử nghiệm đó có ích.
Có lẽ một cách tiếp cận tốt hơn nếu bạn muốn ứng dụng có thể chuyển đổi sẽ là cấu hình các máy chủ với bản sao tròn.
Sao chép thông tư có những vấn đề cố hữu của riêng nó, nhưng miễn là ứng dụng của bạn chỉ luôn luôn được ghi vào một máy chủ tại một thời điểm, hầu hết các vấn đề đó đều trở thành vấn đề. Nói cách khác, cả hai máy luôn luôn và đồng thời cả chủ và nô lệ, theo nghĩa nhân rộng, nhưng ứng dụng của bạn, thông qua một số cơ chế, luôn chỉ trỏ đến một máy tại một thời điểm là "chính" mà nó có thể và nên viết .
Bạn không thể triển khai các công cụ HA trên các máy chủ MySQL do sự tách biệt của chúng, nhưng bạn có thể triển khai nó với HAProxy chạy trên (các) máy chủ ứng dụng. Ứng dụng kết nối với "MySQL" trên localhost, hoàn toàn không phải là MySQL, nhưng thực ra là HAProxy ... và nó chuyển tiếp kết nối TCP đến máy MySQL thích hợp.
HAProxy có thể kiểm tra các kết nối đến máy chủ MySQL và chỉ cung cấp lưu lượng truy cập cho máy MySQL đang chấp nhận kết nối và cho phép xác thực.
Sự kết hợp của HAProxy chạy trên máy chủ ứng dụng (nhu cầu tài nguyên của nó sẽ không đáng kể so với mọi thứ khác mà máy chủ ứng dụng phải làm - gần như chỉ buộc các ổ cắm lại với nhau và bỏ qua tải trọng của chúng) ... và sao chép vòng tròn MySQL sẽ là cách tiếp cận mà tôi có thể sẽ thực hiện trong trường hợp này, dựa trên những gì được biết từ câu hỏi.
Hoặc, để thiết lập thủ công nghiêm ngặt, hãy sử dụng một thứ đơn giản hơn nhiều so với "khám phá", như một mục trong /etc/hosts
tệp của máy chủ ứng dụng có tên máy chủ mà ứng dụng sử dụng để kết nối với MySQL, mà bạn có thể cập nhật thủ công - giả sử quảng cáo nô lệ cho chủ được dự định là một quá trình thủ công.
Hoặc, một cái gì đó phức tạp hơn, sử dụng Percona XtraDB Cluster. Tuy nhiên, đối với điều này, bạn muốn thêm máy chủ thứ ba, vì có 3 nút trong PXC, nếu 2 máy chủ có thể nhìn thấy nhau nhưng bị cô lập khỏi 1 máy chủ (nếu cả ba vẫn chạy) thì 2 máy chủ vẫn chạy vui vẻ nhưng 1 máy chủ cuộn tròn thành một quả bóng nhỏ và từ chối làm bất cứ điều gì vì nó nhận ra nó phải là một số lẻ. Điều này hoạt động vì 2 nhận ra rằng chúng vẫn tạo thành phần lớn các nút trực tuyến trước khi chia mạng và 1 nhận ra rằng nó không phải. Với PXC, ứng dụng của bạn kết nối với máy chủ nào thực sự không quan trọng.
Tôi nói tất cả những điều này là để nói "đừng có ứng dụng thăm dò các máy chủ để xem cái nào là chủ" bởi vì nó sẽ cắn bạn sớm hay muộn và nó sẽ ăn sâu vào hiệu suất của bạn cho đến ngày nó cắn.