Subject | Re: [firebird-support] Unsuccessful execution error |
---|---|
Author | Helen Borrie |
Post date | 2006-05-19T22:25:43Z |
At 07:20 AM 20/05/2006, you wrote:
full server with respect to transaction isolation. But you're on the
wrong track if you think that update conflicts cause the AVs when you
attempt to multi-thread a connection.
The cause of the AVs is in the memory structures that the client uses
to manage the "handles" by which it references stuff and manages the
contexts of its connections. The client's "base session", which is a
thread, consists of one connection to each of one or more databases,
a moving cloth of transactions involving those connections and
another moving cloth of execution requests within the (separate)
contexts of those transactions. So, execution of a request occurs
within a "session" consisting of one connection (or more, if
multi-database transactions are potentially involved) and one transaction.
The key point here is that the client has to *know* which
connection(s) a transaction and its associated requests belong
to. Inside its own thread ("base session"), no problem.
But if your application spawns another thread containing execution
requests that refer to the handles in the base thread, you have
created the conditions for memory protection faults. It is your
*application* that is doing this damage, since the API layer - the
client library - isn't threadable. If the application creates a
thread that doesn't have a complete context (connection[s],
transaction[s] belonging to that [those] connections and requests
within that [those] transactions, then you have made trouble.
So the rule must be: if you spawn threads that do data access, make
each thread an isolated session between the client and the
database[s]. Create a session (connection[s], transaction[s] and
sets) purely within the thread and destroy them before the thread terminates.
superserver or whatever. The system is designed to prevent duplicate
keys. It's up to the database designer to provide safe ways to
ensure that keys are not prone to duplication. Generators
(sequences) are provided for this purpose. Any model of key
generation that relies on the existing values in the table is poison
for a transactional database, threading or no threading.
as a workaround for bad programming and bad database design. The
solution is to fix the programs and the design.
rare. And pessimistic locking doesn't solve the memory fault
conditions created by trying to reference the context of one thread
from another thread.
transactional control is the generation of sequences from generators.
thread (list thread) with an appropriate Subject and try to describe
what you have experienced that leads you to believe this.
the embedded engine so far", one has to suspect that you're bumping
into problems trying to use the embedded engine as a back-end to
development. The embedded engine is not intended for this. It is a
deployment model.
./heLen
>Rik Barker wrote:Well, it's true of course. Embedded is absolutely no different to a
> > Hi,
> >
> > Thanks to everyone who replied. Giving each thread its own connection
> > fixed the problem perfectly.
>
>Ahh, this is exactly what I was thinking about. Consider the following
>sequence:
>
>Thread 1 Thread 2
>================= =======================
>Start Transaction
> Start Transaction
> Select keys
> Insert key "1"
>Select keys
> Commit
>Insert key "1"
>Fails
>
>At the point where thread 1 queries the keys, thread 2 hasn't committed
>the newly inserted key "1", so thread 1 doesn't see it. Hence thread 1
>assumes it can insert the same key, but fails when it tries to do so.
>This is the sort of thing one can run into generally, i.e. not just with
>embedded although when using the embedded engine you have more
>possibilities for working around it (see below).
full server with respect to transaction isolation. But you're on the
wrong track if you think that update conflicts cause the AVs when you
attempt to multi-thread a connection.
The cause of the AVs is in the memory structures that the client uses
to manage the "handles" by which it references stuff and manages the
contexts of its connections. The client's "base session", which is a
thread, consists of one connection to each of one or more databases,
a moving cloth of transactions involving those connections and
another moving cloth of execution requests within the (separate)
contexts of those transactions. So, execution of a request occurs
within a "session" consisting of one connection (or more, if
multi-database transactions are potentially involved) and one transaction.
The key point here is that the client has to *know* which
connection(s) a transaction and its associated requests belong
to. Inside its own thread ("base session"), no problem.
But if your application spawns another thread containing execution
requests that refer to the handles in the base thread, you have
created the conditions for memory protection faults. It is your
*application* that is doing this damage, since the API layer - the
client library - isn't threadable. If the application creates a
thread that doesn't have a complete context (connection[s],
transaction[s] belonging to that [those] connections and requests
within that [those] transactions, then you have made trouble.
So the rule must be: if you spawn threads that do data access, make
each thread an isolated session between the client and the
database[s]. Create a session (connection[s], transaction[s] and
sets) purely within the thread and destroy them before the thread terminates.
>Also note that at some transaction isolation levels, even if thread 2As designed.
>had committed by the time thread 1 queries the keys, thread 1 still
>wouldn't see the key "1" because its transaction started before thread
>2's transaction.
>One (good) solution in such cases is not to rely on querying the keys,This applies in any case, it's not confined to embedded or
>but to use a sequence to generate the keys instead.
superserver or whatever. The system is designed to prevent duplicate
keys. It's up to the database designer to provide safe ways to
ensure that keys are not prone to duplication. Generators
(sequences) are provided for this purpose. Any model of key
generation that relies on the existing values in the table is poison
for a transactional database, threading or no threading.
>Another (not soNo. There is no need to cripple the features of the database engine
>good) solution is to use some form of locking to make sure the thread's
>transactions don't overlap. When using the embedded engine, one could
>use a critical section when a thread enters a transaction to ensure only
>one transaction is active at any given time.
as a workaround for bad programming and bad database design. The
solution is to fix the programs and the design.
>Not a great method, and it rather defeats the purpose of using multipleThe circumstances where pessimistic locking is useful are very
>threads, but in some circumstances it can be a useful method.
rare. And pessimistic locking doesn't solve the memory fault
conditions created by trying to reference the context of one thread
from another thread.
>Another thing I've run into when using the embedded engine is that DDLQuite untrue. The only thing in Firebird that is not subject to
>statements (like CREATE TABLE) don't seem to be under transactional
>control (or at least, not fully?).
transactional control is the generation of sequences from generators.
>I'm not sure if this is a feature/bug of Firebird in general (i.e.It's doesn't exist, as either a feature or a bug. Create a new
>not just the embedded engine)
thread (list thread) with an appropriate Subject and try to describe
what you have experienced that leads you to believe this.
>and/or whether this behavior exists in Firebird 2 as I've onlyIt doesn't exist in v.1.5 or v.2.0. If you have only "played with
>played with the
>1.5 embedded engine so far.
the embedded engine so far", one has to suspect that you're bumping
into problems trying to use the embedded engine as a back-end to
development. The embedded engine is not intended for this. It is a
deployment model.
>That said, I'm still hugely impressed with the embedded engine. ForBut not useful or recommended in a development environment....
>something a little under 2Mb it's a seriously impressive piece of kit
>with all manner of interesting uses :-)
./heLen