When does “select for update” lock and unlock?

Locks are taken during (usually at or near the beginning of) a command’s execution. Locks (except advisory locks) are released only when a transaction commits or rolls back. There is no FOR UNLOCK, nor is there an UNLOCK command to reverse the effects of the table-level LOCK command. This is all explained in the concurrency control section of the PostgreSQL documentation.

You must commit or rollback your transaction to release locks.

Additionally, it doesn’t really make sense to ask “has this row already been deleted by another concurrent transaction”. It isn’t really deleted until the transaction that deleted the row commits… and even then, it might’ve deleted and re-inserted the row or another concurrent transaction might’ve inserted the row again.

Are you building a task queue or message queue system by any chance, because if so, that problem is solved and you shouldn’t be trying to reinvent that unusually complicated wheel. See PGQ, ActiveMQ, RabbitMQ, ZeroMQ, etc. (Future PostgreSQL versions may include FOR UPDATE SKIP LOCKED as this is being tested, but hasn’t been released at time of writing).

I suggest that you post a new question with a more detailed description of the underlying problem you are trying to solve. You’re assuming that the solution to your problem is “find out if the row has already been deleted” or “unlock the row”. That probably isn’t actually the solution. It’s a bit like someone saying “where do I buy petrol” when their push-bike doesn’t go so they assume it’s out of fuel. Fuel isn’t the problem, the problem is that push bikes don’t take fuel and you have to pedal them.

Explain the background. Explain what you’re trying to achieve. Above all else, don’t post pseudocode, post the actual code you are having problems with, preferably in a self-contained and runnable form.

Leave a Comment