Search Postgresql Archives

Re: Transactions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Saturday 18 March 2006 12:31, Florian G. Pflug wrote:
> Kevin Brown wrote:
> > I've been creating a databased application with PostgreSQL for a while
> > now and have loved it, though we just recently stumbled on an interesting
> > bug.
> >
> > I have a particular dialog which can do all kinds of incredibly
> > complicated things to the database.  Of course I didn't want to have to
> > write the "undo it to the database" code, nor did I want to force the
> > user into being screwed with a stray click.
> >
> > So when the dialog opens, it executes a BEGIN, and then based on whether
> > they clicked ok or cancel on the dialog, it'd COMMIT or ROLLBACK.  This
> > worked fine for me in testing, but now that I have two people using this
> > app simulatneously, if they both click on ok at the same time, postgres
> > seemingly deadlocks.  My setup is such that I have n ruby clients talking
> > with DRb to another ruby process on the server, which then does all the
> > communication to postgres.  Each user has his/her own database
> > connection.
>
> What ruby database library are you using?

The C extension.

> Since ruby doesn't use native threads, but instead implements it's own
> threads (purely in user-space), one thread can block your whole app - e.g,
> if the thread tries to read from a socket where not data is available, and
> therefor the kernel puts the process to sleep until data becomes available.
>
> For the "normal" read() and write() operations exposed to the ruby
> programming this is solved internally by ruby (it checks the
> filedescriptions state, and only reads if the read won't block). But
> extensions, especially the ones talking over the network, like the postgres
> client, can still cause this problem. In the "raw" postgres client
> extension for ruby, you'll find two methods that can execute a query -
> query() and query_async(). query() will block the _whole_ ruby interpreter
> until query results are available, while query_async() will block only the
> thread that executed the query.

Yes, but my question is why is the query unable to complete.

> This one-thread-blocks-all behaviour can lead to "interesting" dead-locks.
> Assume, for example, the following situation, with A and B being two ruby
> threads. A1) update table where id=1
> B1) update table where id=1
> -----
> B2) commit
> A2) commit
>
> Now, the query B1 will block until A2 is executed (because the record is
> already locked). But if B1 blocks, and you used query() instead of
> query_async(), then the _whole_ ruby interpreter is blocked, and therefor
> A2 will never be executed. Bingo! you got a deadlock, and postgres has no
> chance to ever detect this.

So what you're saying is that my commits and rollbacks should be async, 
correct?

> Of course, not using threads makes the problem even worse - the only
> solution is to use the _async() functions. DBI lets you set a flag (forgot
> it's name) that forces DBD::Pg to use the _async() functions - if you don't
> use DBI just replace all calls to query() and exec() with query_async() and
> exec_async().

I don't quite understand how a select can be an async call....  I need the 
data to proceed.  If you're saying on my inserts, deletes, etc, then that I 
can understand.

> greetings, Florian Pflug


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux