3

I searched for Assert and found general explanations:

Assertion (software development)

In computer programming, an assertion is a statement that a predicate (Boolean-valued function, a true–false expression) is expected to always be true at that point in the code. If an assertion evaluates to false at run time, an assertion failure results, which typically causes the program to crash, or to throw an assertion exception.

and

What does the “assert” keyword do?

Assertions are generally used primarily as a means of checking the program's expected behavior. It should lead to a crash in most cases, since the programmer's assumptions about the state of the program are false. This is where the debugging aspect of assertions come in. They create a checkpoint that we simply can't ignore if we would like to have correct behavior.

As a database operatior I only saw asserts when data files got corrupt (repair needed, sometimes data loss). Any more examples and definition specific for database systems (both SQL and NoSQL)?

2

I have zero to none experience in the world of NoSQL so I'll add some perspective from a RDBM:s side of view.

I believe assertions where introduced in SQL92, the following is an example from: 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;

Meaning that CONSTRAINT_1 is violated if the average of the TABLE_1.COLUMN_1 values is less than 41.

However, I'm not sure how many RDBM:s that actually implements ASSERTION. Two substitutes often used is CHECK constraints and validation triggers. Example:

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

Such a constraint will prevent any negative values of column_1.

SELECT statements are allowed in CHECK constraints according to standard, but likewise ASSERTIONS I don't think that this is widely implemented. Triggers are commonly use to implement set assertions. Here is one example from the DB2 catalog:

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  

When we try to delete the last policy an exception is thrown.

Other constraints such as UNIQUE or FOREIGN KEY could also be thought of as ASSERTIONS of the state of the universe.

From a philosophical point an "ASSERTION/CONSTRAINT" in a DBMS world is a stronger "rule" than an ASSERTION in a procedural/oo world. Whereas the latter verifies the state for a particular action. Example from:

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

The assertion alone not sufficient to protect MyDB. In addition we also need OO-concepts such as encapsulation, meaning that we must ensure that all possible ways to change the state of MyDB is protected by similar ASSERTIONS. A CONSTRAINT on the other hand guarantees the state no matter what action we take.

ASSERTIONS in RDBM:S and OO both have there merits, but are slightly different concepts and there is not a 1-1 mapping between the two.

1

As per the definitions you've quoted in your question description, assertions are logical tests that trigger exceptions on failure. These are used within most automated testing suites as well as at runtime.

In test suites assertions confirm that the results of a function call or data update are as expected and are often set up as macros indicating the comparison type (eg. ASSERT_EQUALS, ASSERT_OK, ASSERT_NOT_OK).

In the runtime context assertions are safety checks that cause the current operation or process to abort when it is unsafe or impossible to continue. The usage and behaviour of assertions will vary by product.

For the specific case of the MongoDB codebase, there are several types of runtime assertions used. Quoting from the MongoDB Server Exception Architecture documentation these are (as at MongoDB 3.4):

  • uassert Checks for per-operation user errors. Operation-fatal.
  • massert Checks per-operation invariants. Operation-fatal.
  • verify [deprecated] Checks per-operation invariants. A synonym for massert but doesn't require an error code. Do not use for new code; use invariant or fassert instead.
  • fassert Checks fatal process invariants. Process-fatal. Use to detect unexpected situations (such as a system function returning an unexpected error status).
  • invariant Checks process invariant. Process-fatal. Use to detect code logic errors ("pointer should never be null", "we should always be locked")

MongoDB server code always uses one of the listed assertion functions rather than a generic assert() so the intent of the assertion is clear (i.e. operation or process fatal, error or invariant failure) and the assertion leads to a consistent termination of the applicable context (operation or process).

Assertions that are operation-fatal (uassert, massert) will abort the current operation and return an error code and message to the client application. One common example is "E1100" (duplicate key error), which indicates that a document cannot be added to a unique index because there already is a different document indexed with the same key. The assertion numbers do not have any specific meaning aside from helping identify the code point(s) that throw a specific exception. You can find a list of error codes in the MongoDB source code: src/mongo/base/error_codes.err.

Operational-fatal assertions also increment counters in db.serverStatus().asserts. These assertions should be uncommon and typically indicate application or user error. If these counters increase significantly it would be worth reviewing your MongoDB log files for more details. Note: the counters are reset to 0 when the MongoDB process restarts and can potentially rollover for long-running processes with a lot of assertions (as indicated by the asserts.rollovers value).

Assertions that are process-fatal (fassert, invariant) will shut down the MongoDB server process. Common examples are file permission errors on startup (unable to read or write files in the dbPath) or serious data integrity errors where continuing might lead to corruption or loss of data. These assertions require administrative intervention to investigate and resolve the error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.