Skip to content

Thread blocking problem with "firebird-driver" #62

@mbllo-gh

Description

@mbllo-gh

We are developing a database application based on Firebird and Python
which highly uses threads to run many jobs in parallel. Originally, we
decided to use the "fdb" module to connect to the database. Unfortunately,
fdb's support for Firebird versions bigger than 3 is limited, so a switch
to "firebird-driver" is recommended.

To ensure data consistency the database is operating "repeatable read",
this means if transactions of different threads touch the same data, the
transaction is throwing an exception and the application tries to repeat.
Unfortunately, "firebird-driver" tend to block some threads much more than
others so much that they exceed the tolerance of repetitions and give up.
But this nearly never happened with "fdb".

To demonstrate this, I can recommend a Python software we developed nearly
a decade ago to make database benchmarks with PostgreSQL and Firebird.
For PostgreSQL we used "psycopg2" module, for Firebird originally "fdb" and
"firebirdsql". In the last days I also added "firebird-driver" support.

The name of this benchmark software is "dsbench". It makes TPC-B transactions
to measure the database performance in a way like pgbench is doing it.
This means, dsbench generates databases of logarithmically rising sizes up to
about 150GB and is carrying out transactions then. Finally, the software
is creating several diagrams with results and calculates a performance
factor (we called that DSI - dsbench index) to give a single comparable
number.

One "transaction block" lasts about 1 minute. In this minute many threads
(default 16) connects to the database and try to execute as many transactions
as possible. If the database is small, the probability of a collision is high
and transactions must be rolled back. Each block gives you a table of results,
especially numbers of successful and failed transactions for each thread.
If "fdb" is used all threads show comparable numbers of successful and failed
transactions. Otherwise, if "firebird-driver" is used, mainly one thread
is doing all transactions and all the others are more or less blocked
and can't do anything. Let me show this with the dsbench log itself:

First: "fdb" - as expected
Number of "done" (successful transactions) and "errors" (rolled back due to collision) done by different threads is comparable.

--- Begin dsbench measuring cycle 1/10 ---
2025-12-11 21:42:33,477 -- [INFO] (Worker-03 ): cycle=1, scale=1, dbsize=0.017670, done=408, errors=1009, residence=4.58, elapsed=60.00, tpsR=88.99, tpsE=6.80, tpsD=6.80
2025-12-11 21:42:33,479 -- [INFO] (Worker-05 ): cycle=1, scale=1, dbsize=0.017670, done=565, errors=1338, residence=6.07, elapsed=59.99, tpsR=93.14, tpsE=9.42, tpsD=9.42
2025-12-11 21:42:33,483 -- [INFO] (Worker-11 ): cycle=1, scale=1, dbsize=0.017670, done=481, errors=1452, residence=4.92, elapsed=59.96, tpsR=97.75, tpsE=8.02, tpsD=8.02
2025-12-11 21:42:33,485 -- [INFO] (Worker-09 ): cycle=1, scale=1, dbsize=0.017670, done=459, errors=1495, residence=5.47, elapsed=60.00, tpsR=83.93, tpsE=7.65, tpsD=7.65
2025-12-11 21:42:33,488 -- [INFO] (Worker-14 ): cycle=1, scale=1, dbsize=0.017670, done=705, errors=1806, residence=7.66, elapsed=59.79, tpsR=92.09, tpsE=11.79, tpsD=11.75
2025-12-11 21:42:33,490 -- [INFO] (Worker-12 ): cycle=1, scale=1, dbsize=0.017670, done=374, errors=1283, residence=4.39, elapsed=59.68, tpsR=85.13, tpsE=6.27, tpsD=6.23
2025-12-11 21:42:33,492 -- [INFO] (Worker-16 ): cycle=1, scale=1, dbsize=0.017670, done=396, errors=1058, residence=4.04, elapsed=59.73, tpsR=98.03, tpsE=6.63, tpsD=6.60
2025-12-11 21:42:33,492 -- [INFO] (Worker-04 ): cycle=1, scale=1, dbsize=0.017670, done=597, errors=1412, residence=5.90, elapsed=59.73, tpsR=101.24, tpsE=9.99, tpsD=9.95
2025-12-11 21:42:33,496 -- [INFO] (Worker-13 ): cycle=1, scale=1, dbsize=0.017670, done=593, errors=1592, residence=6.64, elapsed=59.61, tpsR=89.37, tpsE=9.95, tpsD=9.88
2025-12-11 21:42:33,496 -- [INFO] (Worker-01 ): cycle=1, scale=1, dbsize=0.017670, done=498, errors=1770, residence=5.78, elapsed=59.69, tpsR=86.20, tpsE=8.34, tpsD=8.30
2025-12-11 21:42:33,516 -- [INFO] (Worker-15 ): cycle=1, scale=1, dbsize=0.017670, done=696, errors=2122, residence=7.18, elapsed=58.92, tpsR=96.90, tpsE=11.81, tpsD=11.60
2025-12-11 21:42:33,520 -- [INFO] (Worker-08 ): cycle=1, scale=1, dbsize=0.017670, done=484, errors=1634, residence=5.80, elapsed=58.55, tpsR=83.49, tpsE=8.27, tpsD=8.07
2025-12-11 21:42:33,520 -- [INFO] (Worker-10 ): cycle=1, scale=1, dbsize=0.017670, done=440, errors=1235, residence=5.05, elapsed=58.91, tpsR=87.16, tpsE=7.47, tpsD=7.33
2025-12-11 21:42:34,486 -- [INFO] (Worker-02 ): cycle=1, scale=1, dbsize=0.017670, done=727, errors=1759, residence=7.07, elapsed=60.00, tpsR=102.89, tpsE=12.12, tpsD=12.12
2025-12-11 21:42:34,486 -- [INFO] (Worker-07 ): cycle=1, scale=1, dbsize=0.017670, done=468, errors=1226, residence=4.79, elapsed=59.99, tpsR=97.68, tpsE=7.80, tpsD=7.80
2025-12-11 21:42:34,487 -- [INFO] (Worker-06 ): cycle=1, scale=1, dbsize=0.017670, done=599, errors=1639, residence=6.53, elapsed=59.99, tpsR=91.66, tpsE=9.98, tpsD=9.98

