The thread-safety issues when database connections are
shared among threads have been well-documented for years, and as threading
becomes more widespread a number of famous libraries have been affected. While
it is good practice to close database connections as soon as possible, an
application can have many database connections open, and connections can be
shared across threads.
The following considerations are planned for the
PyrrhoLink/OSPLink implementations in C# and Python from version 5.4. They
provide some protection from unsafe coding, and operations will only block
while the connection is busy in another thread.
ADO.Net
Many complications involving ADO.NET such as
DependentTransactions are irrelevant in Pyrrho because of strong transaction
isolation and serialisation.
1.
We need to enforce only one ongoing transaction
per connection. The situation is really likely only to arise if the connection
is shared between threads, so a call to BeginTransaction should block until the
connection is available. If it is the same thread it is probably a programmer
mistake (nested or parallel transactions are not supported) and an exception
should be raised.
2.
We need to enforce only one open reader per
connection. In the single threaded case (or on the same thread), this likely to
be a misunderstanding by the programmer (ADO.NET allows only one active reader
per connection), and an exception should be raised. Otherwise, the call should
block until the connection is available.
3.
We should definitely disallow the sharing of
commands between threads because IDbCommand methods can set up the command
text, parameters etc and it is easy to see that conflicts could arise. Each IDbCommand
should be specific to a given thread, but a connection can have many commands.
4.
When a command is executed, the call should
block until the connection is available, as the connection might be busy in
another thread.
5.
We should disallow the sharing of readers
between threads, because of possible races with Read(), data fetching, and
RdrClose(). We will associate each reader with the command’s thread, and cross-thread
access should raise an exception.
Python
Similar blocking and safety measures will be added to the
Python library OSPLink.
Act() and Versioned objects
At first sight, connection.Act(s) looks atomic and
thread-safe, but the changes it makes could interfere with open Readers in the
same connection. So its internal use of Command execution should make it comply
with the same protocol.
Versioned objects do not use Command, but need to be subject
to the same restrictions about the Connection being used. It is okay to use a
versioned object in another Connection, but if that connection is busy in
another thread, an operation such as Update or Delete will block until the
connection is available. Versioned objects can easily be used in client-side
cursor simulations.
REST
The REST API is unaffected by all the above because each
call is effectively in a new Connection.
Comments from the community are welcome.
Comments from the community are welcome.
No comments:
Post a Comment