2009-02-27 34 views
7

Bạn có biết bất kỳ công cụ ORM nào cung cấp khôi phục khóa chết không? Tôi biết deadlocks là một điều xấu nhưng đôi khi bất kỳ hệ thống sẽ bị nó cho số tiền phải tải. Trong Sql Server, thông báo bế tắc nói "Chạy lại giao dịch" vì vậy tôi nghi ngờ rằng chạy lại câu lệnh bế tắc là một tính năng mong muốn trên ORM.Hỗ trợ ORM để xử lý Deadlocks

+0

Tôi không sử dụng ORM bản thân mình nhưng tôi ngạc nhiên đây không phải là một tính năng quan trọng của hầu hết các ORM! Cảm ơn câu hỏi khai sáng –

+0

Tôi đã mã hóa một câu hỏi cho bản thân mình bằng Python, nhưng nó hoạt động với các truy vấn SQL thô. Lý do hầu hết các khung công tác ORM không hỗ trợ nó là thiết kế API sử dụng chung không hỗ trợ nó. ORM không có toàn quyền kiểm soát giao dịch, vì vậy nó không thể chạy lại các giao dịch thất bại. –

Trả lời

3

Tôi không biết về bất kỳ công cụ hỗ trợ công cụ ORM đặc biệt nào cho các giao dịch tự động chạy lại không thành công do deadlocks. Tuy nhiên tôi không nghĩ rằng một ORM làm cho giao dịch với khóa/deadlocking vấn đề rất khác nhau. Thứ nhất, bạn nên phân tích nguyên nhân gốc rễ cho deadlocks của bạn, sau đó thiết kế lại các giao dịch và truy vấn của bạn theo cách mà các deadlocks có thể tránh được hoặc ít nhất là giảm. Có rất nhiều tùy chọn để cải thiện, như chọn mức cô lập phù hợp cho (các phần) giao dịch của bạn, sử dụng các gợi ý khóa vv Điều này phụ thuộc nhiều hơn vào hệ thống cơ sở dữ liệu của bạn sau đó trên ORM của bạn. Tất nhiên nó sẽ giúp nếu ORM của bạn cho phép bạn sử dụng các thủ tục được lưu trữ cho một số lệnh được tinh chỉnh, v.v.

Nếu điều này không giúp tránh deadlocks hoàn toàn, hoặc bạn không có thời gian để thực hiện và kiểm tra thực tế bây giờ, bạn có thể chỉ cần thử/nắm bắt xung quanh lưu/commit/persist hoặc bất kỳ cuộc gọi nào, kiểm tra các ngoại lệ bị bắt nếu chúng cho biết giao dịch không thành công là "nạn nhân bế tắc", và sau đó đơn giản gọi lại lưu/commit/persist sau một vài giây ngủ. Chờ một vài giây là một ý tưởng tốt vì deadlocks thường là một dấu hiệu cho thấy có một đỉnh tạm thời của các giao dịch cạnh tranh cho cùng một tài nguyên, và chạy lại cùng một giao dịch một cách nhanh chóng một lần nữa và có thể sẽ làm mọi việc trở nên tồi tệ hơn.

Vì lý do tương tự, bạn có thể sẽ không đảm bảo rằng bạn chỉ thử một lần để chạy lại cùng một giao dịch.

Trong một kịch bản thế giới thực, chúng tôi đã từng triển khai loại giải pháp này và khoảng 80% "nạn nhân bế tắc" đã thành công trong lần truy cập thứ hai. Nhưng tôi khuyên bạn nên digg sâu hơn để sửa chữa lý do thực sự cho deadlocking, bởi vì những vấn đề này thường tăng theo cấp số nhân với số lượng người dùng. Hy vọng rằng sẽ giúp.

+0

Điểm tốt, cảm ơn bạn. Tuy nhiên - nếu chúng ta biết rằng deadlocks xảy ra và có những chiến lược để xử lý chúng (ít nhất là với Sql Server), tại sao không đặt những người trong DAL? Điều này có nên được mong muốn trong một ORM không? –

+1

Tôi nghĩ rằng nó vẫn là một giải pháp, và có hỗ trợ hạng nhất cho một workaround như vậy sẽ khuyến khích mọi người ở lại với một giải pháp giả thay vì giải quyết vấn đề thực tế. – realMarkusSchmidt

1

Các khóa chết sẽ được mong đợi và SQL Server có vẻ kém hơn ở mặt trước này so với các máy chủ cơ sở dữ liệu khác. Trước tiên, bạn nên cố gắng giảm thiểu deadlocks của bạn. Hãy thử sử dụng SQL Server Profiler để tìm hiểu lý do tại sao nó xảy ra và những gì bạn có thể làm về nó. Tiếp theo, định cấu hình ORM của bạn để không đọc sau khi thực hiện cập nhật trong cùng một giao dịch, nếu có thể. Cuối cùng, sau khi bạn đã làm điều đó, nếu bạn tình cờ sử dụng Spring và Hibernate cùng nhau, bạn có thể đặt vào một kẻ đánh chặn để theo dõi tình huống này. Mở rộng MethodInterceptor và đặt nó trong bean Spring của bạn dưới interceptorNames. Khi interceptor được chạy, sử dụng invocation.proceed() để thực hiện giao dịch. Bắt bất kỳ ngoại lệ nào và xác định số lần bạn muốn thử lại.

+0

Bạn có biết nếu Hibernate có khả năng theo dõi các câu lệnh trong một giao dịch và chạy lại tất cả chúng trong trường hợp bế tắc? Tính năng như vậy có được mong muốn trong ORM không? –

+0

"SQL Server có vẻ tồi tệ hơn ở mặt trước này so với các máy chủ cơ sở dữ liệu khác" - hoàn toàn không đúng sự thật. Có lẽ một trong những lý do ai đó có thể nghĩ rằng điều này, là nó rất dễ dàng để bắt đầu sử dụng SQL Server, nó cũng dễ dàng để làm cho những sai lầm. –

+0

Tôi thực sự nghĩ rằng SQL làm một công việc tốt đẹp darn xem xét một số các lược đồ cơ sở dữ liệu kinh dị tôi đã nhìn thấy trong những năm qua. – RobS

0

Một hệ thống tôi làm việc trên được dựa trên “lệnh” mà sau đó đã được cam kết với cơ sở dữ liệu khi người dùng nhấn tiết kiệm, nó làm việc như thế này:

While(true) 
    start a database transaction 
    Foreach command to process 
     read data the command need into objects 
     update the object by calling the command.run method 
    EndForeach 
    Save the objects to the database 
    If not deadlock 
    commit the database transaction 
    we are done 
    Else 
    abort the database transaction 
    log deadlock and try again 
    EndIf 
EndWhile 

Bạn có thể làm điều gì đó giống như với bất kỳ ORM; chúng tôi đã sử dụng hệ thống truy cập dữ liệu trong nhà, vì ORM quá mới vào thời điểm đó.

Chúng tôi chạy các lệnh bên ngoài giao dịch trong khi người dùng tương tác với hệ thống. Sau đó chạy lại chúng như trên (khi bạn sử dụng đã làm một "tiết kiệm") để đối phó với những thay đổi người khác đã thực hiện. Vì chúng ta đã có một lý tưởng tốt về các hàng mà lệnh sẽ thay đổi, chúng ta thậm chí có thể sử dụng các gợi ý khóa hoặc “chọn để cập nhật” để lấy ra tất cả các khóa ghi mà chúng ta cần khi bắt đầu giao dịch.(Chúng tôi đã rút ngắn tập hợp các hàng được cập nhật để giảm số lượng deadlocks hơn nữa)

+0

Cảm ơn bạn. Vì vậy, bạn sẽ nghĩ là chấp nhận được cho một ORM để cung cấp tính năng như vậy, mặc dù một số người trả lời khác chống lại quan niệm bởi vì nó có thể dẫn đến sự bất cẩn từ các nhà phát triển? –

+0

Tôi nghĩ rằng nó phải được xây dựng trên đầu trang của ORM, vì không phải tất cả các ứng dụng đều sử dụng các lệnh. Một ORM không biết cách chạy lại mã C# của bạn. –

+0

Nó có thể biết nếu ví dụ khi bạn bắt đầu một giao dịch bạn thu thập mỗi báo cáo đến như một đơn vị công việc và phát lại chúng trong trường hợp thất bại như bế tắc. –

0

Một người lập bản đồ không thể phát hiện điều này, vì bế tắc luôn xảy ra bên trong DBMS. được thiết lập bởi các chủ đề khác hoặc thậm chí các ứng dụng khác.

Để chắc chắn một đoạn mã không tạo ra bế tắc, hãy luôn sử dụng các quy tắc sau: - tìm nạp bên ngoài giao dịch. Vì vậy, đầu tiên lấy, sau đó thực hiện xử lý sau đó thực hiện các câu lệnh DML như chèn, xóa và cập nhật - mọi hành động bên trong một phương thức hoặc một loạt các phương thức chứa/làm việc với một giao dịch phải sử dụng cùng một kết nối đến cơ sở dữ liệu. Điều này là bắt buộc vì ví dụ các khóa ghi được bỏ qua bởi các câu lệnh được thực hiện trên cùng một kết nối (vì cùng một kết nối đó thiết lập các khóa;)).

Thông thường, các sự cố xảy ra do mã tìm nạp dữ liệu bên trong một giao dịch gây ra kết nối MỚI được mở (phải chờ khóa) hoặc sử dụng các kết nối khác nhau cho các lệnh trong giao dịch.

+0

Mục đích của tôi có phần ít tham vọng hơn là một sự đảm bảo tổng số rằng các khóa tử vong có thể tránh được hoặc được xử lý trong mọi tình huống. Vấn đề là, tôi thấy trường hợp deadlocks xảy ra do tải và thử lại các câu lệnh là điều đúng đắn cần làm (chủ yếu là SQL server hoạt động theo cách đó). –

+0

Vâng, những điều bạn nên làm là: 1) đảm bảo mọi hoạt động trong chuỗi sau khi giao dịch được bắt đầu được thực hiện với cùng một kết nối và 2) nếu ngoại lệ xảy ra, bạn nên thử lại mọi thao tác khi giao dịch hoàn tất thất bại và khóa học 3) tìm nạp bên ngoài giao dịch! –

+0

Trong nhiều trường hợp, khóa quá mức hoặc bế tắc có thể được giảm bớt hoặc loại bỏ bằng cách tạo các chỉ mục 'đúng' cho khối lượng công việc truy vấn của bạn. –

0

Tôi đã xem nhanh (không nghi ngờ gì bạn cũng có) và không thể tìm thấy bất cứ điều gì cho thấy rằng hibernate ít nhất cung cấp này. Điều này có thể là do ORM xem xét điều này bên ngoài phạm vi của vấn đề mà họ đang cố giải quyết.

Nếu bạn đang gặp vấn đề với deadlocks chắc chắn thực hiện theo một số gợi ý được đăng ở đây để thử và giải quyết chúng. Sau đó, bạn chỉ cần đảm bảo rằng tất cả mã truy cập cơ sở dữ liệu của bạn được bao bọc bằng thứ gì đó có thể phát hiện bế tắc và thử lại giao dịch.

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