Apache Derby Bài 26: Quản lý đa kết nối đồng thời trong Network Server Mode
1. Kiến trúc đa luồng (Multi-threading) của Derby
Khi chạy ở chế độ Network Server, Apache Derby hoạt động giống như một máy chủ web. Mỗi khi một ứng dụng khách (Client) gọi lệnh DriverManager.getConnection(), máy chủ Derby sẽ tiếp nhận kết nối qua cổng TCP/IP (mặc định 1527) và sinh ra một luồng (Thread) mới bên trong JVM để chuyên phục vụ phiên làm việc đó.
Nhờ kiến trúc này, Derby có thể xử lý đồng thời hàng chục, thậm chí hàng trăm yêu cầu từ các client khác nhau (như DBeaver, ứng dụng Web Spring Boot, các máy trạm POS) mà không làm gián đoạn lẫn nhau. Tuy nhiên, tài nguyên của máy chủ (CPU, RAM) là có giới hạn, do đó việc quản lý số lượng luồng kết nối là bài toán bắt buộc trong môi trường Production.
2. Cấu hình giới hạn số lượng luồng truy cập
Theo mặc định, Derby Network Server không giới hạn số lượng kết nối tối đa. Máy chủ sẽ liên tục tạo luồng mới cho đến khi hệ điều hành cạn kiệt bộ nhớ và văng lỗi OutOfMemoryError.
Để bảo vệ máy chủ, bạn cần giới hạn số lượng luồng xử lý thông qua tệp derby.properties (đã học ở Bài 23):
Properties
# Giới hạn máy chủ chỉ phục vụ tối đa 50 kết nối đồng thời
derby.drda.maxThreads=50
# Thời gian tối đa (tính bằng mili-giây) một luồng được phép chiếm dụng CPU
# trước khi nhường quyền xử lý cho luồng khác. Mặc định là 0 (không chia sẻ thời gian).
derby.drda.timeSlice=1000
Kịch bản khi đạt giới hạn: Nếu bạn đặt maxThreads=50, khi kết nối thứ 51 gửi tới, máy chủ không từ chối ngay lập tức. Cảnh báo sẽ được ghi vào derby.log và luồng thứ 51 sẽ phải xếp hàng chờ cho đến khi một trong 50 luồng trước đó đóng kết nối (gọi conn.close()).
3. Bài toán chi phí khởi tạo kết nối mạng
Trong mã nguồn Java, hành động mở kết nối qua mạng là một thao tác cực kỳ đắt đỏ về mặt tài nguyên hệ thống và thời gian, bao gồm:
-
Thực hiện quá trình bắt tay TCP 3 bước (TCP 3-way handshake).
-
Trao đổi thông điệp xác thực qua giao thức DRDA.
-
Derby Engine khởi tạo vùng nhớ đệm, cấp phát ID cho Session.
Lỗi thiết kế (Anti-pattern) phổ biến:
Java
// KHÔNG NÊN LÀM: Mở và đóng kết nối liên tục trong vòng lặp
for (int i = 0; i < 1000; i++) {
Connection conn = DriverManager.getConnection("jdbc:derby://localhost:1527/db");
// Thực thi SQL...
conn.close();
}
Đoạn mã trên sẽ vắt kiệt CPU của máy chủ Derby chỉ để phục vụ quá trình mở/đóng kết nối, làm sụt giảm nghiêm trọng hiệu năng thực thi SQL.
Giải pháp: Mọi ứng dụng thực tế khi kết nối tới Network Server đều phải sử dụng cơ chế Connection Pool (Hồ chứa kết nối) như HikariCP hoặc Apache DBCP. Thay vì đóng kết nối, Connection Pool giữ các kết nối TCP luôn mở và tái sử dụng chúng cho các yêu cầu tiếp theo. (Chúng ta sẽ cấu hình chi tiết HikariCP ở Bài 40).
4. Giám sát các giao dịch và khóa đang hoạt động
Để biết hiện tại có bao nhiêu luồng đang chạy và chúng đang làm gì, Derby cung cấp các bảng chẩn đoán hệ thống (System Diagnostic Tables) nằm trong schema SYSCS_DIAG. Bạn có thể truy vấn chúng bằng công cụ ij hoặc DBeaver.
Xem danh sách các giao dịch đang chạy
SQL
SELECT * FROM SYSCS_DIAG.TRANSACTION_TABLE;
Bảng này sẽ liệt kê:
-
TXID: Mã giao dịch. -
STATUS: Trạng thái (ACTIVE, IDLE). -
TYPE: Loại thao tác (UserTransaction).
Xem các kết nối đang giữ khóa tệp (Locking)
Trong môi trường đa kết nối, hiện tượng hai Client cùng muốn sửa một dòng dữ liệu sẽ dẫn đến việc tranh chấp khóa (Lock contention). Để xem kết nối nào đang nắm giữ khóa của bảng:
SQL
SELECT
XID,
TYPE,
MODE,
TABLENAME,
STATE
FROM SYSCS_DIAG.LOCK_TABLE;
Nếu bạn thấy trạng thái STATE là WAIT, nghĩa là một Client đang bị treo, chờ đợi Client khác giải phóng khóa.
Kết thúc bài học này, chúng ta đã hoàn tất Phần 4: Vận hành Derby Network Server Mode. Bạn đã nắm trong tay khả năng triển khai Derby như một máy chủ dịch vụ độc lập, quản lý kết nối qua mạng, cấu hình giới hạn luồng và giám sát giao dịch trực tiếp bằng SQL.
Đây là nền tảng vững chắc để chúng ta bước sang Phần 5: Tính năng cơ sở dữ liệu nâng cao, mở đầu với kỹ thuật then chốt quyết định tốc độ của toàn bộ hệ thống: cách cấu trúc dữ liệu bên dưới lớp vỏ SQL.
All rights reserved