web-dev-qa-db-ja.com

データベースの世界でのアサートとは何ですか?

Assertを検索し、一般的な説明を見つけました。

アサーション(ソフトウェア開発)

コンピュータプログラミングでは、アサーションとは、述語(ブール値関数、true-false式)がコードのその時点で常にtrueであることが期待されるステートメントです。実行時にアサーションがfalseと評価されると、アサーションエラーが発生し、通常はプログラムがクラッシュするか、アサーション例外がスローされます。

そして

「assert」キーワードは何をしますか?

アサーションは通常、主にプログラムの予想される動作をチェックする手段として使用されます。プログラムの状態に関するプログラマーの仮定が誤っているため、ほとんどの場合はクラッシュにつながるはずです。これがアサーションのデバッグの側面の出番です。正しい動作が必要な場合は無視できないチェックポイントを作成します。

データベースオペレーターとして、私はデータファイルが破損したときにのみアサートを確認しました(修復が必要、場合によってはデータの損失)。データベースシステム(SQLとNoSQLの両方)に固有の例と定義はありますか?

3
Ivanov

質問の説明で引用した定義に従って、アサーションは失敗時に例外をトリガーする論理テストです。これらは、ほとんどの自動テストスイート内および実行時に使用されます。

テストスイートでは、アサーションにより、関数呼び出しまたはデータ更新の結果が期待どおりであり、比較タイプを示すマクロとして設定されることがよくあります(例:_ASSERT_EQUALS_、_ASSERT_OK_、_ASSERT_NOT_OK_) 。

ランタイムコンテキストでは、アサーションは安全チェックであり、現在の操作またはプロセスは、安全でないか続行できない場合に中止されます。アサーションの使用法と動作は製品によって異なります。

MongoDBコードベースの特定のケースでは、いくつかのタイプのランタイムアサーションが使用されます。 MongoDBからの引用 Server Exception Architecture ドキュメント(MongoDB 3.4と同じ):

  • uassert操作ごとのユーザーエラーをチェックします。致命的なオペレーション。
  • massert操作ごとの不変条件をチェックします。致命的なオペレーション。
  • verify [非推奨]操作ごとの不変条件をチェックします。 massertの同義語ですが、エラーコードは必要ありません。新しいコードには使用しないでください。代わりにインバリアントまたはファサートを使用してください。
  • fassert致命的なプロセス不変条件をチェックします。プロセス致命的。予期しない状況(予期しないエラーステータスを返すシステム関数など)を検出するために使用します。
  • invariantプロセス不変をチェックします。プロセス致命的。コードロジックエラーを検出するために使用します(「ポインターをnullにしない」、「常にロックする」)

MongoDBサーバーコードは、一般的なassert()ではなく、リストされたアサーション関数のいずれかを常に使用するため、アサーションの意図は明確であり(つまり、操作またはプロセスの致命的、エラー、または不変の失敗)、アサーションは一貫した終了につながります該当するコンテキスト(操作またはプロセス)。

操作に致命的なアサーション(uassertmassert)は、現在の操作を中止し、エラーコードとメッセージをクライアントアプリケーションに返します。 1つの一般的な例は "E1100"(重複キーエラー)です。これは、同じキーでインデックス付けされた別のドキュメントが既にあるため、ドキュメントを一意のインデックスに追加できないことを示します。アサーション番号は、特定の例外をスローするコードポイントを特定することを除いて、特定の意味はありません。エラーコードのリストは、MongoDBソースコード src/mongo/base/error_codes.err にあります。

運用上致命的なアサーションは db.serverStatus().asserts のカウンタもインクリメントします。これらのアサーションは一般的ではなく、通常はアプリケーションまたはユーザーのエラーを示します。これらのカウンターが大幅に増加する場合は、MongoDBログファイルで詳細を確認することをお勧めします。注:MongoDBプロセスが再起動すると、カウンターは0にリセットされ、多くのアサーション( _asserts.rollovers_ 値で示される)を伴う長時間実行プロセスのロールオーバーの可能性があります。

プロセスに致命的なアサーション(fassertinvariant)は、MongoDBサーバープロセスをシャットダウンします。一般的な例は、起動時のファイルアクセス権エラー(dbPath内のファイルを読み書きできない)または継続するとデータの破損または損失につながる可能性がある重大なデータ整合性エラーです。これらのアサーションは、エラーを調査して解決するために管理者の介入を必要とします。

2
Stennie

私はNoSQLの世界でゼロからゼロの経験を持っているので、RDBMの観点からいくつかの視点を追加します。

アサーションはSQL92で導入されたと思います。以下はその例です。 https://mariadb.com/kb/en/sql-99/create-assertion-statement/

CREATE ASSERTION constraint_1 
    CHECK ((SELECT AVG(column_1) FROM Table_1 >40) NOT DEFERRABLE;

TABLE_1.COLUMN_1値の平均が41未満の場合、CONSTRAINT_1に違反していることを意味します。

ただし、実際にASSERTIONを実装するRDBM:の数はわかりません。よく使用される2つの代替は、CHECK制約と検証トリガーです。例:

ALTER TABLE Table_1 
     ADD CONSTRAINT C1 CHECK (column_1 >= 0);

このような制約により、column_1の負の値が防止されます。

SELECTステートメントは標準に従ってCHECK制約で許可されますが、同様にアサーションこれは広く実装されているとは思いません。トリガーは通常、セットアサーションを実装するために使用されます。以下は、DB2カタログの1つの例です。

CREATE TRIGGER SYSTOOLS.POLICY_DR  
NO CASCADE  BEFORE DELETE  ON SYSTOOLS.POLICY  
REFERENCING OLD AS OLD_ROW  
FOR EACH ROW  
MODE DB2SQL  
SECURED  
BEGIN ATOMIC    
    IF ( ( SELECT COUNT(*) FROM SYSTOOLS.POLICY 
           WHERE OLD_ROW.MED = MED 
             AND OLD_ROW.DECISION = DECISION ) = 1 ) THEN      
        SIGNAL SQLSTATE '85101' ('At least one policy is required.');
    END IF;  
END  

最後のポリシーを削除しようとすると、例外がスローされます。

UNIQUEやFOREIGN KEYなどの他の制約も、宇宙の状態のアサーションと考えることができます。

哲学的な観点から、DBMSの世界での「ASSERTION/CONSTRAINT」は、手続き型/ ooの世界でのASSERTIONよりも強力な「ルール」です。一方、後者は特定のアクションの状態を確認します。例:

https://wiki.python.org/moin/UsingAssertionsEffectively

class MyDB:
[...]
    def by_name(self, name):
        id = self._name2id_map[name]
        assert self._id2name_map[id] == name
        return id

アサーションだけではMyDBを保護するには不十分です。さらに、カプセル化などのOO概念も必要です。つまり、MyDBの状態を変更するすべての可能な方法が、同様のアサーションによって保護されていることを確認する必要があります。一方、制約は、どのようなアクションを実行しても、状態を保証します。

RDBM:SのアサーションとOOの両方にメリットがありますが、コンセプトは少し異なり、2つの間に1-1マッピングはありません。

2
Lennart