Xem qua nguồn của ConnectionPool.java
bạn dường như gặp đoạn mã này trong borrowConnection()
phương pháp:
//we didn't get a connection, lets see if we timed out
if (con == null) {
if ((System.currentTimeMillis() - now) >= maxWait) {
throw new SQLException("[" + Thread.currentThread().getName()+"] " +
"Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +
" seconds, none available["+busy.size()+" in use].");
} else {
//no timeout, lets try again
continue;
}
}
Vì vậy, theo điều này, kết nối của bạn là Null .
Giá trị của con
được truy xuất trên dòng:
PooledConnection con = idle.poll();
nếu bạn theo dõi mã, bạn sẽ thấy idle
là (tùy thuộc vào cấu hình của bạn, nhưng theo mặc định) FairBlockingQueue
. Bạn có thể kiểm tra việc triển khai để biết các gợi ý.
Nói chung, bạn luôn phải đóng ResultSets, Statements và Connections và các kết nối đã sử dụng phải được giải phóng đúng cách trở lại nhóm. Không làm đúng cách có thể dẫn đến kết nối không bao giờ bị đóng => không bao giờ có sẵn để sử dụng lại (nhóm kết nối "rò rỉ" ).
Tôi khuyên bạn nên tạo một số ghi nhật ký chi tiết về trạng thái của nhóm và theo dõi nó để cô lập vấn đề.
Một số hướng dẫn từ Apache để ngăn chặn rò rỉ nhóm kết nối cơ sở dữ liệu:
removeAbandoned="true"
các kết nối cơ sở dữ liệu bị bỏ rơi được loại bỏ và tái chế
removeAbandonedTimeout="60"
đặt số giây mà một kết nối cơ sở dữ liệu không hoạt động trước khi nó bị coi là bị bỏ rơi
logAbandoned="true"
ghi lại một dấu vết ngăn xếp của mã đã bỏ qua tài nguyên kết nối cơ sở dữ liệu. Hãy nhớ rằng "ghi nhật ký các Kết nối bị bỏ qua sẽ thêm chi phí cho mỗi lần mượn Kết nối vì phải tạo dấu vết ngăn xếp".
Tôi vẫn nghĩ rằng sẽ tăng một chút maxWait
value (1200, 1500, 1700 - chỉ cần thử nghiệm, sẽ không có sự khác biệt về thời gian phản hồi từ góc độ người dùng) sẽ xóa những trường hợp hiếm gặp mà bạn vẫn gặp sự cố.