In general, I try to work with short-lived locks where I can do an entire unit of work in a single (serializable) transaction; this avoids the need for an additional locking mechanism, as the db locks will do everything needed.
When working with long-lived locks:
It is a bad idea to use rdbms-locks for that purpose - it simply doesn't scale. Timestamp or row-version columns are a good way of doing optimistic concurrency to prevent against accidental over-writing.
To publish / enforce the fact that a row is being edited, I would store the user-id/user-name of the locking user in a column (null if not locked). This makes it clear who owns the row - i.e. when you want to edit the row, first UPDATE it, setting your user-id (and ensuring that it isn't already locked).
To cope with locks that aren't removed correctly (because of a dead terminal etc) there are 3 common options:
- when the lock owner logs in again, allow them to break their own locks
- allow an administrator to break the user's locks
- store a lock-timeout column (datetime), and have a scheduled task automatically unlock rows that are overdue
So to summarise - consider something like:
Foo
===
Id | ...data... | Timestamp | LockOwner | LockTimeout
---+------------+-----------+-----------+------------
etc