uwiger / locks

A scalable, deadlock-resolving resource locker
Mozilla Public License 2.0
205 stars 26 forks source link

read vs write locks #22

Closed benoitc closed 8 years ago

benoitc commented 8 years ago

I have a quick question corresponding to the way locks are shared or exclusive.

Suppose I have write locks on [Resource, OID] and requesting a read lock on [Resource]. Will the clients be able to handle reads while the client that requested a write is modifying the resource? Or the write lock will exclude all reads on the resource?

uwiger commented 8 years ago

A write lock on [Resource, OID] implies an indirect write lock also on [Resource] and on all [Resource, OID|_]. So supposing that the owner of the write lock tries to read [Resouce], it will be no problem, since it already has an indirect write lock on it - provided there are no other write locks underneath [Resource]

... At this point, I discovered that the implementation is actually buggy. Let me try to fix the bugs and get back to you. ;-)

benoitc commented 8 years ago

OK :) What I wanted to do is allowing others to read/write objects on [Resource | _ ] and only locking [Resource, OID | _] if someone write on [Resource, OID]. If I understand correctly it is not possible with the current algorithm, right?

uwiger commented 8 years ago

Uhm, what I noticed was that the surrender algorithm doesn't handle indirect locks well enough, and also that there was a special case where a lock could appear to have two write (indirect) entries. This can happen due to indirect lock propagation and should be interpreted as 'no lock'.

Anyway, assuming that you have the following locks: A1: [a,1]: write A2: [a,2]: write

This is perfectly fine. If e.g. A1 would attempt to read-lock [a], it would have to wait for A2 to release [a,2]. Meanwhile, A2 has an implied write lock on all [a, 2 | _], etc. No lock entries are created for implied locks until there is contention for one (well, there can sometimes be some 'unnecessary' indirect locks, since the algorithm tries to be lazy about it, and doesn't go out of its way to remove them.)

Does this answer your question?

benoitc commented 8 years ago

hrm not sure, the case:

A1: [a, 1]: read A2: [a, 2]: write

would not be possible right?

uwiger commented 8 years ago

That should absolutely work.

uwiger commented 8 years ago

I merged the PR above into master.

benoitc commented 8 years ago

Thanks! Rereading my previous comment, what I wanted to try is the following:

t0      A1: [a, 1]: read  shared       A2: [a, 2]: write

Ie having someone reading [a, 1] while another is writing on [a, 2] at the same time. Would it be possible?

Also not sure to understand what happen in the following scenario:

t0      A2: [a, 2]: start_transaction, write lock           
t1      A1: [a, 1]: start_transaction, read  lock shared 
t2      A2: [a, 2]: end transaction
t3      A1: [a, 1]: end transaction

Is this possible. Or A1 will wait for A2 to release all locks?

uwiger commented 8 years ago

This would not be problematic. The two locks don't interfere with each other. The bug I identified only happened if both t1 and t2 try to explicitly address [a] (compare this to having object locks ([a,1] and [a,2] respectively) and then trying for a table lock ([a]).

benoitc commented 8 years ago

hrm ok so I don't understand this part in the readme:

To wit, if an agent A takes a lock on [a, b], and it is granted, it will indirectly lock [a]. If another agent B tries to lock [a, b, c] while A holds [a, b], the locks_server will infer that A also indirectly locks [a, b, c].

Anyway just another question if you don't mind :) Is this possible to do the following?:

T  Client 1 Client2
t0 A1: [a, 1] exclusive write
t1  write  A2: [a] read shared
t2  read something
t3  A1: [a, 1] unlock exclusive write  A2: [a] unlock read

What I am trying to achieve is having multiple readers on a db instance and 1 writer for a Key with reads happening while the write is processed. READs can happen concurrently using a classic MVCC or MCC model. I only need to share a lock between them so I can put the db offline when needed. In short

READS : shared lock on [Db]
WRITES: exclusive lock on [Db, Key]

Hopefully it's possible with Locks :)

uwiger commented 8 years ago

To wit, if an agent A takes a lock on [a, b], and it is granted, it will indirectly lock [a]. If another agent B tries to lock [a, b, c] while A holds [a, b], the locks_server will infer that A also indirectly locks [a, b, c].

Yes, and in the locks implementation, the queue of a lock may contain 'indirect' entries. The way to understand this is to compare with table and object locks, except that in locks, it's generalized into a hierarchy. A regular database table a could be represented as [db, a], and objects 1, 2 and 3 would be represented as [db, a, 1], [db, a, 2]`, ... respectively. The 'indirect' locks are not specific claims per se, but come into play if someone explicitly claim a lock.

For example, write locks on [db, a, 1] (say transaction t1) and [db, a, 2] (t2) can coexist just as they would in any DBMS. They both put an 'indirect' write lock on [db, a]. Note that these indirect locks are not exclusive; they just preclude any explicit write lock on [db, a], and if either t1 or t2would try to claim [db, a], they would have to wait for the other indirect lock to go away. The same line of reasoning holds for anyone trying to claim a lock on the whole database [db], of course.

OTOH, if [db, a, 1] and [db, a, 2] are read locks, it would be perfectly fine for anyone to claim a read lock on [db, a] or [db]. Indirect read locks don't preclude direct read locks on the same resource, but a read lock on [db, a] would block a write lock on [db, a, 1].

If what you want is multi-version concurrency control (MVCC), then locks doesn't support it - at least not without some extra logic.

But if what you want is to be able to do concurrent reads and writes on e.g. children of [a], and occasionally claim a lock on [a], which is put into the queue and served as existing child locks go away, and meanwhile forcing new lock requests to wait, then this can be readily done.

benoitc commented 8 years ago

@uwiger thanks a lot for the explanation, it helps a lot. MVCC is already handled here, what I really want is the second part I guess. Anyway thanks again, i didn't understood what were indirects locks until now. Closing the issue then :+1:

uwiger commented 8 years ago

And thanks for giving me the opportunity to identify and fix some bugs! :)