私はデータベースの経験がほとんどなく、firebird2.5データベースでデッドロックを引き起こすトリガーの問題に遭遇しました。
データベースには2つのテーブルがあります。アイテムがITEMSテーブルに追加または削除されると、トリガーはSTATS.ITEMCOUNTおよびSTATS.SIZEを更新します。合計2つのインクリメントと2つのデクリメントの4つのトリガーがあります。
統計テーブルには1つの行があり、データベースの内容を追跡するために使用されます。私はこれを間違った方法でやっていますか?そうでない場合は、回避策があります。
デッドロックは、アプリケーションを開始してから最初の数分以内に発生します。
UPDATE1:すべてのトリガーを投稿しました。
UPDATE2:投稿されたExecuteNonQueryメソッド
UPDATE3: pilcrowによって親切に提案されたviewメソッドを使用している場合でも、デッドロックが発生します。実際、私は再びデッドロックしたストアドプロシージャを使用しようとしました。Firebird Adoプロバイダーは並列トランザクションをサポートしていないため、selectステートメントをトランザクションでラップすることも失敗しました。
public void ExecuteNonQuery(string NonQuery)
{
try
{
FbCommand FBC = new FbCommand(NonQuery, DBConnection);
FBC.ExecuteNonQuery();
FBC.Dispose();
}
catch (FbException e)
{
Log.FatalException("Database NonQuery Error", e);
}
}
}
データベース
** Tables **
CREATE TABLE ITEMS (
ID ID NOT NULL /* ID = VARCHAR(36) NOT NULL */,
EXPIRYTIME EXPIRYTIME NOT NULL /* EXPIRYTIME = BIGINT NOT NULL */,
ITEMSIZE ITEMSIZE /* ITEMSIZE = BIGINT NOT NULL */,
ACCESSCOUNT ACCESSCOUNT DEFAULT 1 NOT NULL /* ACCESSCOUNT = INTEGER DEFAULT 1 NOT NULL */,
LASTACCESSTIME LASTACCESSTIME /* LASTACCESSTIME = TIMESTAMP NOT NULL */
);
CREATE TABLE STATS (
INSTANCE SMALLINT,
SIZE BIGINT DEFAULT 0,
ITEMCOUNT BIGINT DEFAULT 0,
HITS BIGINT DEFAULT 0,
MISSES BIGINT DEFAULT 0
);
**トリガー**
/* Trigger: TRG_INCREMENT_ITEMCOUNT_STATS */
CREATE OR ALTER TRIGGER TRG_INCREMENT_ITEMCOUNT_STATS FOR ITEMS
ACTIVE AFTER INSERT POSITION 1
AS
begin
UPDATE STATS SET ITEMCOUNT = ITEMCOUNT + 1 WHERE INSTANCE = '0';
end
/* Trigger: TRG_DECREMENT_ITEMCOUNT_STATS */
CREATE OR ALTER TRIGGER TRG_DECREMENT_ITEMCOUNT_STATS FOR ITEMS
ACTIVE AFTER DELETE POSITION 2
AS
begin
UPDATE STATS SET ITEMCOUNT = ITEMCOUNT - 1 WHERE INSTANCE = '0';
end
/* Trigger: TRG_INCREMENT_HITS_STATS */
CREATE OR ALTER TRIGGER TRG_INCREMENT_HITS_STATS FOR ITEMS
ACTIVE AFTER UPDATE POSITION 3
AS
begin
UPDATE STATS SET HITS = HITS + 1 WHERE INSTANCE = '0';
end
/* Trigger: TRG_INCREMENT_SIZE_STATS */
CREATE OR ALTER TRIGGER TRG_INCREMENT_SIZE_STATS FOR ITEMS
ACTIVE AFTER INSERT POSITION 4
AS
BEGIN
UPDATE STATS SET SIZE = SIZE + NEW.ITEMSIZE WHERE INSTANCE = 0;
END
/* Trigger: TRG_DECREMENT_CACHESIZE_STATS */
CREATE OR ALTER TRIGGER TRG_DECREMENT_CACHESIZE_STATS FOR ITEMS
ACTIVE AFTER DELETE POSITION 5
AS
BEGIN
UPDATE STATS SET SIZE = SIZE - OLD.ITEMSIZE WHERE INSTANCE = 0;
END