Fix for many lock problems - Mailing list pgsql-hackers
From | Bruce Momjian |
---|---|
Subject | Fix for many lock problems |
Date | |
Msg-id | 199801232109.QAA15027@candle.pha.pa.us Whole thread Raw |
List | 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@candle.pha.pa.us
pgsql-hackers by date: