Default transanction isolation level in PHP for Firebird
I was hunting some problem in PHP application and thanks to Trace API in Firebird I found terrible default value in PHP. What value? It’s the default transaction isolation level value. In 99% of languages/environments in something close to read committed. But not in PHP.
Let’s have a look at it. If you start a new transaction (or if one is started internally, where you cannot change the isolation level) where you don’t explicitly specify isolation level the IBASE_DEFAULT
is used. But this is IBASE_WRITE|IBASE_CONCURRENCY|IBASE_WAIT
. This is read-write wait transaction in concurrency mode. This mode is most restrictive, nothing close to read committed. And to make it worse, there’s no way to change this default value in runtime. You can only do it recompiling sources, nothing to be viable in most cases.
So how to solve it? Well, if you created yourself some abstraction layer over ibase_xxx
/fbird_xxx
function you’ll change it there and you’re done. If not, you’re screwed. 😃 OK, just kidding. You can play with override_function
to override fbird_query
, fbird_prepare
etc., but when you’re in it, maybe it’s time to create simple thin abstraction. That’s what I did. Find & Replace worked for changing the actual code. 😃 For the rest I created simple functions like DbQuery
, DbPrepare
etc. These functions take the transaction, which was created by another function DbTransaction
and stored (i.e. in $GLOBALS
, dirty right? 😎), when first needed (and then used until commit/rollback or end of the page’s life).
function DbQuery()
{
$args = func_get_args();
array_unshift($args, $GLOBALS['tx']);
return call_user_func_array('fbird_query', $args);
}
It’s nothing special, only few small pieces to make to together work. First the function doesn’t declare any input parameters, but in fact there are some. Yeah, dynamic languages. I get these via func_get_args
, then push to the first position the transaction to use (here I’m using the dirty $GLOBALS
😉). Finally I use call_user_func_array
to call fbird_query
. Function fbird_query
takes variable number of arguments so it’s not easy to call it directly with parameters in array as I have. I have to thank people in firebird-php mailing list, because I completely forgot about it, though I’m using exactly the same at other places in same project. Return values are same as from fbird_query
, so you can then start fetching rows and so on (and it’s also good idea to create wrappers for these too, who knows what will strike in the future).
Remember Firebird and PHP is a good combination.