Để thực hiện những gì bạn muốn làm, có thể sử dụng FEDERATED
công cụ lưu trữ trên cả hai máy chủ, kết hợp với trình kích hoạt, để cho phép mỗi máy chủ cập nhật cơ sở dữ liệu của máy chủ khác.
Đây không chính xác là một giải pháp bên ngoài đơn giản, bởi vì nó yêu cầu các biện pháp phòng ngừa bổ sung và yêu cầu bạn quyết định xem tính nhất quán hay dung sai cách ly là quan trọng hơn và cho phép các truy vấn thất bại khi máy chủ khác không khả dụng (tính nhất quán cao hơn ) hoặc sử dụng a CONTINUE HANDLER
để triệt tiêu lỗi (dung sai cách ly).
Nhưng đây là một ví dụ cực kỳ đơn giản.
Mỗi máy chủ sẽ có cấu hình giống hệt nhau.
Bảng người dùng cục bộ:
CREATE TABLE user (
username varchar(64) NOT NULL,
password varbinary(48) NOT NULL, /* encrypted of course */
PRIMARY KEY(username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Một bảng cục bộ được liên kết với bảng người dùng trên máy chủ khác.
CREATE TABLE remote_user (
username varchar(64) NOT NULL,
password varbinary(48) NOT NULL, /* encrypted of course */
PRIMARY KEY(username)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8 CONNECTION='mysql://username:pass@the_other_host:port/schema/user';
Chọn từ remote_user trên một máy chủ sẽ truy xuất các bản ghi từ máy chủ khác và chèn / cập nhật / xóa trên bảng đó sẽ thay đổi dữ liệu trên máy chủ khác.
Vì vậy, chúng tôi tạo ra các kích hoạt thực hiện mục đích cập nhật máy chủ khoảng cách. Chúng được viết dưới dạng BEFORE
kích hoạt, với ý tưởng là chúng ta không muốn làm gì đó với chính mình mà chúng ta không thể làm với máy chủ khác - ví dụ: nếu tên người dùng đã tồn tại trên máy chủ khác, nhưng không phải ở đây, chúng tôi muốn chèn vào máy chủ khác để đưa ra lỗi ngăn chúng tôi tạo người dùng ở đây ... trái ngược với việc tạo người dùng ở đây với tên người dùng mâu thuẫn. Tất nhiên, đây là một trong những quyết định đánh đổi mà bạn cần đưa ra.
DELIMITER $$
CREATE TRIGGER user_bi BEFORE INSERT ON user FOR EACH ROW
BEGIN
INSERT INTO remote_user (username,password) VALUES (NEW.username,NEW.password);
END $$
CREATE TRIGGER user_bu BEFORE UPDATE ON user FOR EACH ROW
BEGIN
UPDATE remote_user
SET username = NEW.username,
password = NEW.password
WHERE username = OLD.username;
END $$
CREATE TRIGGER user_bd BEFORE DELETE ON user FOR EACH ROW
BEGIN
DELETE FROM remote_user
WHERE username = OLD.username;
END $$
DELIMITER ;
Đây không phải là một giải pháp hoàn hảo và không phải là một giải pháp có tính sẵn sàng cao, bởi vì nó phụ thuộc vào kết nối chắc chắn giữa hai hệ thống và ngay cả khi bạn đang sử dụng InnoDB và các giao dịch, các hành động bạn thực hiện đối với bảng mục tiêu không phải là một phần của giao dịch cục bộ của bạn và không thể quay trở lại.
Tôi sử dụng FEDERATED
động cơ khá nhiều; nó có ích cho một số mục đích sáng tạo trong môi trường của tôi, bao gồm một tình huống trong đó tôi đã sử dụng truy vấn được liên kết do trình kích hoạt đưa ra để áp đặt các ràng buộc khóa ngoài đối với nguồn dữ liệu nước ngoài; tuy nhiên, tôi hạn chế sử dụng nó cho các quy trình back-end trong đó các sự cố không mong muốn như hết thời gian, lỗi mã hóa hoặc các sự kiện cách ly / ngắt mạng / máy chủ đến máy chủ không thể dẫn đến việc người dùng cuối trên một trong các trang web của chúng tôi gặp phải bất kỳ sự cố nào . Khả năng của bạn để chịu đựng một tình huống như vậy sẽ là một yếu tố quyết định chính vào việc liệu đây có phải là một giải pháp thích hợp.
Một cách khác là cấu hình hai máy chủ của bạn theo bản sao chính / chính. Đối với điều này, bạn sẽ cần sử dụng các tên cơ sở dữ liệu khác nhau trên mỗi máy chủ, do đó, đối với hầu hết các sự kiện sao chép, hai máy chủ không thể xung đột với nhau. Trong trường hợp xấu nhất, nếu bạn mất kết nối hoặc gặp lỗi sao chép, hai trang web vẫn sẽ hoạt động độc lập và bạn có thể đồng bộ hóa và khôi phục. Cấu hình sẽ trông giống như thế này:
database_a database for site A
database_b database for site B
database_c database for only the shared table(s)
Sau đó, trong cơ sở dữ liệu_a và cơ sở dữ liệu_b:
CREATE ALGORITHM=MERGE SQL SECURITY INVOKER VIEW user AS SELECT * FROM c.user;
MySQL sẽ coi cơ sở dữ liệu_a.user và cơ sở dữ liệu_b.user là bí danh cho bảng người dùng "thực", cơ sở dữ liệu_cuser, do đó bạn sẽ không phải thay đổi ứng dụng của mình ngoài việc sử dụng cơ sở dữ liệu được chỉ định của nó (nghĩa là bạn sẽ không phải định cấu hình để hiểu rằng bảng người dùng thực sự nằm trong một lược đồ khác, bởi vì khung nhìn sẽ hoạt động khá rõ ràng với cấu hình này). Nếu các lược đồ có khóa ngoại đối với bảng người dùng, bạn sẽ khai báo chúng dựa trên cơ sở dữ liệu bảng cơ sở thực sự_c.user.
Định cấu hình hai máy chủ để sao chép mọi thứ, nhưng đặt auto_increment_increment
và auto_increment_offset
thích hợp để bạn không có các giá trị tăng tự động xung đột trên (các) bảng được chia sẻ, nếu các bảng của bạn sử dụng tự động tăng. (Lưu ý, tài liệu nói rằng các biến này chỉ dành cho NDB
bảng, nhưng điều đó không chính xác).
Một lợi thế nữa của thiết lập này là hai máy chủ của bạn sau đó sẽ có một bản sao hoàn chỉnh của dữ liệu của trang web khác mà bạn có thể sử dụng để tạo lợi thế cho việc phục hồi từ lỗi phần cứng ở một trong các máy chủ.