Second: "firebird-driver" - some threads blocked
For instance, Worker-15 did not try any transaction (successful or failed) within one minute!

--- Begin dsbench measuring cycle 1/10 ---
2025-12-11 21:45:49,128 -- [INFO] (Worker-07 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=10324, residence=0.00, elapsed=60.00, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,134 -- [INFO] (Worker-08 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=3, residence=0.00, elapsed=0.02, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,135 -- [INFO] (Worker-03 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=4, residence=0.00, elapsed=0.03, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,137 -- [INFO] (Worker-11 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=14, residence=0.00, elapsed=60.00, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,141 -- [INFO] (Worker-05 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=7, residence=0.00, elapsed=0.04, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,142 -- [INFO] (Worker-13 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=1766, residence=0.00, elapsed=32.10, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,146 -- [INFO] (Worker-14 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=3, residence=0.00, elapsed=0.02, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,146 -- [INFO] (Worker-16 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=7, residence=0.00, elapsed=0.03, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,146 -- [INFO] (Worker-09 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=4, residence=0.00, elapsed=0.03, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,147 -- [INFO] (Worker-02 ): cycle=1, scale=1, dbsize=0.014465, done=4029, errors=0, residence=26.45, elapsed=26.61, tpsR=152.34, tpsE=151.39, tpsD=67.15
2025-12-11 21:45:49,149 -- [INFO] (Worker-10 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=2028, residence=0.00, elapsed=44.95, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,152 -- [INFO] (Worker-12 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=0, residence=0.00, elapsed=0.00, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,152 -- [INFO] (Worker-04 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=2, residence=0.00, elapsed=0.02, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:49,152 -- [INFO] (Worker-15 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=0, residence=0.00, elapsed=0.00, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:50,126 -- [INFO] (Worker-06 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=12669, residence=0.00, elapsed=60.00, tpsR=0.00, tpsE=0.00, tpsD=0.00
2025-12-11 21:45:50,132 -- [INFO] (Worker-01 ): cycle=1, scale=1, dbsize=0.014465, done=0, errors=2, residence=0.00, elapsed=0.02, tpsR=0.00, tpsE=0.00, tpsD=0.00

To reproduce:

  • Take the dsbench software and unpack
  • Look at INSTALL instructions - at the end I added some notes to use a venv
    instead of installing system packages
  • MANUAL gives you more info about dsbench
  • Activate your venv (source venv/bin/activate)
  • Execute dsbench using fdr.conf configuration file (which uses "firebird-diver")
    python dsbench.py -f fdr.conf
  • To activate "fdb" instead, open fdr.conf and change the line:
    self.job.fbdriver = "fdr"
    to:
    self.job.fbdriver = "fdb"

Regards
Mathias

dsbench.tar.gz

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions