0

非常に単純なコードに縮小できる 2 つの直接関連する問題があります。マシン 1 がアプリケーションをホストし、マシン 2 がデータベースをホストし、ハブを介してイーサネットで接続されているとします。ハブからネットワーク ケーブルを抜いて、ネットワークの問題をシミュレートします。

おそらく「ネットワークの信頼性を高めてください」と言うでしょう。私もそうです。顧客が信じる前に、問題を明確に把握して、それが最初ではないことを証明する必要があります。

/非常に/長時間実行されるクエリと非クエリがあるため、この問題をタイムアウトで解決することはできません。はい、中には実際に 1 時間以上かかるものもあり、ユーザーは、実際のエラーが発生するのに十分な時間、フリーズしたセッションをじっと見つめることに我慢できません。彼らは代わりにそれを殺します。

using System.Data;
using System.Data.SqlClient;

public class test {
    public static void hang1()
    {
        using SqlConnection oConnection = applib.getConnection() // returns an open connectin
        {
            using SqlCommand oCmd = new SqlCommand("WAITFOR DELAY 00:01:00", oConnection)
                oCmd.ExecuteNonQuery(); // unplug cable between hub and database server when in this call and this call never returns
        }
     }

     public static void hang2()
     {
            using SqlCommand oTCmd = new SqlCommand("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE", oConnection)
                oCmd.ExecuteNonQuery();

            using oTransaction = new SqlClient.SqlTransaction
            {

            using SqlCommand oCmd = new SqlCommand("SELECT max(id) FORM Table1")
            {
               oCmd.Transaction = oTransaction;
               oCmd.ExecuteScaler();
               System.Threading.Thread.Sleep(60 * 1000);
               // Disconnect the cable between the hub and the application server here
               // Now table Table1 is locked and will remain locked until the transaction
               // is manually killed from the database server.
               oCmd.ExecuteScaler();
            }
            }
      }
 }

タイムアウトを設定せずに、トランザクションがスタックしていることを検出するソリューションを探しています。独自の TCP/IP プロトコルを設計する場合は、ハートビートを設計して、十分な時間応答がない場合 = 停止、救済、クリーンアップと結論付けるようにします。同じアイデアを実現する方法が欲しいです。つまり、静かなハングをノイズの多いクラッシュに変えて、クリーンアップ コードでクリーンアップできるようにすることです。

4

2 に答える 2

0

ここに別の提案があります。

SQL Server ではCheckConnection(@spid int)、何らかの方法で接続のステータスを報告する と呼ばれる proc を実装します。この情報は、master.sys.sysprocessesまたは新しい情報スキーマ ビューから見つけることができます。

このようなもの:

create proc CheckConnection(@spidToCheck int)
as
begin

    select 
        spcheck.spid, spcheck.blocked, 
        spcheck.lastwaittype, 
        (select name from master.dbo.sysdatabases sd where sd.dbid = spcheck.dbid) as database_name,
        spcheck.physical_io, 
        spcheck.memusage,
        spcheck.login_time,
        spcheck.last_batch, 
        spcheck.open_tran,
        spcheck.status,
        case 
        when spcheck.spid = spcurrent.spid
        then 'Same Connection'
        when 
        spcheck.net_library = spcurrent.net_library
        and spcheck.net_address = spcurrent.net_address
        and spcheck.sid = spcurrent.sid
        and spcheck.hostprocess = spcurrent.hostprocess
        then 'Same Client'
        else 'Different Client'
        end as client_status
    from master.dbo.sysprocesses spcheck
    inner join master.dbo.sysprocesses spcurrent
    on spcheck.spid = @spidToCheck and spcurrent.spid = @@spid



end

実行時間の長いプロセスを実行する前に、 を実行して接続オブジェクトの SPID を確認できますconnection.ExecuteScalar("select @@SPID as SPID");。その後、別の接続を使用して、SPID がまだ有効であり、同じクライアントを持っているかどうかを数分ごとに監視できます。(SPID は閉じられると再利用されるため、クライアントが同じであることを確認する必要があります)。

于 2013-05-03T09:27:29.283 に答える