The granularity is literally the name of the lock. It's not attached to anything else in the DB. You get to define what the lock means in your code. If you use Django/Python + Postgres, here's an example of a nice abstraction on top of it: https://pypi.python.org/pypi/django-pglocks/1.0.1
Think of these locks as mutexes in threaded code: they don't mean anything on their own, but they simply guard against the rest of your code. Contrived semi-pseudocode example:
def add_item_to_cart(order, item):
try:
lock = acquire_named_lock('order-{}'.format(order.id), timeout=10)
order.add_item(item)
order.recalculate_total()
order.save()
lock.release()
except LockTimeoutError:
raise OrderUpdateError('Timed out trying to add item to order.')
def checkout(order):
try:
lock = acquire_named_lock('order-{}'.format(order.id), timeout=10)
order.pay()
order.generate_and_email_invoice()
order.print_shipping_label()
order.save()
lock.release()
except LockTimeoutError:
raise OrderUpdateError('Timed out trying to check out.')
Note that the two functions will never step on each others' toes because the first thing they do is acquire a lock.