Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 21 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
21
Dung lượng
231,99 KB
Nội dung
Các chiến lược giao tác: : Hiểu những cạm bẫy trong giao tác Đề phòng các lỗi thường gặp khi triển khai thực hiện giao tác trên nền Java Mark Richards, Giám đốc và kiến trúc sư kỹ thuật cao cấp, Collaborative Consulting, LLC Tóm tắt: Xử lý giao tác phải đạt được tính toàn vẹn và nhất quán của dữ liệu ở mức cao. Bài viết này, là bài đầu tiên trong một loạt bài viết về phát triển một chiến lược giao tác hiệu quả trên nền Java, sẽ giới thiệu những cạm bẫy thường gặp để ngăn bạn khỏi mắc vào. Dùng những ví dụ là các đoạn mã lệnh trong Spring Framework và đặc tả EnterPrise JavaBeans (EJB) 3.0, tác giả Mark Richards sẽ giải thích những lỗi quá thông thường ấy. Lý do chung nhất khi sử dụng các giao tác trong một ứng dụng là để duy trì tính toàn vẹn và nhất quán của dữ liệu ở mức cao. Nếu bạn không quan tâm đến chất lượng dữ liệu của mình, thì bạn cũng không cần quan tâm đến các giao tác. Sau hết, việc hỗ trợ giao tác trên nền Java có thể hủy hoại hiệu năng, sinh ra vấn đề về khóa và các vấn đề tương tranh trong cơ sở dữ liệu, và do vậy gây thêm phức tạp cho trình ứng dụng của bạn. Về loạt bài này Các giao tác làm tăng chất lượng, tính toàn vẹn và tính nhất quán của dữ liệu của bạn, và khiến cho các trình ứng dụng của bạn vững chãi hơn. Việc triển khai thể hiện thành công các xử lý giao tác trong các ứng dụng Java không phải là một công việc tầm thường, và đây là nói về việc thiết kế cũng quan trọng ngang với nói về viết mã lệnh. Trong loạt bài mới này, Mark Richards sẽ hướng dẫn chúng ta thiết kế một chiến lược giao tác hiệu quả cho một loạt các trường hợp từ các trình ứng dụng đơn giản cho đến xử lý giao tác hiệu năng cao. Nhưng những người phát triển lại không bận tâm đến những giao tác gây thiệt hại cho mình như thế. Hầu hết các ứng dụng có liên quan đến kinh doanh đều yêu cầu chất lượng dữ liệu ở mức cao. Chỉ riêng ngành kinh doanh đầu tư tài chính đã mất mười tỉ đô la cho các hoạt động thương mại thất bại, mà dữ liệu tồi là nguyên nhân thứ hai dẫn tới tình trạng này (xem Tài nguyên). Mặc dù việc thiếu các hỗ trợ giao tác chỉ là một tác nhân dẫn đến tình trạng dữ liệu tồi (vẫn là nguyên nhân chính), một kết luận chắc chắn là hàng tỷ đô la đã bị lãng phí chỉ riêng trong lĩnh vực kinh doanh đầu tư tài chính là hậu quả của việc thiếu hụt hoặc không có các hỗ trợ giao tác. Không biết gì về các hỗ trợ giao tác là nguyên nhân khác của vấn đề. Rất thường xuyên tôi đã nghe những tuyên bố theo kiểu “chúng tôi không cần hỗ trợ giao tác trong các trình ứng dụng của chúng tôi đâu, bởi vì chúng chả bao giờ lỗi cả.” Đúng. Tôi đã từng chứng kiến một số trình ứng dụng trong thực tế cực hiếm hoặc không bao giờ đưa ra các báo lỗi. Những trình ứng dụng ấy trông cậy vào việc có mã lệnh viết rất tốt, có các thủ tục kiểm tra dữ liệu hợp lệ được viết tốt và việc hỗ trợ kiểm soát mã và kiểm thử đầy đủ để giảm chi phí thực thi và những phức tạp liên quan đến xử lý giao tác. Vấn đề của cách suy nghĩ như thế là ở chỗ nó chỉ tính đến một đặc trưng của hỗ trợ giao tác: tính nguyên tử . Tính nguyên tử đảm bảo rằng mọi cập nhật sẽ được xem như một đơn vị công việc duy nhất và, hoặc là tất cả được giao kết hoặc là tất cả bị hủy bỏ. Nhưng sự hủy bỏ hoặc phối hợp các cập nhật không phải là khía cạnh duy nhất của hỗ trợ giao tác. Một khía cạnh khác, sự phân lập, sẽ đảm bảo rằng mỗi đơn vị công việc được tách biệt khỏi các đơn vị khác. Nếu không có sự phân lập giao tác thích hợp, các đơn vị công việc khác có thể truy nhập vào các cập nhật được tạo ra bởi một đơn vị công việc đang chạy, mặc dù đơn vị này chưa hoàn thành xong việc của mình. Và kết quả là các quyết định kinh doanh có thể được đưa ra dựa trên dữ liệu chưa hoàn chỉnh, gây ra những giao dịch kinh doanh thất bại hoặc những hậu quả tiêu cực. Muộn còn hơn không Tôi bắt đầu đánh giá đúng các vấn đề trong xử lý giao tác từ đầu năm 2000, khi làm việc cho khách hàng tôi để ý đến một mục trong bản kế hoạch dự án ngay bên trên nhiệm vụ kiểm thử hệ thống. Dòng đó là thực hiện hỗ trợ giao tác. Chắc chắn rồi, khá dễ dàng bổ sung các hỗ trợ giao tác vào trình ứng dụng chính khi nó gần như đã đến giai đoạn sẵn sàng để kiểm thử hệ thống có phải không? Thật không may, cách tiếp cận này quá chung chung. Ít nhất thì dự án này, không giống như hầu hết những dự án khác, đã thực thi các hỗ trợ giao tác, mặc dù ở giai đoạn cuối của chu kỳ phát triển. Vậy thì khi đã biết rằng chi phí cao và ảnh hưởng xấu của dữ liệu tồi và các hiểu biết cơ bản về giao tác là quan trọng (và cần thiết), bạn cần sử dụng các giao tác và học cách giải quyết các vấn đề nảy sinh. Bạn gấp rút bổ sung hỗ trợ giao tác vào trình ứng dụng của mình. Và đây chính là chỗ mà các vấn đề thường nảy sinh. Các giao tác hình như thường không hoạt động như hứa hẹn trên nền Java. Bài viết này sẽ khảo sát tỉ mỉ lý do tại sao như thế. Cùng với sự trợ giúp của các đoạn mã ví dụ, tôi sẽ giới thiệu những cạm bẫy phổ biến trong giao tác mà tôi thường thấy và kinh nghiệm trong lĩnh vực này, hầu hết trường hợp là trong các môi trường sản xuất. Mặc dù hầu hết các đoạn mã ví dụ trong bài viết này sử dụng khung công tác Spring (Spring Framework) phiên bản 2.5, khái niệm giao tác là tương tự như trong đặc tả EJB 3.0. Trong đa số các trường hợp, chỉ đơn giản là ta thay thế lời chú giải @Transactional của khung công tác Spring bằng @TransactionAttribute trong đặc tả của EJB 3.0. Những chỗ mà hai bộ khung này khác nhau về khái niệm và kỹ thuật, tôi sẽ đưa ra cả hai ví dụ mã nguồn của khung công tác Spring và EJB 3. Những cạm bẫy trong giao tác cục bộ. Cách tốt nhất để khởi đầu là bằng một kịch bản dễ nhất: việc sử dụng các giao tác cục bộ, cũng thường được gọi là giao tác cơ sở dữ liệu. Thời kỳ đầu mới xuất hiện cơ sở dữ liệu bền vững (ví dụ JDBC), chúng ta thường giao phó việc xử lý giao tác cho cơ sở dữ liệu. Rốt cuộc thì đây có phải chính là cái mà cơ sở dữ liệu cần phải làm? Các giao tác cục bộ làm việc tốt với các đơn vị công việc logic (LUW), tức là thực hiện các câu lệnh đơn như chèn, cập nhật hoặc xóa. Ví dụ, xét đoạn mã lệnh JDBC đơn giản trong Liệt kê 1, đoạn mã lệnh này thực hiện thao tác chèn một lệnh mua bán chứng khoán vào bảng TRADE: Liệt kê 1. Thao tác chèn đơn giản vào một cơ sở dữ liệu sử dụng JDBC @Stateless public class TradingServiceImpl implements TradingService { @Resource SessionContext ctx; @Resource(mappedName="java:jdbc/tradingDS") DataSource ds; public long insertTrade(TradeData trade) throws Exception { Connection dbConnection = ds.getConnection(); try { Statement sql = dbConnection.createStatement(); String stmt = "INSERT INTO TRADE (ACCT_ID, SIDE, SYMBOL, SHARES, PRICE, STATE)" + "VALUES (" + trade.getAcct() + "','" + trade.getAction() + "','" + trade.getSymbol() + "'," + trade.getShares() + "," + trade.getPrice() + ",'" + trade.getState() + "')"; sql.executeUpdate(stmt, Statement.RETURN_GENERATED_KEYS); ResultSet rs = sql.getGeneratedKeys(); if (rs.next()) { return rs.getBigDecimal(1).longValue(); } else { throw new Exception("Trade Order Insert Failed"); } } finally { if (dbConnection != null) dbConnection.close(); } } } Đoạn mã lệnh JDBC trong Liệt kê 1 không có logic giao tác, nó một mực đưa lệnh mua bán vào bảng TRADE trong cơ sở dữ liệu. Trong trường hợp này, cơ sở dữ liệu điều khiển logic giao tác. Điều này là tốt và hợp lý đối với trường hợp chỉ có một hành động duy trì cơ sở dữ liệu trong đơn vị công việc lô gic (LUW). Nhưng giả sử rằng bạn cần cập nhật số dư tài khoản cùng thời điểm với việc bạn chèn một lệnh mua bán vào cơ sở dữ liệu, như ta thấy trong Liệt kê 2: Liệt kê 2. Thực hiện nhiều cập nhật bảng trong cùng một phương thức public TradeData placeTrade(TradeData trade) throws Exception { try { insertTrade(trade); updateAcct(trade); return trade; } catch (Exception up) { //log the error throw up; } } Trong trường hợp này, các phương thức insertTrade() và updateAcct() đã dùng mã lệnh JDBC chuẩn mà không có các giao tác. Một khi phương thức insertTrade() kết thúc, cơ sở dữ liệu sẽ khẳng định (và giao kết (commit)) lệnh mua bán. Nếu phương thức updateAcct() thất bại bởi bất cứ lý do gì, lệnh mua bán này sẽ vẫn tồn tại trong bảng TRADE khi kết thúc phương thức placeTrade(), kết quả là dữ liệu không nhất quán trong cơ sở dữ liệu. Nếu phương thức placeTrade() sử dụng các giao tác, cả hai hoạt động này sẽ nằm trong cùng một LUW và lệnh mua bán này sẽ bị hủy nếu việc cập nhật tài khoản bị thất bại. Với sự phổ biến rộng rãi của các khung công tác bền vững của Java như Hibernate, TopLink và Java Persistence API (JPA) đang phát triển, chúng ta hiếm khi viết thẳng các đoạn mã lệnh JDBC nữa. Phổ biến hơn là chúng ta dùng các khung công tác ánh xạ quan hệ - đối tượng (ORM) mới hơn để làm cho công việc dễ dàng hơn bằng cách thay thế tất cả các đoạn mã lệnh JDBC khó chịu này bằng một vài lời gọi phương thức đơn giản. Ví dụ, để chèn một lệnh mua bán từ ví dụ đoạn mã lệnh JDBC trong Liệt kê 1, sử dụng khung công tác Spring với JPA, bạn sẽ ánh xạ đối tượng TradeData vào bảng TRADE và thay thế toàn bộ đoạn mã lệnh JDBC này bằng đoạn mã lệnh JPA trong Liệt kê 3: Liệt kê 3. Thao tác chèn đơn giản dùng JPA public class TradingServiceImpl { @PersistenceContext(unitName="trading") EntityManager em; public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); } } Lưu ý rằng trong Liệt kê 3 ta gọi phương thức persist() trong EntityManager để chèn một lệnh mua bán. Đơn giản quá, đúng không? Không hẳn thế. Đoạn mã lệnh này sẽ không chèn lệnh mua bán vào bảng TRADE như ta mong muốn, cũng không sinh ra ngoại lệ. Nó chỉ đơn giản là trả lại giá trị 0 như là khóa của lệnh mua bán này mà chẳng biến đổi gì cơ sở dữ liệu cả. Đây là cạm bẫy chủ yếu đầu tiên của xử lý giao tác: các khung công tác dựa trên nền ORM yêu cầu phải có một giao tác để kích hoạt một quá trình đồng bộ hóa giữa đối tượng nhớ sẵn (cache object) và cơ sở dữ liệu. Chính là thông qua việc giao kết một giao tác mà mã SQL sẽ được sinh ra và tác động đến cơ sở dữ liệu với các hành động mong muốn (như chèn, cập nhật, xóa). Không có một giao tác ở đây thì không thể kích hoạt một quá trình trên ORM để sinh mã lệnh SQL và thực hiện các thay đổi, như vậy phương thức đơn giản chỉ kết thúc– không có lỗi ngoại lệ, không có cập nhật. Nếu bạn đang dùng khung công tác dựa trên ORM, bạn phải dùng sử dụng các giao tác. Bạn không còn có thể dựa vào cơ sở dữ liệu để quản lý các kết nối và hoàn tất công việc. Những ví dụ đơn giản này biểu thị rõ ràng rằng giao tác là cần thiết để duy trì dữ liệu toàn vẹn và nhất quán. Nhưng đây mới chỉ là bề ngoài của những rắc rối và những cạm bẫy thường vấp phải khi thực thi các giao tác trên nền Java. Bẫy chú giải @Transactional của khung công tác Spring Như vậy bạn đã kiểm thử mã lệnh trong Liệt kê 3 và khám phá ra rằng phương thức persist() không thực hiện khi thiếu giao tác. Kết quả là bạn thấy vài đường liên kết nhờ một thao tác tìm kiếm đơn giản trên Internet và biết rằng với khung công tác Spring, ta cần dùng chú giải @Transactional. Bởi thế bạn thêm chú giải vào mã lệnh như trong Liệt kê 4: Liệt kê 4. Sử dụng chú giải @Transactional public class TradingServiceImpl { @PersistenceContext(unitName="trading") EntityManager em; @Transactional public long insertTrade(TradeData trade) throws Exception { em.persist(trade); return trade.getTradeId(); } } Kiểm thử lại mã lệnh và bạn sẽ nhận thấy chương trình vẫn không hoạt động. Vấn đề là bạn phải thông báo với SpringFramework rằng bạn đang sử dụng các chú giải để quản lý giao tác. Trừ phi bạn đang thực hiện kiểm thử đơn vị toàn bộ, đôi khi cái bẫy này khá là khó tìm ra. Thông thường nó dẫn người phát triển đến chỗ chỉ đơn giản thêm vào các logic giao tác trong tệp cấu hình Spring mà không nghĩ tới các chú giải. Khi sử dụng chú giải @Transactional trong Spring, ta phải thêm dòng mã sau vào tệp cấu hình Spring: <tx:annotation-driven transaction-manager="transactionManager"/> Thuộc tính transaction-manager lưu giữ một tham chiếu đến bean quản lý giao tác được định nghĩa trong tệp cấu hình Spring. Dòng mã này báo cho Spring sử dụng chú giải @Transaction khi áp dụng bộ chặn giao tác. Nếu không có đoạn mã này, chú giải @Transactional sẽ bị bỏ qua, kết quả là không có giao tác nào được sử dụng trong mã lệnh. Việc làm cho chú giải cơ sở @Transactional có tác dụng trong mã lệnh ở Liệt kê 4 chỉ là sự khởi đầu. Lưu ý rằng Liệt kê 4 sử dụng chú giải @Transactional mà không định rõ bất cứ tham số chú giải bổ sung nào. Tôi nhận thấy nhiều người dùng chú giải @Transactional mà không bỏ thời gian tìm hiểu đầy đủ xem nó làm gì. Ví dụ, khi sử dụng chú giải @Transactional không tham số như ta đã làm trong Liệt kê 4, chế độ lan truyền giao tác sẽ được thiết lập là gì? Cờ báo chỉ đọc được đặt là gì? Mức phân lập giao tác được đặt là gì? Quan trọng hơn, khi nào thì giao tác sẽ bị cuộn lùi trở lại? Hiểu chú giải giao tác được sử dụng như thế nào là rất quan trọng để đảm bảo bạn có mức độ hỗ trợ giao tác thích hợp trong trình ứng dụng của mình. Và đây là trả lời những câu hỏi tôi vừa đặt ra: khi sử dụng chú giải @Transactional không có bất kỳ tham số nào, chế độ lan truyền được đặt là REQUIRED, cờ báo chỉ đọc đặt là false, mức phân lập giao tác đặt giá trị mặc định của cơ sở dữ liệu (thường là READ_COMMITTED), và giao tác sẽ không bị cuộn lùi trở lại khi ngoại lệ đã được kiểm tra. Bẫy cờ chỉ đọc của chú giải @Transactional Một cạm bẫy phổ biến nhất mà tôi thường xuyên gặp là dùng sai cờ chỉ đọc trong chú giải Spring @Transactional. Ở đây có một câu hỏi nhanh dành cho bạn: Khi dùng mã lệnh JDBC chuẩn của Java bền vững, chú giải @Transactional trong Liệt kê 5 thực hiện công việc gì khi cờ chỉ đọc được thiết lập giá trị true và chế độ lan truyền đặt là SUPPORTS? Liệt kê 5. Sử dụng cờ chỉ đọc với chế độ lan truyền JDBC là SUPPORTS. @Transactional(readOnly = true, propagation=Propagation.SUPPORTS) public long insertTrade(TradeData trade) throws Exception { //JDBC Code } Khi thi hành phương thức insertTrade() trong Liệt kê 5, nó sẽ: A. Đưa ra lỗi ngoại lệ cảnh báo kết nối chỉ đọc. B. Chèn một cách chính xác lệnh mua bán và giao kết dữ liệu C. Không làm gì vì mức lan truyền đặt là SUPPORTS Bạn đầu hàng? Câu trả lời chính xác là B. Lệnh mua bán được chèn một cách chính xác vào cơ sở dữ liệu, thậm chí cả khi cờ chỉ đọc được thiết lập giá trị true và lan truyền giao tác được đặt là SUPPORTS. Nhưng tại sao lại có thể như thế? Không có giao tác nào được khởi động vì phương thức truyền dẫn là SUPPORTS, như vậy là phương thức này thực sự dùng giao tác cục bộ (của cơ sở dữ liệu). Cờ chỉ đọc chỉ được áp dụng nếu một giao tác được khởi động. Trong trường hợp này, không có giao tác nào thực hiện nên cờ chỉ đọc bị bỏ qua. Được thôi, nếu đúng là như thế thì chú giải @Transactional sẽ có tác dụng gì trong liệt kê 6 khi cờ chỉ đọc có giá trị true và phương thức truyền dẫn là REQUIRED? Liệt kê 6. Sử dụng cờ chỉ đọc với phương thức truyền dẫn REQUIRED của — JDBC @Transactional(readOnly = true, propagation=Propagation.REQUIRED) public long insertTrade(TradeData trade) throws Exception { //JDBC code } Khi chạy, phương thức insertTrade() trong liệt kê 6 sẽ làm gì: A. Đưa ra một lỗi ngoại lệ cảnh báo kết nối chỉ đọc B. Chèn đúng đắn lệnh mua bán và giao kết dữ liệu C. Không làm gì cả vì cờ chỉ đọc được thiết đặt giá trị true Câu hỏi rất dễ trả lời vì đã có các giải thích lúc trước. Câu trả lời chính xác là A. Sẽ có một ngoại lệ được đưa ra, chỉ báo rằng bạn đang cố thực hiện một thao tác cập nhật trên kết nối chỉ đọc. Vì một giao tác sẽ được khởi động (REQUIRED), kết nối này sẽ được thiết đặt là chỉ đọc. Chắc chắn, khi bạn thử thực hiện câu lệnh SQL ấy, bạn sẽ nhận được một ngoại lệ thông báo rằng kết nối là chỉ đọc. [...]... đáng kể trong việc phát triển một chiến lược giao tác toàn diện Những bài còn lại trong loạt bài Các chiến lược giao tác sẽ giúp hướng dẫn bạn về vấn đề thiết kế một chiến lược giao tác hiệu quả cho các ca sử dụng trong một phạm vi rộng từ những ứng dụng đơn giản cho đến ứng dụng xử lý giao tác hiệu năng cao Mục lục Những cạm bẫy trong giao tác cục bộ Bẫy chú giải @Transactional của khung công tác. .. ra vì một giao tác mới được khởi động trong phương thức updateAcct(), như vậy giao tác này sẽ hoàn tất khi phương thức updateAcct() kết thúc Khi ta dùng thuộc tính giao tác REQUIRES_NEW, nếu đã có một giao tác tồn tại rồi, thì giao tác hiện tại sẽ bị buộc tạm dừng và một giao tác mới được khởi động Khi phương thức kết thúc thì giao tác mới sẽ được giao kết và giao tác ban đầu lại phục hồi Vì cách hoạt... là cuộn lùi giao tác khi đã hoàn tất phương thức khởi động giao tác này Chiến lược giao tác mô tả trong bài viết tiếp theo của loạt bài này sẽ hướng dẫn khi nào và ở đâu cần cuộn lùi Kết luận Mã lệnh dùng để thực hiện các giao tác trên nền Java không quá phức tạp; tuy nhiên, cách bạn dùng và cấu hình chúng có thể có chút rắc rối Nhiều cái bẫy có liên quan đến việc thực hiện các hỗ trợ giao tác trên nền... Liệt kê 8 s : A Khởi động một giao tác, nhận một lệnh mua bán, sau đó hoàn tất giao tác B Nhận một lệnh mua bán mà không khởi động một giao tác Đừng bao giờ nói không bao giờ Một lúc nào đó bạn muốn khởi động một giao tác cho thao tác đọc cơ sở dữ liệu – ví dụ, khi phân lập các thao tác đọc để đảm bảo nhất quán dữ liệu hay thiết lập một mức phân lập giao tác cụ thể cho thao tác đọc Tuy nhiên, những tình... đó để dùng nó tương tự như trong ví dụ kiểm toán đã nêu Những cái bẫy do cuộn lùi giao tác Tôi để lại trình bày cuối cùng cái bẫy giao tác phổ biến nhất Thật không may, tôi lại thấy nó xuất hiện nhiều hơn trong các mã lệnh chạy sản xuất Tôi sẽ bắt đầu với Spring Framework và sau đó chuyển sang EJB 3 Cho đến giờ, mã lệnh mà chúng ta đã xem xét trông giống như trong Liệt kê 1 3: Liệt kê 13 Không hỗ trợ... thế nên thuộc tính giao tác REQUIRES_NEW chỉ nên dùng trong trường hợp hành động cơ sở dữ liệu trong phương thức được gọi cần được ghi lưu vào cơ sở dữ liệu bất chấp kết quả của giao tác phủ ngoài Ví dụ, giả sử người ta cố gắng ghi lại tất cả các giao dịch chứng khoán vào trong cơ sở dữ liệu kiểm toán Thông tin này cần được ghi lại bền vững bất kể giao dịch thất bại hay không bởi các lý do như lỗi không... trên quan điểm giao tác; mặc dù nó có vẻ là dùng các giao tác để duy trì tính nguyên tử và tính nhất quán, thực tế là nó không làm được Mặc dù kiểu hành xử này có vẻ lạ, các giao tác hành xử theo cách này là vì một số lý do thích đáng Trước hết, không phải tất cả các ngoại lệ đã kiểm tra đều tệ; chúng có thể được dùng cho việc báo cáo sự kiện hoặc để chuyển hướng việc xử lý dựa trên những điều kiện... @Transactional khi thực hiện thao tác đọc, như chỉ ra trong Liệt kê 1 0: Liệt kê 10 Loại bỏ chú giải @Transactional khi thực hiện thao tác select public TradeData getTrade(long tradeId) throws Exception { return em.find(TradeData.class, tradeId); } Những lỗi thường vấp đối với thuộc tính giao tác REQUIRES_NEW Dù bạn đang sử dụng khung công tác Spring hay EJB, việc dùng thuộc tính giao tác REQUIRES_NEW cũng mang... những tình huống như vậy khá hiếm trong các ứng dụng kinh doanh, trừ khi bạn phải đối mặt với vấn đề như thế, bạn nên tránh khởi động một giao tác cho các thao tác đọc vì chúng không cần thiết và có thể dẫn tới việc khóa chết luôn cơ sở dữ liệu, hiệu suất thấp và thông lượng kém Câu trả lời chính xác ở đây là A Một giao tác sẽ được khởi tạo và hoàn tất Đừng quên rằng: chế độ lan truyền mặc định của... nền Java (bao gồm một số cái bẫy nữa ít phổ biến hơn mà tôi không thảo luận ở đây) Vấn đề lớn nhất với đa số các cạm bẫy này là không có một cảnh báo biên dịch hay một lỗi khi đang chạy nào cho ta biết việc thực hiện giao tác là không chính xác Hơn thế nữa, trái ngược với giả định phản ánh trong giai thoại "Muộn còn hơn không" ở đầu bài viết, việc thực hiện hỗ trợ giao tác không chỉ là lao động lập . Các chiến lược giao tác: : Hiểu những cạm bẫy trong giao tác Đề phòng các lỗi thường gặp khi triển khai thực hiện giao tác trên nền Java Mark Richards, Giám. đáng kể trong việc phát triển một chiến lược giao tác toàn diện. Những bài còn lại trong loạt bài Các chiến lược giao tác sẽ giúp hướng dẫn bạn về vấn đề thiết kế một chiến lược giao tác hiệu. Spring và EJB 3. Những cạm bẫy trong giao tác cục bộ. Cách tốt nhất để khởi đầu là bằng một kịch bản dễ nhất: việc sử dụng các giao tác cục bộ, cũng thường được gọi là giao tác cơ sở dữ liệu.