Re: Small PosgreSQL locking function request - with bounty
От | Ralf Schuchardt |
---|---|
Тема | Re: Small PosgreSQL locking function request - with bounty |
Дата | |
Msg-id | 3CEA077E-FB3E-4D4F-9FAF-DB45FA8E32F2@gmx.de обсуждение исходный текст |
Ответ на | Re: Small PosgreSQL locking function request - with bounty (David Noel <david.i.noel@gmail.com>) |
Список | pgsql-general |
Am 13.09.2013 um 18:47 schrieb David Noel <david.i.noel@gmail.com>: >> ...have you used the "for update" clause in your select statements? > > Hi Ralf, thanks for the reply. I was unaware of the "for update" > construct. Thank you! > >> My understanding is, that "for update" does what you need. > [...] > My question is: according to the documentation, it seems > that SELECT FOR UPDATE may still run into the same concurrency issue. > If two concurrent transactions select the same row, the first will be > given the lock. The second transaction will encounter the lock and be > forced to wait. The update from the first transaction will occur, the > lock will be released, and control will be passed to the second > transaction. According to the documentation, the row will already have > been selected, so the transaction, it seems, will continue processing > the row as if it were marked "Inactive". In essence, the way I read > it, it won't care that the row had been updated by the first > transaction, and so essentially I will be running into the same > problem I'm facing now. Am I reading this correctly? No, I think it will work. The part "and will then lock and return the updated row" does not mean, that the select criteriais not rechecked. Let's try it. Two clients: -- > Client 1 locktest=# create table locktest (id serial primary key, state int2); CREATE TABLE locktest=# insert into locktest values (1, 0), (2, 0); INSERT 0 2 locktest=# select * from locktest; id | state ----+------- 1 | 0 2 | 0 (2 rows) locktest=# begin; BEGIN locktest=# select * from locktest where state = 0 limit 1 for update; id | state ----+------- 1 | 0 (1 row) -------------- WAIT HERE IN CLIENT 1 -- > Client 2 locktest=# begin; BEGIN locktest=# select * from locktest where state = 0 limit 1 for update; ------------- Client 2 waits for a lock -- > Client 1 locktest=# update locktest set state = 1 where id = 1; UPDATE 1 locktest=# commit; COMMIT -- > Client 2 id | state ----+------- 2 | 0 (1 row) [...] You only have to take care, that the UPDATE really only updates the selected row. An URL as a primary key might work, but might not be the best choice. Ralf
В списке pgsql-general по дате отправления: