2008-11-14 13 views
5

Dường như cách cổ điển để xử lý các giao dịch với JDBC là đặt tự động cam kết thành sai. Điều này tạo ra một giao dịch mới, và mỗi cuộc gọi cam kết đánh dấu sự khởi đầu của các giao dịch tiếp theo. Trên ứng dụng đa luồng, tôi hiểu rằng thực tế phổ biến là mở một kết nối mới cho mỗi luồng.JDBC: Tôi có thể chia sẻ kết nối trong ứng dụng đa luồng và tận hưởng giao dịch tốt đẹp không?

Tôi đang viết một ứng dụng máy chủ đa khách hàng dựa trên RMI, để về cơ bản máy chủ của tôi liên tục sinh ra một luồng cho mỗi kết nối mới. Để xử lý giao dịch một cách chính xác, tôi có nên đi và tạo kết nối mới cho từng chuỗi đó không? Chi phí của một kiến ​​trúc như vậy có bị cấm không?

Trả lời

4

Có, nói chung, bạn cần tạo kết nối mới cho mỗi chuỗi. Bạn không có quyền kiểm soát cách hệ điều hành thời gian thực hiện các luồng (mặc dù định nghĩa các phần quan trọng của riêng bạn), vì vậy bạn vô tình có thể có nhiều luồng cố gắng gửi dữ liệu xuống một đường ống đó.

Lưu ý điều tương tự cũng áp dụng cho bất kỳ liên lạc mạng nào. Ví dụ: nếu bạn có hai chủ đề cố gắng chia sẻ một ổ cắm với kết nối HTTP.

  • Chủ đề 1 tạo ra một yêu cầu
  • Chủ đề 2 tạo ra một yêu cầu
  • Chủ đề 1 lần đọc byte từ các ổ cắm, vô tình đọc phản hồi từ chủ đề 2 của yêu cầu

Nếu bạn bọc tất cả các giao dịch của bạn trong các phần quan trọng, và do đó khóa bất kỳ chủ đề khác cho toàn bộ chu kỳ bắt đầu/cam kết, sau đó bạn có thể chia sẻ kết nối cơ sở dữ liệu giữa các luồng. Nhưng tôi sẽ không làm điều đó ngay cả khi đó, trừ khi bạn thực sự có kiến ​​thức bẩm sinh về giao thức JDBC.

Nếu hầu hết các chủ đề của bạn không cần thiết cho kết nối cơ sở dữ liệu (hoặc không cần chút nào), bạn có thể chỉ định một luồng để thực hiện công việc cơ sở dữ liệu của mình và yêu cầu các luồng khác xếp hàng yêu cầu của chúng vào chuỗi đó. Điều đó sẽ làm giảm chi phí của rất nhiều kết nối. Nhưng bạn sẽ phải tìm ra cách quản lý các kết nối cho mỗi luồng trong môi trường của bạn (hoặc hỏi một câu hỏi cụ thể khác về điều đó trên StackOverflow).

update: Để trả lời câu hỏi của bạn trong các bình luận, hầu hết các nhãn hiệu cơ sở dữ liệu không hỗ trợ nhiều giao dịch đồng thời trên một kết nối duy nhất (Interbase/Firebird là ngoại lệ duy nhất tôi biết).

Thật tuyệt khi có một đối tượng giao dịch riêng biệt và có thể bắt đầu và thực hiện nhiều giao dịch cho mỗi kết nối. Nhưng các nhà cung cấp chỉ đơn giản là không hỗ trợ nó.

Tương tự, các API độc lập của nhà cung cấp tiêu chuẩn như JDBC và ODBC đưa ra giả định tương tự, trạng thái giao dịch chỉ đơn thuần là thuộc tính của đối tượng kết nối.

+0

Ok ... Chỉ bằng sự tò mò, bạn có biết tại sao định nghĩa của giao dịch được kết hợp với định nghĩa kết nối trên JDBC không? Tôi thực sự đánh giá cao một đối tượng giao dịch. – fulmicoton

