Ngiêm cấm sử đụng PROXY và VPS vào mục đích trái pháp luật bạn sẽ phải chịu toàn bộ trách nhiệm trước pháp luật khi sử dụng dịch vụ của chúng tôi tks!
ProxySQL: hostgroup, query rule và chia đọc ghi cho MySQL

ProxySQL: hostgroup, query rule và chia đọc ghi cho MySQL

Chuyên viên Kỹ thuật ProxyVN 09-05-2026 Đang tính... phút đọc

ProxySQL là proxy hiểu giao thức MySQL, đứng trước các máy chủ cơ sở dữ liệu và chọn máy trả lời theo từng câu truy vấn. Nó không phải proxy HTTP đổi IP. ProxyVN viết bài này theo tài liệu chính thức, kèm bộ phát lại thứ tự query rule đã chạy thật.

ProxySQL là gì và khác proxy IP thuê ở điểm nào

ProxySQL là phần mềm mã nguồn mở viết bằng C++. Trang kiến trúc của dự án mô tả nó là proxy hiểu sâu giao thức, thiết kế quanh mô hình nhiều luồng và hướng sự kiện. Ban đầu nó dành cho MySQL, nay tài liệu nói rõ nó hỗ trợ cả PostgreSQL bằng các luồng riêng.

Anh em đặt ProxySQL giữa ứng dụng và các máy chủ MySQL. Ứng dụng kết nối tới ProxySQL như kết nối tới một máy chủ MySQL thường. ProxySQL đọc từng câu lệnh, rồi quyết định gửi nó tới máy nào trong số các máy phía sau.

Khác bài PgBouncer ở điểm nào

PgBouncer chủ yếu gom kết nối PostgreSQL và không đọc nội dung truy vấn để định tuyến. ProxySQL làm nhiều hơn: nó phân tích câu lệnh, so với bảng quy tắc, chuyển câu SELECT tới máy đọc, chuyển câu ghi tới máy chính, viết lại câu, lưu đệm kết quả và chặn câu nguy hiểm.

Hai công cụ không loại trừ nhau, và mỗi công cụ đi với một hệ quản trị khác. Bài này chỉ nói về ProxySQL cho MySQL, còn PostgreSQL có bài riêng về PgBouncer.

Không phải proxy HTTP hay SOCKS5 thuê ngoài

Phần lớn bài trên Proxy.vn nói về proxy HTTP và SOCKS5, nơi anh em thuê địa chỉ IP để website đích thấy một vị trí khác. ProxySQL không làm việc đó. Nó nói giao thức MySQL, không đổi IP khi anh em vào website, và không có IP xoay.

Nếu anh em đang quản lý nhiều worker thu thập dữ liệu cùng ghi vào MySQL, ProxySQL giúp gom kết nối và tách đọc ghi ở lớp lưu trữ. Phần lấy trang vẫn đi qua proxy IP như bình thường. Hai lớp này độc lập. Bài định dạng proxy dành cho lớp đầu.

Phạm vi đã thử và chưa thử

ProxySQL chạy trên Linux. Trang cài đặt liệt kê Amazon Linux, Debian, Ubuntu và AlmaLinux, cộng thêm Docker và Kubernetes. Máy mình soạn bài chạy Windows, không có Docker, không có bản phân phối WSL và không có MySQL. Mình không chạy ProxySQL.

Phần mình chạy thật là một script Python phát lại logic chọn hostgroup của bảng query rule theo mô tả trong tài liệu. Script đó không phải ProxySQL, và mình nêu giới hạn của nó ở phần kiểm thử. Mọi thao tác trên giao diện quản trị trong bài đều theo tài liệu, chưa thấy trên máy.

Bản phát hành mới nhất trên trang GitHub của ProxySQL khi mình soạn bài là 3.0.11, ngày 27/08/2026.

Hostgroup và query rule trong ProxySQL cho MySQL

Hai khái niệm này quyết định mọi thứ khác.

Hostgroup là gì

Hostgroup là nhóm máy chủ có cùng chức năng. Tài liệu bảng MySQL định nghĩa: các máy chủ được nhóm vào hostgroup, và một hostgroup là một tập máy có cùng vai trò logic. Mỗi hostgroup có nhóm kết nối riêng tới các máy của nó.

