Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
postgresql_management_locking [2020/01/20 11:59] – andonovj | postgresql_management_locking [2020/01/20 20:36] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 8: | Line 8: | ||
* Table Locks | * Table Locks | ||
* Row Locks | * Row Locks | ||
+ | * Advisory Locks | ||
Let's start with the Table Locks | Let's start with the Table Locks | ||
Line 44: | Line 45: | ||
{{ : | {{ : | ||
+ | =====Advisory Locks===== | ||
+ | PostgreSQL provides a means for creating locks that have application-defined meanings. These are called advisory locks, because the system does not enforce their use — it is up to the application to use them correctly. Advisory locks can be useful for locking strategies that are an awkward fit for the MVCC model. For example, a common use of advisory locks is to emulate pessimistic locking strategies typical of so-called "flat file" data management systems. While a flag stored in a table could be used for the same purpose, advisory locks are faster, avoid table bloat, and are automatically cleaned up by the server at the end of the session. | ||
+ | |||
+ | ======Monitoring====== | ||
+ | To monitor the Locks, PostgreSQL provided us with couple views which we can use: | ||
+ | |||
+ | ====Row Locks (Blocking==== | ||
+ | The following query may be helpful to see what processes are blocking SQL statements (these only find row-level locks, not object-level locks). | ||
+ | <sxh bash> | ||
+ | SELECT blocked_locks.pid | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | JOIN pg_catalog.pg_stat_activity blocked_activity | ||
+ | JOIN pg_catalog.pg_locks | ||
+ | ON blocking_locks.locktype = blocked_locks.locktype | ||
+ | AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE | ||
+ | AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation | ||
+ | AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page | ||
+ | AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple | ||
+ | AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid | ||
+ | AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid | ||
+ | AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid | ||
+ | AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid | ||
+ | AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid | ||
+ | AND blocking_locks.pid != blocked_locks.pid | ||
+ | JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid | ||
+ | </ | ||
+ | |||
+ | Setting application_name variable in the begging of each transaction allows you to which logical process blocks another one. It can be information which source code line starts transaction or any other information that helps you to match application_name to your code. | ||
+ | If you want to include the application name, use: | ||
+ | |||
+ | |||
+ | <sxh bash> | ||
+ | SET application_name=' | ||
+ | SELECT blocked_locks.pid | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | JOIN pg_catalog.pg_stat_activity blocked_activity | ||
+ | JOIN pg_catalog.pg_locks | ||
+ | ON blocking_locks.locktype = blocked_locks.locktype | ||
+ | AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE | ||
+ | AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation | ||
+ | AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page | ||
+ | AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple | ||
+ | AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid | ||
+ | AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid | ||
+ | AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid | ||
+ | AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid | ||
+ | AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid | ||
+ | AND blocking_locks.pid != blocked_locks.pid | ||
+ | JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid | ||
+ | WHERE NOT blocked_locks.GRANTED; | ||
+ | </ | ||
+ | |||
+ | Here's an alternate view of that same data that includes an idea how old the state is | ||
+ | <sxh bash> | ||
+ | SELECT a.datname, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | a.pid | ||
+ | FROM pg_stat_activity a | ||
+ | JOIN pg_locks l ON l.pid = a.pid | ||
+ | ORDER BY a.query_start; | ||
+ | </ | ||
+ | |||
+ | For PostgreSQL older than 9.0: | ||
+ | <sxh bash> | ||
+ | SELECT a.datname, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | FROM pg_stat_activity a | ||
+ | JOIN pg_locks | ||
+ | JOIN pg_class | ||
+ | ORDER BY a.query_start; | ||
+ | </ |