+0

Cảm ơn bạn rất nhiều vì câu trả lời của bạn !!! – fulmicoton

+1

Tuyên bố "bạn vô tình có thể có nhiều chủ đề cố gắng gửi dữ liệu xuống một đường ống" trong câu trả lời này là hoàn toàn sai cho postgresql. Xem http://doc.postgresintl.com/jdbc/ch10.html. Kết nối ít nhất là an toàn, mặc dù không hoàn toàn song song vì nó có thể. –

1

Thực tiễn không phổ biến để mở kết nối mới cho từng chuỗi. Thông thường, bạn sử dụng hồ bơi kết nối như thư viện c3po.

Nếu bạn đang ở trong một máy chủ ứng dụng hoặc sử dụng Hibernate chẳng hạn, hãy xem tài liệu và bạn sẽ tìm cách cấu hình nhóm kết nối.

+0

Cảm ơn sự đóng góp của bạn. Tôi nên được ok mà không có một hồ bơi kết nối trong trường hợp của tôi: Tôi không có khả năng yêu cầu kết nối quá thường xuyên anyway. Đối với người đọc khác: Tôi khá chắc chắn rằng c3po là một thư viện tuyệt vời, tuy nhiên hãy chắc chắn rằng nó là ok cho bạn để sử dụng LGPL. – fulmicoton

+0

Vấn đề với LGPL là gì? Bạn có thể sử dụng nó với các ứng dụng thương mại (nó là Lesser GPL). –

1

Đối tượng kết nối tương tự có thể được sử dụng để tạo nhiều đối tượng câu lệnh và các đối tượng tuyên bố này có thể được sử dụng đồng thời bởi các luồng khác nhau.Hầu hết các DB hiện đại được giao tiếp bởi JDBC có thể làm điều đó. Do đó, JDBC có thể sử dụng các con trỏ đồng thời như sau. PostgreSQL là không có ngoại lệ ở đây, xem ví dụ:

http://doc.postgresintl.com/jdbc/ch10.html

này cho phép kết nối pooling nơi kết nối chỉ được sử dụng trong một thời gian ngắn, cụ thể là để tạo ra các đối tượng tuyên bố và nhưng sau đó trở lại hồ bơi. Việc gộp nhóm thời gian ngắn này chỉ được khuyến nghị khi kết nối JDBC thực hiện song song các hoạt động tuyên bố, nếu không kết nối gộp bình thường có thể cho kết quả tốt hơn. Nhưng dù sao thread có thể tiếp tục làm việc với đối tượng statement và đóng nó lại sau, nhưng không thể kết nối.

1. Thread 1 opens statement 
3. Thread 2 opens statement 
4. Thread 1 does something   Thread 2 does something 
5. ...        ... 
6. Thread 1 closes statement  ... 
           7. Thread 2 closes statement 

Ở trên chỉ hoạt động ở chế độ cam kết tự động. Nếu giao dịch là cần thiết, vẫn không cần phải buộc giao dịch vào một luồng. Bạn chỉ có thể phân vùng tổng hợp dọc theo các giao dịch đó là tất cả và sử dụng cách tiếp cận tương tự như trên. Nhưng điều này chỉ cần thiết không phải vì một số giới hạn kết nối socket nhưng vì JDBC sau đó tương đương với ID phiên với ID giao dịch.

Nếu tôi nhớ rõ, nên có các API và sản phẩm xung quanh với thiết kế đơn giản hơn, trong đó ID phiên và ID giao dịch không được cân bằng. Trong API này, bạn có thể viết máy chủ của mình với một đối tượng kết nối cơ sở dữ liệu duy nhất, ngay cả khi nó thực hiện giao dịch . Sẽ cần phải kiểm tra và cho bạn biết sau này API và sản phẩm này là gì.

Các vấn đề liên quan