I'd like to store a number in my Firebird database that indicates the revision of its structure. The number is supposed to be updated only when the structure has successfully been altered by some migration script. Therefore the storage mechanism needs to be transaction sensitive, which is why I cannot use a generator. The alternative I considered was to define a stored procedure which returns the number, and alter its definition in a transaction, but that as well seems to survive a rollback. What options do I have, not using a table?
Storing a transaction sensitive constant in Firebird
firebird
Related Solutions
The problem is twofold:
First Firebird 3 uses tighter security and has the old authentication mechanism disabled by default. So clients depending on older connection libraries will not work out of the box.
To allow the old authentication mechanism to work, the following setting needs to be set in firebird.conf:
AuthServer = Legacy_Auth, Srp, Win_Sspi
(be sure to remove the #
prefix)
Second, the pure-java wire protocol implementation of Jaybird (the Firebird JDBC driver) uses an outdated authentication mechanism that is not supported by this Legacy_Auth
option. Using Jaybird to connect to Firebird 3 at this time will only work if you use the native option (with the jdbc:firebirdsql:native:
URL-prefix and jaybird2x.dll and fbclient.dll).
Addendum 1
Firebird 3 (since Alpha 1) has now also implemented the old authentication method used by Jaybird, so Jaybird will now also work without using the native library (as long as the legacy authentication is enabled, and the user has been setup with the legacy usermanager).
See also Jaybird and Firebird 3
Addendum 2
Jaybird 3 and higher support the more secure Srp authentication model out of the box, and Jaybird 3.0.4 introduced support for the wire protocol encryption. This means that it can connect to Firebird 3 without additional configuration.
There are a number of things you need to know when using the monitoring tables:
- The monitoring tables (like
MON$STATEMENTS
) provides you a list of the active or prepared statements at the time a query was run. - The query result stays stable until the transaction is committed! This means that repeatedly executing the query without committing will not yield new information.
- Only
SYSDBA
, the databaseowner or a user with roleRDB$ADMIN
can see all information, other users can only see information about their own connections. - Your Firebird installation contains basic documentation on the tables in
doc/README.monitoring_tables.txt
Now as to your screenshot: all statements are from the same connection (your own): MON$ATTACHMENT_ID = 1521
. Only one statement is currently active (MON$STATE = 1
) and participating in transaction MON$TRANSACTION_ID = 90964
and was started at 2012-12-06 10:08 (MON$TIMESTAMP
), the rest is inactive (MON$STATE = 0
) and therefor has no transaction-id and timestamp. The first statement is also the only one that currently has an actual query (MON$SQL_TEXT
), which is the query that actual produced the result in the screenshot. In Firebird statements are allocated separately from the actual query to be executed using that statement.
That is not much, but if you had joined to MON$RECORD_STATS
, MON$IO_STATS
or MON$MEMORY_USAGE
based on MON$STAT_ID
you would have received statistics on the query (ie the number of reads, records update, number of pages read or written, memory use). The monitoring tables show information at a specific moment in time, and if a query has already finished when you execute it, you don't get any info (I am not 100% sure, but it might remain available until the next execute of a statement, or until the statement is unprepared or closed).
If instead you need a stream of information and statistics, than you might get more out of the Firebird Trace API. I haven't used it much myself yet, but the article Audit and Trace Services in Firebird 2.5 by Thomas Steinmauer provides a good introduction to it.
In your question you say you expected 'more content', but didn't actually specify what content you need or expected; I hope this provides sufficient info.
Best Answer
I think you can use Database trigger which fires on
TRANSACTION COMMIT
. However, you need to react only to those commits caused by the "upgrade script" so you need to set up an flag to indicate it. For that you could set an context variable inUSER_TRANSACTION
namespace. Ie your script would look like thisNow the database trigger can check for the
IncrementVersion
context variable and act accordinglyHere trigger uses generator (aka sequence) named "GEN_DB_Version" to "store" the version number.
If you use
COMMIT WORK
statements in your script you have to make the system more complicated, either set up additional flags to ignore those commits in the middle of the script or set the flag up right before final commit or perhaps some third way - it all depends on what "side effects" you want to use.