Fix for many lock problems

From: Bruce Momjian <maillist(at)candle(dot)pha(dot)pa(dot)us>
To: hackers(at)postgreSQL(dot)org (PostgreSQL-development)
Subject: Fix for many lock problems
Date: 1998-01-23 21:09:57
Message-ID: 199801232109.QAA15027@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I am submitting this patch for people to review.

It fixes several problems in the lock manager. Let me show you how to
reproduce them. Try this before applying the patch and you will see the
old bugs.

First, set up three psql sessions. Do a 'begin;' in each one to start a
transaction.

---------------------------------------------------------------------------

OK, pick a single table to use. In the first one, do an UPDATE, in the
second psql session, do an UPDATE, in the third, do an UPDATE. Now, do
'end;' in the first psql, and you will find the third finishes, even
though the second was first to request the lock.

---------------------------------------------------------------------------

OK, exit all your psql's, and start them again, with a 'begin;' for
each.

Do an UPDATE in the first, a SELECT in the second, and an UPDATE in the
third, in that order. Now do an 'end;' in the first. The second
completes, even though the write should have higher priority over a read
WHEN THEN ARE BOTH ASLEEP waiting for a lock.

---------------------------------------------------------------------------

OK, exit all your psql's, and start them again, with a 'begin;' for
each.

Now, do a SELECT in the first, and UPDATE in the second, and a SELECT in
the third. The third completes right away, even though it should wait
behind the higher-priority second UPDATE and not share the existing
lock.

---------------------------------------------------------------------------

The following patch fixes this. The proc.c priority queue condition was
backwards, and did not put newer requesters behind older requesters.
The lock.c change adds code to check the wait queue and not allow
sharing a lock if someone of higher priority is waiting for it.

This should eliminate writer starvation in 6.3, and fix other problems
people might have been experiencing with this buggy behavior.

This will be in 6.3. I will apply it now.

Comments?

---------------------------------------------------------------------------

*** ./backend/storage/lmgr/lock.c.orig Fri Jan 23 01:01:03 1998
--- ./backend/storage/lmgr/lock.c Fri Jan 23 15:59:06 1998
***************
*** 708,713 ****
--- 708,727 ----
result->nHolding = 0;
}

+ {
+ /* ------------------------
+ * If someone with a greater priority is waiting for the lock,
+ * do not continue and share the lock, even if we can. bjm
+ * ------------------------
+ */
+ int myprio = ltable->ctl->prio[lockt];
+ PROC_QUEUE *waitQueue = &(lock->waitProcs);
+ PROC *topproc = (PROC *) MAKE_PTR(waitQueue->links.prev);
+
+ if (waitQueue->size && topproc->prio > myprio)
+ return STATUS_FOUND;
+ }
+
/* ----------------------------
* first check for global conflicts: If no locks conflict
* with mine, then I get the lock.
*** ./backend/storage/lmgr/proc.c.orig Fri Jan 23 14:34:27 1998
--- ./backend/storage/lmgr/proc.c Fri Jan 23 15:22:11 1998
***************
*** 469,475 ****
proc = (PROC *) MAKE_PTR(queue->links.prev);
for (i = 0; i < queue->size; i++)
{
! if (proc->prio < prio)
proc = (PROC *) MAKE_PTR(proc->links.prev);
else
break;
--- 469,475 ----
proc = (PROC *) MAKE_PTR(queue->links.prev);
for (i = 0; i < queue->size; i++)
{
! if (proc->prio >= prio)
proc = (PROC *) MAKE_PTR(proc->links.prev);
else
break;

--
Bruce Momjian
maillist(at)candle(dot)pha(dot)pa(dot)us

Browse pgsql-hackers by date

  From Date Subject
Next Message Jan Vicherek 1998-01-23 21:50:29 Show stopper ? (was: Re: "cruising" or "browsing" through tables using an index / ordering)
Previous Message The Hermit Hacker 1998-01-23 19:56:11 Re: [QUESTIONS] Re: [HACKERS] Re: [PORTS] Important Announcement