Quy ước thường dùng trong tài liệu hướng dẫn: hostgroup 1 là máy ghi (writer), hostgroup 2 là các máy đọc (reader). Số hiệu do anh em chọn. Một máy có thể thuộc nhiều hostgroup, tài liệu bảng `mysql_servers` ghi rõ điều đó.

Mỗi dòng máy chủ có `status`. Giá trị `ONLINE` là hoạt động bình thường. `SHUNNED` là tạm bị loại vì quá nhiều lỗi kết nối trong thời gian ngắn, hoặc độ trễ sao chép vượt ngưỡng. `OFFLINE_SOFT` ngừng tạo kết nối mới nhưng giữ kết nối đang dùng cho tới khi chúng được trả về. `OFFLINE_HARD` ngừng tạo kết nối mới và bỏ ngay kết nối rảnh, tương đương xóa máy khỏi hostgroup.

Chính `OFFLINE_SOFT` là cách gỡ máy chủ êm nhất khi bảo trì.

Query rule là gì

Bảng `mysql_query_rules` định nghĩa chính sách định tuyến. Mỗi dòng là một quy tắc, có bộ lọc và hành động. Tài liệu bảng liệt kê các cột chính.

  • `rule_id` là mã duy nhất. Các quy tắc được xử lý theo thứ tự `rule_id` tăng dần.
  • `active` bằng 1 thì quy tắc mới được xét và nạp vào runtime.
  • `username` và `schemaname` là bộ lọc theo tài khoản và schema mặc định. Nếu khác rỗng, truy vấn chỉ khớp khi kết nối đúng tài khoản hoặc schema đó.
  • `digest` khớp đúng một chữ ký truy vấn, lấy từ bảng thống kê. `match_digest` là biểu thức chính quy so với digest. `match_pattern` so với nguyên văn câu lệnh.
  • `destination_hostgroup` là nơi gửi truy vấn khớp.
  • `apply` bằng 1 thì dừng xét tiếp và thực thi ngay.
  • `cache_ttl` là thời gian lưu đệm kết quả, tính bằng mili giây. Tài liệu chú thích ở bản 1.1.x đơn vị là giây.
  • `error_msg` chặn truy vấn và trả thông báo cho client.

Tài liệu khuyên dùng `match_digest` thay cho `match_pattern` vì digest nhỏ hơn và khớp nhanh hơn.

Digest là gì

Digest là dạng chuẩn hóa của câu lệnh, trong đó giá trị cụ thể được thay bằng dấu hỏi. Ví dụ `SELECT c FROM sbtest1 WHERE id=?` là digest chung cho mọi câu tìm theo `id`. Ví dụ này lấy từ tài liệu cấu hình lần đầu.

Nhờ digest, hàng nghìn câu khác giá trị gom thành một dòng trong bảng thống kê `stats_mysql_query_digest`. Anh em nhìn bảng đó để biết câu nào tốn thời gian nhất, rồi mới viết quy tắc.

Quy tắc nối chuỗi: flagIN, flagOUT, apply

Ba cột này cho phép tạo chuỗi quy tắc. Truy vấn bắt đầu với cờ bằng 0 và được thử với mọi quy tắc có `flagIN=0`. Nếu một quy tắc khớp và có `flagOUT`, truy vấn được xét lại với các quy tắc có `flagIN` bằng giá trị đó. Nếu quy tắc khớp có `apply=1`, truy vấn được thực thi ngay. Nếu không quy tắc nào khớp, ProxySQL dùng `destination_hostgroup` hoặc `default_hostgroup` của người dùng.

Bài này không dùng chuỗi cờ. Mình chỉ dùng `apply`.

Chuẩn bị lab ProxySQL: topology, phiên bản, listener, backend

Lab gồm một ProxySQL và hai máy MySQL.

Phiên bản và cách cài

Anh em chọn gói theo bản phân phối trên trang cài đặt, hoặc dùng tarball Linux chung. Tarball dùng được khi hệ thống có glibc 2.34 trở lên và OpenSSL 3, theo tài liệu. Docker chạy bằng ảnh trên DockerHub với ánh xạ cổng 6032 và 6033, như ví dụ `docker run -p 16032:6032 -p 16033:6033` trong tài liệu.

Hãy ghi lại phiên bản qua giao diện quản trị khi chạy thật, và đối chiếu tài liệu đúng nhánh. Một số bảng và cột thay đổi theo phiên bản, tài liệu bảng cũng nói danh sách bảng có thể khác nhau tùy bản.

