PPoossttffiixx OOppeennLLDDAAPP LLMMDDBB HHoowwttoo

-------------------------------------------------------------------------------

IInnttrroodduuccttiioonn

    WWaarrnniinngg:: LLMMDDBB ddaattaabbaasseess hhaavvee aa sshhooww--ssttooppppeerr bbuugg:: tthheeyy ddoo nnoott ggrrooww bbeeyyoonndd aa
    ssppeecciiffiieedd lliimmiitt,, aanndd iinnttrroodduuccee aa ""ddaattaabbaassee ffuullll"" hhaarrdd eerrrroorr ccoonnddiittiioonn tthhaatt
    ddooeess nnoott eexxiisstt wwiitthh aannyy ootthheerr PPoossttffiixx ddaattaabbaassee ttyyppee.. TThhiiss iiss aa pprroobblleemm ffoorr
    pprrooggrraammss wwhhoossee ddaattaabbaassee ggrroowwss wwiitthh ssyysstteemm llooaadd.. EExxaammpplleess aarree ppoossttssccrreeeenn((88)),,
    ggrreeyylliissttiinngg,, vveerriiffyy((88)) aanndd ttllssmmggrr((88))..

    YYoouu hhaavvee bbeeeenn wwaarrnneedd..

Postfix uses databases of various kinds to store and look up information.
Postfix databases are specified as "type:name". OpenLDAP LMDB implements the
Postfix database type "lmdb". The name of a Postfix OpenLDAP LMDB database is
the name of the database file without the ".lmdb" suffix. OpenLDAP LMDB
databases are maintained with the postmap(1) and postalias(1) commands.

This document describes:

 1. How to build Postfix with OpenLDAP LMDB support.

 2. How to configure LMDB settings.

 3. Missing pthread library trouble.

 4. Unexpected failure modes that don't exist with other Postfix databases.

BBuuiillddiinngg PPoossttffiixx wwiitthh OOppeennLLDDAAPP LLMMDDBB ssuuppppoorrtt

Postfix normally does not enable OpenLDAP LMDB support. To build Postfix after
you installed OpenLDAP LMDB from source code, use something like:

    % make makefiles CCARGS="-DHAS_LMDB -I/usr/local/include" \
        AUXLIBS="-L/usr/local/lib -llmdb"
    % make

Solaris needs this:

    % make makefiles CCARGS="-DHAS_LMDB -I/usr/local/include" \
        AUXLIBS="-R/usr/local/lib -L/usr/local/lib -llmdb"
    % make

The exact pathnames depend on how OpenLDAP LMDB was installed.

CCoonnffiigguurree LLMMDDBB sseettttiinnggss

Postfix provides a configuration parameter that controls how large an OpenLDAP
LMDB database may grow.

  * lmdb_map_size (default: 16 MBytes per table). This setting controls how
    large any OpenLDAP LMDB database may grow. It must be set large enough to
    accommodate the largest table that Postfix will use.

MMiissssiinngg pptthhrreeaadd lliibbrraarryy ttrroouubbllee

When building Postfix fails with:

    undefined reference to `pthread_mutexattr_destroy'
    undefined reference to `pthread_mutexattr_init'
    undefined reference to `pthread_mutex_lock'

Add the "-lpthread" library to the "make makefiles" command.

    % make makefiles .... AUXLIBS="... -lpthread"

Source code for OpenLDAP LMDB is available at http://www.openldap.org. More
information is available at http://highlandsun.com/hyc/mdb/.

UUnneexxppeecctteedd ffaaiilluurree mmooddeess ooff PPoossttffiixx LLMMDDBB ddaattaabbaasseess..

As documented below, conversion to LMDB introduces a number of failure modes
that don't exist with other Postfix databases.

UUnneexxppeecctteedd ppoossttmmaapp((11))//ppoossttaalliiaass((11)) ""ddaattaabbaassee ffuullll"" eerrrroorrss..

Problem:
    The "postmap lmdb:filename" command fails with an MDB_MAP_FULL error. This
    problem does not exist with other Postfix databases.

Background:
    LMDB databases have a hard size limit (configured with the lmdb_map_size
    configuration parameter).

    When executing "postmap lmdb:filename", the Postfix LMDB database client
    stores the new data in a transaction which takes up space in addition to
    the existing data, and commits the transaction when it closes the database.
    Only then can the space for old data be reused.

Impact:
    This failure does not affect Postfix availability, because the old data
    still exists in the database.

Mitigation:
    When the postmap(1) or postalias(1) command fails with an MDB_MAP_FULL
    error, it expands the database file size to the current LMDB map size limit
    before terminating.

    When the postmap(1) or postalias(1) command opens an LMDB file larger than
    lmdb_map_size/3, it logs a warning and uses a larger size limit instead:

    warning: filename.lmdb: file size 15024128 >= (lmdb map size limit
    16777216)/3 -- using a larger map size limit

    The two steps above can be used to automate recovery and avoid the need for
    human intervention. Just repeat "postmap lmdb:filename" (up to some limit).
    After each failure it will use a 3x larger size limit, and eventually the
    "database full" error will disappear.

Prevention:
    Monitor your LMDB files and make sure that lmdb_map_size > 3x the largest
    LMDB file size.

UUnneexxppeecctteedd PPoossttffiixx ddaaeemmoonn ""ddaattaabbaassee ffuullll"" eerrrroorrss..

Problem:
    Postfix daemon programs fail with "database full" errors, such as
    postscreen(8), tlsmgr(8) or verify(8). This problem does not exist with
    other Postfix databases.

Impact:
    This failure temporarily affects Postfix availability. The daemon restarts
    automatically and tries to open the database again as described next.

Mitigation:
    When a Postfix daemon opens an LMDB file larger than lmdb_map_size/3, it
    logs a warning and uses a larger size limit instead:

    warning: filename.lmdb: file size 15024128 >= (lmdb map size limit
    16777216)/3 -- using a larger map size limit

    This can be used to automate recovery and avoid the need for human
    intervention. Each time the daemon runs into a "database full" error, it
    restarts and uses a 3x larger size limit. The "database full" error will
    disappear, at least for a while.

Prevention:
    Monitor your LMDB files and make sure that lmdb_map_size > 3x the largest
    LMDB file size.

NNoonn--oobbvviioouuss rreeccoovveerryy wwiitthh ppoossttmmaapp((11))//ppoossttaalliiaass((11))//ttllssmmggrr((88)) ffrroomm aa ccoorrrruupptteedd
ddaattaabbaassee..

Problem:
    You cannot rebuild a corrupted LMDB database simply by running postmap(1)
    or postalias(1), or by waiting until the tlsmgr(8) daemon restarts
    automatically. This problem does not exist with other Postfix databases.

Background:
    The Postfix LMDB database client does not truncate the database file.
    Instead it attempts to create a transaction for a "drop" request plus
    subsequent "store" requests. That is obviously not possible with a
    corrupted database file.

Impact:
    Postfix does not process mail until someone fixes the problem.

Recovery:
    First delete the ".lmdb" file by hand, then rebuild the file with the
    postmap(1) or postalias(1) command, or wait until the tlsmgr(8) daemon
    restarts automatically.

Prevention:
    Arrange your file systems such that they never run out of free space.

    Use ECC memory to detect and correct silent corruption of in-memory file
    system data and metadata.

    Use a file system such as ZFS to detect and correct silent corruption of
    on-disk file system data and metadata.

