2009-05-20 21 views
23

Hiện đang làm việc với Oracle, nhưng cũng sẽ cần một giải pháp cho MS SQL.Làm cách nào để hủy một hoạt động Cơ sở dữ liệu dài hạn?

Tôi có GUI cho phép người dùng tạo SQL sẽ được thực thi trên cơ sở dữ liệu. Quá trình này có thể mất nhiều thời gian, tùy thuộc vào tìm kiếm mà chúng tạo ra. Tôi muốn GUI/App đáp ứng trong quá trình tìm kiếm này và tôi muốn người dùng có thể hủy tìm kiếm.

Tôi đang sử dụng Đề tài công nhân nền.

Vấn đề của tôi là khi người dùng hủy tìm kiếm, tôi không thể ngắt cuộc gọi đến cơ sở dữ liệu. Nó đợi cho đến khi nó được hoàn thành và sau đó, nó có thể thăm dò tài sản 'CancelationPending'. Tài nguyên này không chỉ lãng phí trên cơ sở dữ liệu, mà còn tạo ra các vấn đề cho mã của tôi.

Nếu người dùng truy cập 'Tìm kiếm' trên một truy vấn rất dài, sau đó nhấp vào 'Hủy' và sau đó nhấp vào 'Tìm kiếm' lần nữa - tìm kiếm đầu tiên vẫn đang lưu lại trên cơ sở dữ liệu. Nhân viên nền vẫn bận khi họ nhấn tìm kiếm lần nữa. Giải pháp duy nhất tôi gặp phải trong vấn đề này là tạo một nhân viên nền tảng mới.

Dường như một cách thực sự xấu xí để làm việc. Cơ sở dữ liệu tiếp tục làm việc Tôi đang tạo các phiên bản mới của các nhân viên nền .... khi tôi thực sự muốn DỪNG cuộc gọi cơ sở dữ liệu và sử dụng lại cùng một nhân viên.

Tôi có thể làm như thế nào?

+1

Cảm ơn tất cả các bài đăng; Tôi thực sự không chắc câu trả lời nào là tốt nhất; tất cả các cuộc bỏ phiếu dường như đã đến từ tôi. Lời xin lỗi của tôi nếu tôi đã chọn sai. –

+0

bất kỳ mã mẫu tốt nào ?? – Kiquenet

Trả lời

1

Tôi không nghĩ điều đó là có thể. Dưới đây là một liên kết đến một cuộc thảo luận trên trang web của Oracle về chủ đề này: http://forums.oracle.com/forums/thread.jspa?threadID=400492&start=15&tstart=0

+1

Đây là sai hoàn toàn - xem bình luận của tôi dưới đây. Nó chắc chắn là * có thể *, bởi vì tôi đã thấy nó được thực hiện. Tôi ước tôi biết làm thế nào, mặc dù ... – JosephStyons

+1

MS SQL - có thể. – Nayan

3

Bạn có thể có ngọn lửa nhân nền tắt cuộc gọi cơ sở dữ liệu thực tế về một chủ đề khác nhau, và sau đó kiểm tra định kỳ để xem nếu một trong hai cuộc gọi cơ sở dữ liệu đã kết thúc hoặc hủy bỏ đã được nhấn, tại thời điểm đó bạn có thể hủy bỏ chuỗi cơ sở dữ liệu. Điều này sẽ không thực sự giúp cơ sở dữ liệu tải bất kỳ (như truy vấn của bạn đã được gửi và vẫn đang xử lý) nhưng nó phát hành tài nguyên cục bộ của bạn liên quan đến nó.

+1

Bạn không thể hủy chuỗi trong cuộc gọi gốc. – ctusch

2

Nếu bạn đang sử dụng SQLCommand, bạn có thể thử gọi phương thức đó là Cancel.

2

Điều gì về việc mở một kết nối mới vào cơ sở dữ liệu, đăng nhập bằng sysdba và gửi một "ALTER SYSTEM KILL SESSION 'sid, lệnh nối tiếp #' IMMEDIATE" chỉ định SID của quá trình bạn muốn chấm dứt.

Để có được sessionid: chọn sid từ v $ mystat nơi rownum = 1

Để có được Serial #: chọn sid, serial # từ v $ session nơi sid =: SID

http://www.oracle-base.com/articles/misc/KillingOracleSessions.php

EDIT: WW ý tưởng cho không Đăng nhập như sysdba đây: http://forums.oracle.com/forums/thread.jspa?threadID=620578

+2

Việc đăng nhập ứng dụng của bạn là sysdba không phải là ý tưởng hay từ quan điểm bảo mật. Tôi sẽ đề nghị gói lệnh giết này trong một gói PL/SQL mà chỉ có thể giết các phiên nhất định. –

+0

Đúng, trong mọi trường hợp, bạn có thể cần một số đặc quyền để chạy Gói SQL, nhưng bạn cũng phải thiết lập kết nối mới để gửi lệnh kill, vì vậy bạn sẽ đăng nhập vào cơ sở với các đặc quyền đặc biệt chỉ để chấm dứt phiên, phần còn lại của ứng dụng có thể sử dụng cùng một người dùng trước đó. – Burnsys

10

Nếu bạn đang sử dụng ADO.NET và nhà cung cấp dữ liệu SQL, hãy xem phương pháp SqlCommand.Cancel. Đó là những gì bạn đang tìm kiếm. Tuy nhiên, nó cố gắng để hủy bỏ và hủy bỏ có thể mất thời gian. Về cơ bản, nó lên đến SQL Server để quyết định khi nào để cấp yêu cầu hủy bỏ của bạn. Khi truy vấn bị hủy, bạn sẽ nhận được một SqlException chỉ ra rằng các hoạt động đã bị hủy bỏ bởi người sử dụng. Rõ ràng, bạn không muốn đối xử với ngoại lệ này như là ngoại lệ và xử lý nó đặc biệt như nếu SqlException là do người dùng hủy bỏ hoạt động, chỉ cần nuốt nó.

3

Tôi nghĩ rằng giải pháp tốt nhất dường như giết phiên thông qua bảng theo dõi.

Với Oracle bạn có thể làm cho nó như nói Burnsys

Trong Firebird 2.5 nó sẽ trông giống same

Tôi hy vọng một cái gì đó tương tự tồn tại trong Ms SQL

5

Tôi khá chắc chắn nó là thể - chúng tôi sử dụng TOAD cho Oracle và cho phép bạn hủy các truy vấn chạy dài, as described here. Tôi không chắc họ làm thế nào.

6

Tôi cũng nhận thấy lệnh.Cancel() không thực sự hủy bỏ lệnh. Những gì làm việc cho tôi là đóng kết nối (giao dịch rollback nếu bạn sử dụng một) khi người dùng hủy bỏ. Điều này sẽ nâng cao một ngoại lệ trong chủ đề nền của bạn trong khi lệnh được thực hiện, vì vậy bạn phải nắm bắt nó và kiểm tra tài sản CancellationPending ở đó và không rethrow ngoại trừ trong trường hợp đó ...

// When aborting 
worker.CancelAsync(); 
command.Connection.Close(); 

// In your DoWork event handler 
... 
catch (Exception) 
{ 
    if (worker.CancellationPending) 
    { 
     e.Cancel = true; 
     return; 
    } 
    else 
    { 
     throw; 
    } 
} 

// And in your RunWorkerCompleted event handler 
if (e.Error == null && !e.Cancelled) 
{ 
    ... 
} 
+0

Tôi đang cố gắng sử dụng đề xuất này nhưng nhận được một nhận thức bản địa mà tôi không thể bắt mà ngăn cản tôi làm điều này theo cách này. Bạn có bất kỳ kinh nghiệm với phương pháp này bằng cách sử dụng SQLCE? –

+0

Không biết xin lỗi ... – Koen

+1

Bạn sẽ muốn gọi SqlConnection.ClearPool để đảm bảo kết nối không quay lại hồ bơi ... http://objectmix.com/ado-dao-rdo-rds/ 358123-sqlconnection-clearpool-best-practice-command-timeout.html http://stackoverflow.com/questions/1145892/how-to-force-a-sqlconnection-to-physically-close-while-using-connection-pooling – user423430

1

Tôi đã thử cả hai Hủy bỏ và Đóng với máy khách gốc ADO 2.8 và SQLOLEDB hoặc SQL Server. Với Cancel, recordset dừng tìm nạp dữ liệu, nhưng trong backround, việc đọc từ máy chủ sẽ tiếp tục và tiêu thụ bộ nhớ từ ứng dụng. Trong một ứng dụng 32 bit nó có thể xảy ra mà bạn nhận được một "ra khỏi bộ nhớ" tin nhắn một vài phút sau đó. Khi tôi đóng bản ghi (hoặc kết nối, có hoặc không có Hủy trước), ADO 2.8 đợi cho đến khi tất cả các bản ghi được tìm nạp.

Tôi không biết liệu ADO.NET có thực hiện tốt hơn hay không, nhưng tôi nghĩ rằng nên theo dõi bộ nhớ và truy cập mạng sau khi Hủy/Đóng để đảm bảo rằng ADO thực sự ngừng đọc dữ liệu.

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