Hai cổng khác nhau

Cổng 6033 cho ứng dụng, cổng 6032 để quản trị

Cổng 6033 cho ứng dụng, cổng 6032 để quản trị

ProxySQL lắng nghe ở hai nơi. Cổng quản trị 6032 dùng giao thức MySQL để anh em cấu hình. Cổng cho ứng dụng là 6033 theo ví dụ cấu hình trong tài liệu cài đặt (`interfaces="0.0.0.0:6033"`).

Ứng dụng kết nối cổng 6033. Anh em quản trị qua cổng 6032. Nhầm hai cổng là lỗi đầu tiên người mới gặp: gõ lệnh `INSERT INTO mysql_servers` vào cổng 6033 sẽ bị coi là một câu SQL gửi cho MySQL.

Backend của lab

Hai máy MySQL, `mysql-a` với `server_id=1` đặt làm máy chính, `mysql-b` với `server_id=2` đặt `read_only=1` làm máy đọc. Tài liệu cấu hình lần đầu dặn: đặt `read_only=0` ở máy chính và `read_only=1` ở bản sao, vì ProxySQL dùng giá trị này để quyết định định tuyến.

Mình không dựng sao chép giữa hai máy. Mục tiêu của lab là xem truy vấn đi tới máy nào, và mỗi máy tự báo `server_id` của nó. Dữ liệu trên hai máy không cần giống nhau. Nếu anh em muốn thử độ trễ sao chép, lúc đó mới cần dựng sao chép thật.

Tài khoản cần có

Cần ba loại tài khoản. Tài khoản ứng dụng `app` tồn tại trên cả hai máy MySQL. Tài khoản giám sát `monitor` có quyền `USAGE` và `REPLICATION CLIENT`, theo tài liệu. Tài khoản quản trị ProxySQL, mặc định trong ví dụ cài đặt là `admin:admin`, và anh em phải đổi.

Cấu hình ProxySQL tối thiểu, quyền truy cập và các tuyến cần kiểm tra

Mọi lệnh dưới đây chạy trong giao diện quản trị. Kết nối bằng lệnh mà tài liệu đưa ra.

mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt 'ProxySQL Admin> '

Khai báo máy chủ và hostgroup

INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'10.0.0.11',3306);
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (2,'10.0.0.12',3306);
INSERT INTO mysql_replication_hostgroups (writer_hostgroup,reader_hostgroup,comment)
 VALUES (1,2,'lab');
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

Tài liệu giải thích: với `mysql_replication_hostgroups`, ProxySQL tự chuyển máy giữa hai hostgroup theo `read_only`. Máy có `read_only=0` vào hostgroup 1, máy có `read_only=1` vào hostgroup 2.

Giám sát

UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username';
UPDATE global_variables SET variable_value='MAT_KHAU_MONITOR' WHERE variable_name='mysql-monitor_password';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

Module giám sát chạy bốn loại kiểm tra: kết nối, ping, độ trễ sao chép và `read_only`. Kết quả ghi vào các bảng trong schema `monitor`, như `mysql_server_connect_log` và `mysql_server_ping_log`. Tài liệu cho ví dụ đặt khoảng kiểm tra 2000 mili giây.

Người dùng

INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('app','MAT_KHAU_APP',1);
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

Cột `default_hostgroup` quyết định nơi truy vấn đi khi không có quy tắc nào khớp. Ở đây là hostgroup 1, tức máy chính. Đây là cách an toàn: mặc định mọi thứ về máy chính, chỉ những câu được chứng minh là đọc an toàn mới sang máy đọc.

Bảng `mysql_users`, theo tài liệu quản lý người dùng, có cột `frontend` và `backend`. Tài khoản `frontend=1` được đăng nhập vào ProxySQL. Tài khoản `backend=1` là thông tin ProxySQL dùng để kết nối tới MySQL. Cả hai thường bằng 1 cho đơn giản. Cột `max_connections` giới hạn số phiên đồng thời của tài khoản.

Cột `transaction_persistent`, khi bằng 1, giữ mọi câu trong một transaction trên cùng máy chủ. Tài liệu ghi điều này quan trọng để giữ nhất quán khi ghi. Cột `fast_forward` bằng 1 cho phép bỏ qua bộ xử lý truy vấn với tài khoản đó, nghĩa là quy tắc không áp dụng.

Hai quy tắc chia đọc ghi

INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply)
VALUES (1,1,'^SELECT.*FOR UPDATE',1,1),
       (2,1,'^SELECT',2,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

Hai quy tắc này lấy từ hướng dẫn chia đọc ghi, tùy chọn thứ hai. Quy tắc 1 gửi câu `SELECT ... FOR UPDATE` về máy chính vì nó khóa dòng. Quy tắc 2 gửi các SELECT còn lại tới máy đọc.

Chính tài liệu cảnh báo ngay sau ví dụ đó: quy tắc SELECT tổng quát gây vấn đề với transaction, trạng thái phiên và tính nhất quán. Cách khuyến nghị là tùy chọn thứ ba, định tuyến theo phân tích truy vấn.

Cách khuyến nghị: từ máy chính, rồi chọn lọc

Tài liệu khuyên đi theo bốn bước. Gửi mọi thứ về máy chính trước. Phân tích `stats_mysql_query_digest` để tìm các SELECT tốn kém. Xác định câu nào chạy được trên bản sao mà không sai kết quả. Rồi thêm quy tắc cho từng câu.

Quy tắc có thể nhắm đúng một digest bằng cột `digest`, hoặc một nhóm bằng `match_digest`, như `^SELECT COUNT\(\*\)` để gửi các câu đếm sang máy đọc. Tài liệu kèm sẵn các truy vấn xếp hạng theo tổng thời gian, theo số lần gọi và theo thời gian tối đa.

Cấu hình theo cổng

Tùy chọn đầu tiên trong tài liệu là định tuyến theo cổng. ProxySQL nghe hai cổng, ví dụ `SET mysql-interfaces='0.0.0.0:6401;0.0.0.0:6402';`, rồi hai quy tắc dùng cột `proxy_port` gửi cổng 6401 về hostgroup 1 và cổng 6402 về hostgroup 2. Hạn chế: ứng dụng phải tự biết đâu là đọc, đâu là ghi và nối vào đúng cổng.

Tùy chọn này đổi `mysql-interfaces` nên cần `PROXYSQL RESTART`, theo tài liệu.

Hệ thống cấu hình nhiều lớp của ProxySQL: memory, runtime, disk

Điểm hay làm người mới mất thời gian: gõ xong lệnh mà không thấy gì thay đổi.

Bốn lớp

Bốn lớp cấu hình: file, disk, memory, runtime

Bốn lớp cấu hình: file, disk, memory, runtime

Tài liệu hệ thống nhiều lớp mô tả bốn lớp cấu hình. RUNTIME là cấu trúc dữ liệu mà các luồng xử lý đang dùng. Chỉ lớp này ảnh hưởng hành vi thật của proxy. Anh em chỉ đọc nó qua các bảng `runtime_`, và chỉ đổi bằng lệnh `LOAD ... TO RUNTIME`.

MEMORY là cơ sở dữ liệu SQLite trong bộ nhớ, giao diện chính để anh em dùng `INSERT`, `UPDATE`, `DELETE`. Thay đổi ở đây không bền, mất khi khởi động lại nếu chưa lưu.

DISK là tệp SQLite trên ổ cứng, thường là `proxysql.db`. Chỉ đổi bằng `SAVE ... TO DISK`. Khi khởi động, ProxySQL nạp MEMORY từ DISK.

CONFIG FILE là tệp `proxysql.cnf`, dùng chủ yếu cho lần khởi tạo đầu. Nó chỉ ghi đè DISK khi khởi động với cờ `--initial` hoặc `--reload`.

Quy trình ba bước

Mỗi lần đổi cấu hình, làm ba việc: sửa MEMORY bằng SQL, đẩy sang RUNTIME bằng `LOAD ... TO RUNTIME` để có hiệu lực, rồi đẩy sang DISK bằng `SAVE ... TO DISK` để bền.

Quên bước thứ hai là nguyên nhân số một của câu hỏi "tôi thêm quy tắc rồi mà không chạy". Quên bước thứ ba là nguyên nhân của "sau khi khởi động lại, quy tắc biến mất".

Muốn quay lại trạng thái đã lưu, dùng `LOAD ... FROM DISK`. Muốn xem trạng thái runtime, dùng `SAVE ... TO MEMORY` để sao ngược nó vào SQLite rồi đọc.

Quên LOAD là lỗi dễ kiểm tra nhất

So sánh hai bảng `mysql_query_rules` và `runtime_mysql_query_rules`. Nếu bảng đầu có quy tắc mà bảng sau không, anh em chưa chạy `LOAD MYSQL QUERY RULES TO RUNTIME`. Đó là phép kiểm tra rẻ nhất trước khi nghi ngờ regex.

Chạy ca đúng và sai với ProxySQL, đọc stats và log

Phần này gồm bộ phát lại mình đã chạy và kịch bản anh em chạy khi có lab.

Bộ phát lại thứ tự quy tắc

Đảo rule_id làm câu FOR UPDATE sang máy đọc

Đảo rule_id làm câu FOR UPDATE sang máy đọc

Mình viết `mo_phong_query_rules.py`. Script đọc một danh sách quy tắc và danh sách truy vấn, rồi in hostgroup mà mỗi truy vấn sẽ đi tới theo mô tả trong tài liệu. Quy tắc được xét theo `rule_id` tăng dần và chỉ khi `active`. Script lọc `username`, coi `match_digest` là biểu thức chính quy không phân biệt hoa thường, dừng ngay khi gặp `apply=1`, và dùng `default_hostgroup` nếu không quy tắc nào khớp.

Giới hạn cần nói thẳng. Script không phải ProxySQL. Nó nhận đầu vào đã là digest có dấu hỏi, nên không kiểm chứng cách ProxySQL tự chuẩn hóa câu lệnh. Nó bỏ qua `flagIN`, `flagOUT`, `transaction_persistent` và multiplexing. Giá trị của nó là cho anh em thấy ảnh hưởng của thứ tự quy tắc trước khi nạp lên máy chủ.

Mình chạy với năm digest và hai bộ quy tắc, cùng tài khoản `app` có `default_hostgroup=1`.

Bảng: Bộ phát lại thứ tự quy tắc

Digest

Bộ đúng (FOR UPDATE xét trước)

Bộ sai (^SELECT xét trước)

`SELECT c FROM sbtest1 WHERE id=?`

hostgroup 2, quy tắc 2

hostgroup 2, quy tắc 1

`SELECT * FROM don_hang WHERE id=? FOR UPDATE`

hostgroup 1, quy tắc 1

hostgroup 2, quy tắc 1 (sai)

`UPDATE don_hang SET trang_thai=? WHERE id=?`

hostgroup 1, mặc định

hostgroup 1, mặc định

`INSERT INTO nhat_ky(noi_dung) VALUES(?)`

hostgroup 1, mặc định

hostgroup 1, mặc định

`SELECT COUNT(*) FROM don_hang`

hostgroup 2, quy tắc 2

hostgroup 2, quy tắc 1

Chỉ khác biệt duy nhất nằm ở câu `FOR UPDATE`. Khi đảo `rule_id` của hai quy tắc, quy tắc `^SELECT` khớp trước và có `apply=1`, nên câu khóa dòng bị gửi sang máy đọc. Việc khóa dòng khi đó diễn ra trên bản sao thay vì máy chính, nên mục đích của `FOR UPDATE` mất đi. Lỗi này không hiện trên tệp cấu hình, chỉ hiện khi chạy.

Đây là điều tài liệu nói bằng câu "quy tắc được xử lý theo thứ tự `rule_id`". Script chỉ làm nó nhìn thấy được.

Kịch bản kiểm tra khi có lab

Mỗi máy MySQL tự báo `server_id` của nó, nên dùng câu hỏi đó làm dấu.

mysql -h127.0.0.1 -P6033 -uapp -p -e "SELECT @@server_id"
mysql -h127.0.0.1 -P6033 -uapp -p -e "BEGIN; SELECT id FROM don_hang LIMIT 1 FOR UPDATE; SELECT @@server_id; COMMIT"
mysql -h127.0.0.1 -P6033 -uapp -p -e "UPDATE don_hang SET trang_thai='thu' WHERE id=1"
Bảng: Kịch bản kiểm tra khi có lab

Ca

Mong đợi theo tài liệu

`SELECT @@server_id`

Khớp `^SELECT`, đi hostgroup 2, trả `server_id` của máy đọc

`FOR UPDATE` trong transaction

Khớp quy tắc 1, đi hostgroup 1

`UPDATE`

Không quy tắc nào khớp, đi `default_hostgroup` 1

Cột "mong đợi" là suy ra từ tài liệu và logic của bộ phát lại. Mình chưa thấy kết quả thật.

Đọc bảng thống kê

Sau khi chạy các ca, đọc `stats_mysql_query_digest` để xem mỗi digest đã đi hostgroup nào. Tài liệu có truy vấn tổng hợp theo hostgroup: tổng thời gian và số lần gọi gom nhóm theo cột `hostgroup`. Kết quả lưu đệm hiện với `hostgroup = -1`.

Bảng `stats_mysql_connection_pool` cho số liệu kết nối và lưu lượng theo từng hostgroup. Bảng `stats_mysql_commands_counters` cho phân bố loại truy vấn và thời gian thực thi.

Thử loại máy ra

Tắt máy đọc rồi xem log giám sát. Hai bảng cần đọc là `monitor.mysql_server_connect_log` và `monitor.mysql_server_ping_log`. Trạng thái trong `mysql_servers` có thể chuyển `SHUNNED` khi quá nhiều lỗi trong thời gian ngắn, theo mô tả của tài liệu. Nếu máy đọc duy nhất bị loại, các câu SELECT khớp quy tắc 2 phụ thuộc vào cách anh em cấu hình tiếp. Mình không có đoạn tài liệu nào để khẳng định ProxySQL làm gì ở trường hợp này, nên anh em tự thử trước khi tin vào một hành vi.

Chi tiết này mình để trống có chủ ý. Mình không đưa số giây cụ thể cho thời điểm bị loại, vì nó phụ thuộc biến giám sát mà mình chưa đo.

Đưa ProxySQL vào hệ thống thật: hoàn nguyên, giới hạn, bảo mật

Checklist trước khi đưa ProxySQL vào hệ thống thật

Checklist trước khi đưa ProxySQL vào hệ thống thật

Lab chạy được chưa phải điều kiện đủ.

Hoàn nguyên

Trước khi sửa lớn, hãy xuất nội dung các bảng ra tệp SQL để có đường lui độc lập với `proxysql.db`. Quay lại cấu hình cũ bằng lệnh `LOAD ... FROM DISK` nếu anh em chưa chạy `SAVE ... TO DISK` cho thay đổi lỗi. Nếu đã lưu, sửa lại bảng và chạy lại ba bước. Một thói quen tốt là chép lại tệp `proxysql.db` trước khi sửa lớn.

Gỡ một máy chủ êm bằng cách đặt `OFFLINE_SOFT`, đợi kết nối đang dùng được trả về, rồi mới xóa. Gỡ ngay thì dùng `OFFLINE_HARD`, và phiên đang gắn với máy đó sẽ bị cắt khi client dùng tới.

Giới hạn tài nguyên

Cột `max_connections` của `mysql_servers` mặc định 1000, và `max_connections` của người dùng giới hạn phiên của từng tài khoản. Hãy đặt chúng thấp hơn giới hạn của MySQL phía sau, để ProxySQL không đẩy MySQL tới ngưỡng `max_connections` của chính nó.

Mình không đo CPU hay RAM của ProxySQL nên không đưa số nào. Hãy đo bằng tải thật. Bài đo tải proxy nói về cách nghĩ chung khi đo, dù áp dụng cho proxy HTTP.

Bảo mật

Ví dụ cài đặt trong tài liệu có tài khoản quản trị `admin:admin` và `radmin:radmin`, trong đó `radmin` dùng khi kết nối từ ngoài container. Đừng giữ mật khẩu mặc định. Cổng quản trị 6032 chỉ nên mở cho máy quản trị.

Cấu hình ví dụ nghe `0.0.0.0:6033`, tức mọi địa chỉ. Hãy giới hạn bằng tường lửa hoặc đổi địa chỉ nghe. Tài liệu bảng người dùng cũng ghi chú tài khoản trong `mysql_users` không nên dùng chung cho `admin-admin_credentials`.

ProxySQL thấy toàn bộ truy vấn và mật khẩu kết nối backend, nên máy chạy nó cần bảo vệ như máy cơ sở dữ liệu. Cột `use_ssl` ở `mysql_users` và `mysql_servers` bật mã hóa tới backend. Nếu muốn hiểu thêm về lớp mã hóa trên proxy nói chung, xem bài proxy SSL là gì.

Lưu đệm kết quả

Đặt `cache_ttl` lên quy tắc để ProxySQL trả kết quả từ bộ nhớ trong mili giây đã định. Nó giảm tải đọc, nhưng người dùng có thể thấy dữ liệu cũ tới hết thời hạn. Chỉ cache các truy vấn chấp nhận dữ liệu cũ. Khái niệm này giống bài proxy caching ở lớp HTTP, chỉ khác lớp.

Ghi chép khi thử

Khi chạy lab thật, anh em nên lưu lại ba thứ: phiên bản ProxySQL và MySQL, nội dung các bảng `runtime_mysql_servers` và `runtime_mysql_query_rules` tại thời điểm thử, và kết quả `server_id` của từng ca. Ba thứ này đủ để người khác tái hiện lại kết quả mà không phải hỏi lại anh em từng bước một. Nếu kết quả khác với bảng mong đợi trong bài, hãy tin kết quả thật và sửa tài liệu nội bộ theo nó, đừng sửa kết quả cho khớp tài liệu.

Khi nào nên cân nhắc ProxySQL

Nếu chỉ có một máy MySQL và vài kết nối, ProxySQL thêm một thành phần phải vận hành mà không đem lại nhiều. Nó đáng giá khi có nhiều máy, cần chia đọc ghi, cần chặn hay viết lại truy vấn mà không sửa mã, hoặc cần gom kết nối rất nhiều client. Với định tuyến TCP đơn giản mà không cần hiểu SQL, HAProxy nhẹ hơn. Cho phần dự phòng của proxy IP, xem proxy failover.

Câu hỏi thường gặp về ProxySQL

ProxySQL có chạy trên Windows không. Trang cài đặt chỉ liệt kê các bản Linux, Docker và Kubernetes. Trên Windows, cách thực tế là chạy trong máy ảo Linux hoặc container. Mình chưa thử.

ProxySQL có đổi IP khi vào website không. Không. Nó nói giao thức MySQL và PostgreSQL. Muốn đổi IP khi truy cập website, anh em dùng proxy HTTP hoặc SOCKS5.

Tôi thêm quy tắc mà không chạy. Kiểm tra `runtime_mysql_query_rules`. Nếu quy tắc chưa ở đó, chạy `LOAD MYSQL QUERY RULES TO RUNTIME`. Rồi kiểm tra `active=1`, đúng `username`, và thứ tự `rule_id`.

Truy vấn trong transaction có bị chia sang máy đọc không. Tài liệu ghi `destination_hostgroup` không áp dụng khi đã bắt đầu transaction và tài khoản có `transaction_persistent=1`. Hãy bật cột này cho tài khoản ứng dụng khi dùng chia đọc ghi.

Có nên viết quy tắc `^SELECT` cho mọi SELECT không. Tài liệu cảnh báo cách này gây vấn đề với transaction, trạng thái phiên và nhất quán. Hãy bắt đầu từ máy chính rồi chọn từng digest.

Khác gì giữa `match_digest` và `match_pattern`. `match_digest` so với dạng chuẩn hóa, nhỏ và nhanh. `match_pattern` so với nguyên văn câu. Tài liệu khuyên dùng `match_digest` khi có thể. Khi dùng `replace_pattern` thì bắt buộc có `match_pattern`.

Tại sao `SELECT @@server_id` đi sang máy đọc. Vì nó khớp `^SELECT`. Kiểu câu hỏi tham số hệ thống này thường cũng vô hại ở máy đọc, nhưng các câu `SELECT` gọi hàm có tác dụng phụ thì không, và đó là lý do cần xem digest trước khi gửi.

Nếu cần thêm IP, anh em có thể mua proxy tại ProxyVN, có proxy dân cư tĩnh Viettel, VNPT, FPT, datacenter Việt Nam và proxy xoay, hỗ trợ HTTP và SOCKS5 với tài khoản user và mật khẩu.

ProxySQL: những điều cần nhớ

ProxySQL định tuyến MySQL theo hostgroup và query rule xét từ rule_id nhỏ tới lớn, nên thứ tự quyết định kết quả. Sau mỗi thay đổi nhớ LOAD vào RUNTIME rồi SAVE xuống DISK. Cần proxy IP ổn định cho việc khác, liên hệ Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam cho ProxySQL.

TIN TỨC LIÊN QUAN