Làm thế nào để xác định chủ trong mysql master-Slave


17

Tôi đang thiết lập bản sao MySQL Master-Slave và tôi đang cố gắng tìm ra cách xử lý tình huống chuyển đổi dự phòng nơi tôi quảng bá nô lệ thành chủ (trong trường hợp chủ bị hỏng).

Máy chủ ứng dụng của tôi cần hướng tất cả ghi vào máy chủ hiện tại, nhưng tôi không thể sử dụng HA cấp máy chủ giữa máy chủ và máy chủ (nhịp tim, giữ nguyên) vì hai máy chủ db nằm trên các mạng con hoàn toàn khác nhau ở các vị trí vật lý khác nhau.

Tôi nghĩ rằng đây là điều mà tôi cần xử lý ở cấp ứng dụng. 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ủ đó.

Có một truy vấn trong MySQL để xem liệu máy chủ hiện tại có phải là bản chính trong bản sao chính-phụ không?


Bạn đang sử dụng phiên bản MySQL nào ???
RolandoMySQLDBA

Đây là đầu ra của mysqlServer version: 5.5.23 MySQL Community Server (GPL)
Ethan Hayon

Câu trả lời:


13

@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 STATUShoạ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 = OFFcho 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_safekhởi động lại một cách cẩn thận mysqldvà 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.processlisttruy 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/hoststệ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.


Trước hết, cảm ơn bạn đã phản hồi bằng văn bản. Tôi nghĩ rằng bạn đã đề xuất một giải pháp tốt. Tôi đã nghĩ về việc sử dụng sao chép vòng tròn trong quá khứ, nhưng đã đọc những điều xấu liên quan đến độ tin cậy của nó. Tuy nhiên, phần lớn các vấn đề này có thể được ngăn chặn bằng cách sửa đổi auto_increment_increment, auto_increment_offset, v.v ... Sử dụng HAProxy cục bộ trên các máy chủ ứng dụng (chỉ là chuyển đổi dự phòng) sẽ hoạt động tốt với chúng tôi vì chúng tôi sẽ không phải sửa đổi ứng dụng của mình logic ra khỏi lớp ứng dụng. Tôi sẽ xem xét cấu hình HAProxy, cảm ơn!
Ethan Hayon

1
Vui mừng được giúp đỡ. Một cuộc bỏ phiếu sẽ được đánh giá cao nếu bạn chưa có. Sao chép tròn cũng đáng tin cậy như chủ / nô lệ (đó là cùng một công nghệ, chỉ đi theo cả hai hướng) miễn là bạn hiểu cách thức hoạt động của nó và sử dụng nó một cách hợp lý. Miễn là các máy chủ được đồng bộ hóa đúng cách và ứng dụng chỉ ghi vào một máy chủ tại một thời điểm, tôi chưa bao giờ gặp sự cố với nó. Các auto_increment_*biến vẫn tốt để sử dụng trong kịch bản này, "chỉ trong trường hợp." Ngoài ra, hãy nhớ sử dụng binlog_format= rowhoặc mixed- không statement(ngay cả khi bạn không thực hiện thông tư).
Michael - sqlbot

Tôi đã thay đổi câu trả lời được chấp nhận hoàn toàn vì lời giải thích chi tiết này đã giúp tôi tái kiến ​​trúc hệ thống trở nên mạnh mẽ hơn. Câu trả lời của @ RolandoMySQLDBA vẫn đúng và giải quyết vấn đề tôi mô tả ban đầu. Cảm ơn!
Ethan Hayon

10

Nếu bạn chỉ sử dụng Master / Slave, đây là một cái gì đó nhanh và bẩn:

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

Thứ này nói lên điều gì?

  • Nếu SlaveThreadCount= 0, bạn có Master
  • Nếu SlaveThreadCount> 0, bạn có Slave

CAVEAT : Điều này hoạt động miễn là bạn không chạySTOP SLAVE;

Một điều khác để thử là: Nếu bạn vô hiệu hóa ghi nhật ký nhị phân trên Slave và bạn chạy SHOW MASTER STATUS;, Master sẽ cung cấp cho bạn nhật ký nhị phân hiện tại. Slave cho bạn không có gì.


Tuyệt vời, đây chính xác là những gì tôi cần. Bạn có nghĩ rằng đây là một giải pháp lộn xộn cho vấn đề? Vấn đề duy nhất tôi có thể hình dung là cả hai máy chủ đều được thăng cấp thành chủ, nhưng điều đó không bao giờ thực sự xảy ra.
Ethan Hayon

Nếu câu trả lời này là những gì bạn cần, vui lòng đánh dấu câu trả lời được chấp nhận bằng cách nhấp vào dấu chọn trên câu trả lời của tôi.
RolandoMySQLDBA

Tôi không thể đánh dấu nó là được chấp nhận trong 5 phút nữa :)
Ethan Hayon

Không vấn đề gì. Tôi rất vui vì tôi có thể giúp !!!
RolandoMySQLDBA

0

thực hiện câu lệnh này từ mysql prompt
mysql> hiển thị trạng thái nô lệ;

Trên nô lệ, nó hiển thị rất nhiều tham số và giá trị / trạng thái của chúng trong khi ở chế độ chính, nó hiển thị Tập rỗng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.