pg-lock-tracer 0.5.5__tar.gz → 0.6.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pg_lock_tracer-0.5.5/src/pg_lock_tracer.egg-info → pg_lock_tracer-0.6.1}/PKG-INFO +79 -8
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/README.md +78 -7
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/setup.cfg +1 -0
- pg_lock_tracer-0.6.1/src/pg_lock_tracer/__init__.py +1 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/animate_lock_graph.py +12 -2
- pg_lock_tracer-0.6.1/src/pg_lock_tracer/bpf/pg_row_lock_tracer.c +121 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/helper.py +56 -1
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/oid_resolver.py +1 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/pg_lock_tracer.py +149 -69
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/pg_lw_lock_tracer.py +12 -19
- pg_lock_tracer-0.6.1/src/pg_lock_tracer/pg_row_lock_tracer.py +372 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1/src/pg_lock_tracer.egg-info}/PKG-INFO +79 -8
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/SOURCES.txt +2 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/entry_points.txt +1 -0
- pg_lock_tracer-0.5.5/src/pg_lock_tracer/__init__.py +0 -1
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/LICENSE +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/pyproject.toml +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/setup.py +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/bpf/__init__.py +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/bpf/pg_lock_tracer.c +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer/bpf/pg_lw_lock_tracer.c +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/dependency_links.txt +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/requires.txt +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/src/pg_lock_tracer.egg-info/top_level.txt +0 -0
- {pg_lock_tracer-0.5.5 → pg_lock_tracer-0.6.1}/tests/test_helper.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pg_lock_tracer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: A BPF based lock tracer for the PostgreSQL database
|
|
5
5
|
Home-page: https://github.com/jnidzwetzki/pg-lock-tracer
|
|
6
6
|
Author: Jan Nidzwetzki
|
|
@@ -30,11 +30,12 @@ Requires-Dist: psycopg2
|
|
|
30
30
|
|
|
31
31
|
This project provides tools that allow you to gain deep insights into PostgreSQL's locking activities and troubleshoot locking-related issues (e.g., performance problems or deadlocks).
|
|
32
32
|
|
|
33
|
-
* `pg_lock_tracer` - is a lock tracer
|
|
34
|
-
* `pg_lw_lock_tracer` -
|
|
33
|
+
* `pg_lock_tracer` - is a PostgreSQL table level lock tracer.
|
|
34
|
+
* `pg_lw_lock_tracer` - is a tracer for PostgreSQL lightweight locks (LWLocks).
|
|
35
|
+
* `pg_row_lock_tracer` - is a tracer for PostgreSQL row locks.
|
|
35
36
|
* `animate_lock_graph` - creates animated locks graphs based on the `pg_lock_tracer` output.
|
|
36
37
|
|
|
37
|
-
__Note:__
|
|
38
|
+
__Note:__ These tools employ the [eBPF](https://ebpf.io/) (_Extended Berkeley Packet Filter_) technology. At the moment, PostgreSQL 12, 13, 14, 15, and 16 are supported (see additional information below).
|
|
38
39
|
|
|
39
40
|
# pg_lock_tracer
|
|
40
41
|
`pg_lock_tracer` observes the locking activity of a running PostgreSQL process (using _eBPF_ and _UProbes_). In contrast to the information that is present in the table `pg_locks` (which provides information about which locks are _currently_ requested), `pg_lock_tracer` gives you a continuous view of the locking activity and collects statistics and timings.
|
|
@@ -73,8 +74,13 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -
|
|
|
73
74
|
# Show statistics about locks
|
|
74
75
|
pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 --statistics
|
|
75
76
|
|
|
76
|
-
# Create an animated lock graph
|
|
77
|
-
|
|
77
|
+
# Create an animated lock graph (with Oids)
|
|
78
|
+
pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -o locks.json
|
|
79
|
+
animate_lock_graph -i lock -o locks.html
|
|
80
|
+
|
|
81
|
+
# Create an animated lock graph (with table names)
|
|
82
|
+
pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -r 1234:psql://jan@localhost/test2 -o locks.json
|
|
83
|
+
animate_lock_graph -i lock -o locks.html
|
|
78
84
|
```
|
|
79
85
|
|
|
80
86
|
## Example Output
|
|
@@ -686,7 +692,7 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_2_DEBUG/bin/postgres -
|
|
|
686
692
|
### Animated Lock Graphs
|
|
687
693
|
See the content of the [examples](examples/) directory for examples.
|
|
688
694
|
|
|
689
|
-
#
|
|
695
|
+
# pg_lw_lock_tracer
|
|
690
696
|
|
|
691
697
|
`pg_lw_lock_trace` allows to trace lightweight locks ([LWLocks](https://github.com/postgres/postgres/blob/c8e1ba736b2b9e8c98d37a5b77c4ed31baf94147/src/backend/storage/lmgr/lwlock.c)) in a PostgreSQL process via _Userland Statically Defined Tracing_ (USDT).
|
|
692
698
|
|
|
@@ -805,8 +811,73 @@ Locks per type
|
|
|
805
811
|
+--------------+----------+
|
|
806
812
|
```
|
|
807
813
|
|
|
808
|
-
#
|
|
814
|
+
# pg_row_lock_tracer
|
|
815
|
+
|
|
816
|
+
`pg_row_lock_tracer` allows to trace row locks (see the PostgreSQL [documentation](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS)) of a PostgreSQL process using _eBPF_ and _UProbes_
|
|
817
|
+
|
|
818
|
+
## Usage Examples
|
|
819
|
+
```
|
|
820
|
+
# Trace the row locks of the given PostgreSQL binary
|
|
821
|
+
pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
|
|
822
|
+
|
|
823
|
+
# Trace the row locks of the PID 1234
|
|
824
|
+
pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
|
|
825
|
+
|
|
826
|
+
# Trace the row locks of the PID 1234 and 5678
|
|
827
|
+
pg_row_lock_tracer -p 1234 -p 5678 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
|
|
828
|
+
|
|
829
|
+
# Trace the row locks of the PID 1234 and be verbose
|
|
830
|
+
pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres -v
|
|
831
|
+
|
|
832
|
+
# Trace the row locks and show statistics
|
|
833
|
+
pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
## Example output
|
|
809
837
|
|
|
838
|
+
SQL Query: `SELECT * FROM temperature FOR UPDATE;`
|
|
839
|
+
|
|
840
|
+
CLI: `sudo pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics`
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
Tracer output:
|
|
844
|
+
|
|
845
|
+
```
|
|
846
|
+
[...]
|
|
847
|
+
2783502701862408 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13100 ns
|
|
848
|
+
2783502701877081 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 143) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
|
|
849
|
+
2783502701972367 [Pid 2604491] LOCK_TUPLE_END TM_OK in 95286 ns
|
|
850
|
+
2783502701988387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 144) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
|
|
851
|
+
2783502702001690 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13303 ns
|
|
852
|
+
2783502702016387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 145) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
|
|
853
|
+
2783502702029375 [Pid 2604491] LOCK_TUPLE_END TM_OK in 12988 ns
|
|
854
|
+
^C
|
|
855
|
+
Lock statistics:
|
|
856
|
+
================
|
|
857
|
+
|
|
858
|
+
Used wait policies:
|
|
859
|
+
+---------+-----------------+----------------+-----------------+
|
|
860
|
+
| PID | LOCK_WAIT_BLOCK | LOCK_WAIT_SKIP | LOCK_WAIT_ERROR |
|
|
861
|
+
+---------+-----------------+----------------+-----------------+
|
|
862
|
+
| 2604491 | 1440 | 0 | 0 |
|
|
863
|
+
+---------+-----------------+----------------+-----------------+
|
|
864
|
+
|
|
865
|
+
Lock modes:
|
|
866
|
+
+---------+---------------------+------------------+---------------------------+----------------------+
|
|
867
|
+
| PID | LOCK_TUPLE_KEYSHARE | LOCK_TUPLE_SHARE | LOCK_TUPLE_NOKEYEXCLUSIVE | LOCK_TUPLE_EXCLUSIVE |
|
|
868
|
+
+---------+---------------------+------------------+---------------------------+----------------------+
|
|
869
|
+
| 2604491 | 0 | 0 | 0 | 1440 |
|
|
870
|
+
+---------+---------------------+------------------+---------------------------+----------------------+
|
|
871
|
+
|
|
872
|
+
Lock results:
|
|
873
|
+
+---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
|
|
874
|
+
| PID | TM_OK | TM_INVISIBLE | TM_SELFMODIFIED | TM_UPDATED | TM_DELETED | TM_BEINGMODIFIED | TM_WOULDBLOCK |
|
|
875
|
+
+---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
|
|
876
|
+
| 2604491 | 1440 | 0 | 0 | 0 | 0 | 0 | 0 |
|
|
877
|
+
+---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
# Additional Information
|
|
810
881
|
|
|
811
882
|
## Installation
|
|
812
883
|
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
This project provides tools that allow you to gain deep insights into PostgreSQL's locking activities and troubleshoot locking-related issues (e.g., performance problems or deadlocks).
|
|
10
10
|
|
|
11
|
-
* `pg_lock_tracer` - is a lock tracer
|
|
12
|
-
* `pg_lw_lock_tracer` -
|
|
11
|
+
* `pg_lock_tracer` - is a PostgreSQL table level lock tracer.
|
|
12
|
+
* `pg_lw_lock_tracer` - is a tracer for PostgreSQL lightweight locks (LWLocks).
|
|
13
|
+
* `pg_row_lock_tracer` - is a tracer for PostgreSQL row locks.
|
|
13
14
|
* `animate_lock_graph` - creates animated locks graphs based on the `pg_lock_tracer` output.
|
|
14
15
|
|
|
15
|
-
__Note:__
|
|
16
|
+
__Note:__ These tools employ the [eBPF](https://ebpf.io/) (_Extended Berkeley Packet Filter_) technology. At the moment, PostgreSQL 12, 13, 14, 15, and 16 are supported (see additional information below).
|
|
16
17
|
|
|
17
18
|
# pg_lock_tracer
|
|
18
19
|
`pg_lock_tracer` observes the locking activity of a running PostgreSQL process (using _eBPF_ and _UProbes_). In contrast to the information that is present in the table `pg_locks` (which provides information about which locks are _currently_ requested), `pg_lock_tracer` gives you a continuous view of the locking activity and collects statistics and timings.
|
|
@@ -51,8 +52,13 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -
|
|
|
51
52
|
# Show statistics about locks
|
|
52
53
|
pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 --statistics
|
|
53
54
|
|
|
54
|
-
# Create an animated lock graph
|
|
55
|
-
|
|
55
|
+
# Create an animated lock graph (with Oids)
|
|
56
|
+
pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -o locks.json
|
|
57
|
+
animate_lock_graph -i lock -o locks.html
|
|
58
|
+
|
|
59
|
+
# Create an animated lock graph (with table names)
|
|
60
|
+
pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_15_1_DEBUG/bin/postgres -p 1234 -j -r 1234:psql://jan@localhost/test2 -o locks.json
|
|
61
|
+
animate_lock_graph -i lock -o locks.html
|
|
56
62
|
```
|
|
57
63
|
|
|
58
64
|
## Example Output
|
|
@@ -664,7 +670,7 @@ pg_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_2_DEBUG/bin/postgres -
|
|
|
664
670
|
### Animated Lock Graphs
|
|
665
671
|
See the content of the [examples](examples/) directory for examples.
|
|
666
672
|
|
|
667
|
-
#
|
|
673
|
+
# pg_lw_lock_tracer
|
|
668
674
|
|
|
669
675
|
`pg_lw_lock_trace` allows to trace lightweight locks ([LWLocks](https://github.com/postgres/postgres/blob/c8e1ba736b2b9e8c98d37a5b77c4ed31baf94147/src/backend/storage/lmgr/lwlock.c)) in a PostgreSQL process via _Userland Statically Defined Tracing_ (USDT).
|
|
670
676
|
|
|
@@ -783,8 +789,73 @@ Locks per type
|
|
|
783
789
|
+--------------+----------+
|
|
784
790
|
```
|
|
785
791
|
|
|
786
|
-
#
|
|
792
|
+
# pg_row_lock_tracer
|
|
793
|
+
|
|
794
|
+
`pg_row_lock_tracer` allows to trace row locks (see the PostgreSQL [documentation](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS)) of a PostgreSQL process using _eBPF_ and _UProbes_
|
|
795
|
+
|
|
796
|
+
## Usage Examples
|
|
797
|
+
```
|
|
798
|
+
# Trace the row locks of the given PostgreSQL binary
|
|
799
|
+
pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
|
|
800
|
+
|
|
801
|
+
# Trace the row locks of the PID 1234
|
|
802
|
+
pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
|
|
803
|
+
|
|
804
|
+
# Trace the row locks of the PID 1234 and 5678
|
|
805
|
+
pg_row_lock_tracer -p 1234 -p 5678 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres
|
|
806
|
+
|
|
807
|
+
# Trace the row locks of the PID 1234 and be verbose
|
|
808
|
+
pg_row_lock_tracer -p 1234 -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres -v
|
|
809
|
+
|
|
810
|
+
# Trace the row locks and show statistics
|
|
811
|
+
pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
## Example output
|
|
787
815
|
|
|
816
|
+
SQL Query: `SELECT * FROM temperature FOR UPDATE;`
|
|
817
|
+
|
|
818
|
+
CLI: `sudo pg_row_lock_tracer -x /home/jan/postgresql-sandbox/bin/REL_14_9_DEBUG/bin/postgres --statistics`
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
Tracer output:
|
|
822
|
+
|
|
823
|
+
```
|
|
824
|
+
[...]
|
|
825
|
+
2783502701862408 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13100 ns
|
|
826
|
+
2783502701877081 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 143) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
|
|
827
|
+
2783502701972367 [Pid 2604491] LOCK_TUPLE_END TM_OK in 95286 ns
|
|
828
|
+
2783502701988387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 144) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
|
|
829
|
+
2783502702001690 [Pid 2604491] LOCK_TUPLE_END TM_OK in 13303 ns
|
|
830
|
+
2783502702016387 [Pid 2604491] LOCK_TUPLE (Tablespace 1663 database 305234 relation 313419) - (Block and offset 7 145) - LOCK_TUPLE_EXCLUSIVE LOCK_WAIT_BLOCK
|
|
831
|
+
2783502702029375 [Pid 2604491] LOCK_TUPLE_END TM_OK in 12988 ns
|
|
832
|
+
^C
|
|
833
|
+
Lock statistics:
|
|
834
|
+
================
|
|
835
|
+
|
|
836
|
+
Used wait policies:
|
|
837
|
+
+---------+-----------------+----------------+-----------------+
|
|
838
|
+
| PID | LOCK_WAIT_BLOCK | LOCK_WAIT_SKIP | LOCK_WAIT_ERROR |
|
|
839
|
+
+---------+-----------------+----------------+-----------------+
|
|
840
|
+
| 2604491 | 1440 | 0 | 0 |
|
|
841
|
+
+---------+-----------------+----------------+-----------------+
|
|
842
|
+
|
|
843
|
+
Lock modes:
|
|
844
|
+
+---------+---------------------+------------------+---------------------------+----------------------+
|
|
845
|
+
| PID | LOCK_TUPLE_KEYSHARE | LOCK_TUPLE_SHARE | LOCK_TUPLE_NOKEYEXCLUSIVE | LOCK_TUPLE_EXCLUSIVE |
|
|
846
|
+
+---------+---------------------+------------------+---------------------------+----------------------+
|
|
847
|
+
| 2604491 | 0 | 0 | 0 | 1440 |
|
|
848
|
+
+---------+---------------------+------------------+---------------------------+----------------------+
|
|
849
|
+
|
|
850
|
+
Lock results:
|
|
851
|
+
+---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
|
|
852
|
+
| PID | TM_OK | TM_INVISIBLE | TM_SELFMODIFIED | TM_UPDATED | TM_DELETED | TM_BEINGMODIFIED | TM_WOULDBLOCK |
|
|
853
|
+
+---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
|
|
854
|
+
| 2604491 | 1440 | 0 | 0 | 0 | 0 | 0 | 0 |
|
|
855
|
+
+---------+-------+--------------+-----------------+------------+------------+------------------+---------------+
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
# Additional Information
|
|
788
859
|
|
|
789
860
|
## Installation
|
|
790
861
|
|
|
@@ -48,6 +48,7 @@ pg_lock_tracer.bpf =
|
|
|
48
48
|
console_scripts =
|
|
49
49
|
pg_lock_tracer = pg_lock_tracer.pg_lock_tracer:main
|
|
50
50
|
pg_lw_lock_tracer = pg_lock_tracer.pg_lw_lock_tracer:main
|
|
51
|
+
pg_row_lock_tracer = pg_lock_tracer.pg_row_lock_tracer:main
|
|
51
52
|
animate_lock_graph = pg_lock_tracer.animate_lock_graph:main
|
|
52
53
|
|
|
53
54
|
[egg_info]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.1"
|
|
@@ -207,7 +207,7 @@ class DOTModel:
|
|
|
207
207
|
if self.verbose:
|
|
208
208
|
print(f"Processing {event}")
|
|
209
209
|
|
|
210
|
-
tablename = event
|
|
210
|
+
tablename = StringHelper.get_tablename(event)
|
|
211
211
|
lock_type = event["lock_type"]
|
|
212
212
|
|
|
213
213
|
if not self.graph.vs.select(label_eq=tablename):
|
|
@@ -244,7 +244,7 @@ class DOTModel:
|
|
|
244
244
|
if self.verbose:
|
|
245
245
|
print(f"Processing {event}")
|
|
246
246
|
|
|
247
|
-
tablename = event
|
|
247
|
+
tablename = StringHelper.get_tablename(event)
|
|
248
248
|
lock_type = event["lock_type"]
|
|
249
249
|
lock_numeric_value = PostgreSQLLockHelper.lock_type_to_int(lock_type)
|
|
250
250
|
|
|
@@ -383,6 +383,16 @@ class StringHelper:
|
|
|
383
383
|
|
|
384
384
|
return result
|
|
385
385
|
|
|
386
|
+
@staticmethod
|
|
387
|
+
def get_tablename(event):
|
|
388
|
+
"""
|
|
389
|
+
Get the tablename or the Oid of the event.
|
|
390
|
+
"""
|
|
391
|
+
if "table" in event:
|
|
392
|
+
return event["table"]
|
|
393
|
+
|
|
394
|
+
return f"Oid {event['oid']}"
|
|
395
|
+
|
|
386
396
|
|
|
387
397
|
def main():
|
|
388
398
|
"""
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#include <uapi/linux/ptrace.h>
|
|
2
|
+
|
|
3
|
+
/* Placeholder for auto generated defines */
|
|
4
|
+
__DEFINES__
|
|
5
|
+
|
|
6
|
+
typedef struct RowLockEvent_t {
|
|
7
|
+
u32 pid;
|
|
8
|
+
u64 timestamp;
|
|
9
|
+
u32 event_type;
|
|
10
|
+
|
|
11
|
+
/* See RelFileNode - Oid is u32 */
|
|
12
|
+
u32 tablespace;
|
|
13
|
+
u32 database;
|
|
14
|
+
u32 relation;
|
|
15
|
+
|
|
16
|
+
/* LockTupleMode */
|
|
17
|
+
u8 locktuplemode;
|
|
18
|
+
|
|
19
|
+
/* LockWaitPolicy */
|
|
20
|
+
u8 lockwaitpolicy;
|
|
21
|
+
|
|
22
|
+
/* Locked tuple */
|
|
23
|
+
u32 blockid;
|
|
24
|
+
u16 offset;
|
|
25
|
+
|
|
26
|
+
/* TM_Result */
|
|
27
|
+
int lockresult;
|
|
28
|
+
} RowLockEvent;
|
|
29
|
+
|
|
30
|
+
BPF_PERF_OUTPUT(lockevents);
|
|
31
|
+
|
|
32
|
+
static void fill_and_submit(struct pt_regs *ctx, RowLockEvent *event) {
|
|
33
|
+
event->pid = bpf_get_current_pid_tgid();
|
|
34
|
+
event->timestamp = bpf_ktime_get_ns();
|
|
35
|
+
|
|
36
|
+
// sudo cat /sys/kernel/debug/tracing/trace_pipe
|
|
37
|
+
// bpf_trace_printk("LW lock event for trance: %s\\n", tranche);
|
|
38
|
+
|
|
39
|
+
lockevents.perf_submit(ctx, event, sizeof(RowLockEvent));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* Acquire a tuple lock
|
|
44
|
+
*
|
|
45
|
+
* Arguments:
|
|
46
|
+
* 1. Relation relation (1st member RelFileNode)
|
|
47
|
+
* 2. ItemPointer tid
|
|
48
|
+
* 3. Snapshot snapshot,
|
|
49
|
+
* 4. TupleTableSlot *slot,
|
|
50
|
+
* 5. CommandId cid,
|
|
51
|
+
* 6. LockTupleMode mode,
|
|
52
|
+
* 7. LockWaitPolicy wait_policy,
|
|
53
|
+
* 8. uint8 flags,
|
|
54
|
+
* 9. TM_FailureData *tmfd
|
|
55
|
+
*
|
|
56
|
+
*/
|
|
57
|
+
int heapam_tuple_lock(struct pt_regs *ctx) {
|
|
58
|
+
RowLockEvent event = {.event_type = EVENT_LOCK_TUPLE};
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* (gdb) ptype /o RelFileNode
|
|
62
|
+
* 0 | 4 Oid spcNode;
|
|
63
|
+
* 4 | 4 Oid dbNode;
|
|
64
|
+
* 8 | 4 Oid relNode;
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
char buffer_relation[12];
|
|
68
|
+
bpf_probe_read_user(buffer_relation, sizeof(buffer_relation),
|
|
69
|
+
(void *)PT_REGS_PARM1(ctx));
|
|
70
|
+
bpf_probe_read_kernel(&(event.tablespace), sizeof(event.tablespace),
|
|
71
|
+
&(buffer_relation[0]));
|
|
72
|
+
bpf_probe_read_kernel(&(event.database), sizeof(event.database),
|
|
73
|
+
&(buffer_relation[4]));
|
|
74
|
+
bpf_probe_read_kernel(&(event.relation), sizeof(event.relation),
|
|
75
|
+
&(buffer_relation[8]));
|
|
76
|
+
|
|
77
|
+
/* Locked tuple */
|
|
78
|
+
char buffer_item_pointer[6];
|
|
79
|
+
u16 bi_hi;
|
|
80
|
+
u16 bi_lo;
|
|
81
|
+
|
|
82
|
+
bpf_probe_read_user(buffer_item_pointer, sizeof(buffer_item_pointer),
|
|
83
|
+
(void *)PT_REGS_PARM2(ctx));
|
|
84
|
+
bpf_probe_read_kernel(&(bi_hi), sizeof(bi_hi), &(buffer_item_pointer[0]));
|
|
85
|
+
bpf_probe_read_kernel(&(bi_lo), sizeof(bi_lo), &(buffer_item_pointer[2]));
|
|
86
|
+
bpf_probe_read_kernel(&(event.offset), sizeof(event.offset),
|
|
87
|
+
&(buffer_item_pointer[4]));
|
|
88
|
+
|
|
89
|
+
/* See #define BlockIdGetBlockNumber(blockId) */
|
|
90
|
+
event.blockid = (bi_hi) << 16 | bi_lo;
|
|
91
|
+
|
|
92
|
+
/* Locking options */
|
|
93
|
+
bpf_probe_read_kernel(&(event.locktuplemode), sizeof(event.locktuplemode),
|
|
94
|
+
&(PT_REGS_PARM6(ctx)));
|
|
95
|
+
|
|
96
|
+
/* Only the first six function parameters are passed via register. All
|
|
97
|
+
* remaining parameters are stored on the stack.
|
|
98
|
+
*
|
|
99
|
+
* See: System V Application Binary Interface—AMD64 Architecture Processor
|
|
100
|
+
* Supplement.
|
|
101
|
+
*/
|
|
102
|
+
void *ptr = 0;
|
|
103
|
+
bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx) + (1 * 8)));
|
|
104
|
+
bpf_probe_read_kernel(&(event.lockwaitpolicy), sizeof(event.lockwaitpolicy),
|
|
105
|
+
&ptr);
|
|
106
|
+
|
|
107
|
+
fill_and_submit(ctx, &event);
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/*
|
|
112
|
+
* Acquire a tuple lock - Function done
|
|
113
|
+
*/
|
|
114
|
+
int heapam_tuple_lock_end(struct pt_regs *ctx) {
|
|
115
|
+
RowLockEvent event = {.event_type = EVENT_LOCK_TUPLE_END};
|
|
116
|
+
|
|
117
|
+
event.lockresult = PT_REGS_RC(ctx);
|
|
118
|
+
|
|
119
|
+
fill_and_submit(ctx, &event);
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
@@ -6,9 +6,10 @@ import os
|
|
|
6
6
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
|
+
from bcc import BPF
|
|
9
10
|
|
|
10
|
-
class PostgreSQLLockHelper:
|
|
11
11
|
|
|
12
|
+
class PostgreSQLLockHelper:
|
|
12
13
|
"""
|
|
13
14
|
# Defines taken from: src/include/storage/lockdefs.h
|
|
14
15
|
#
|
|
@@ -91,6 +92,9 @@ class PostgreSQLLockHelper:
|
|
|
91
92
|
|
|
92
93
|
|
|
93
94
|
class BPFHelper:
|
|
95
|
+
# The size of the kernel ring buffer
|
|
96
|
+
page_cnt = 2048
|
|
97
|
+
|
|
94
98
|
@staticmethod
|
|
95
99
|
def enum_to_defines(enum_instance, prefix):
|
|
96
100
|
"""
|
|
@@ -115,3 +119,54 @@ class BPFHelper:
|
|
|
115
119
|
|
|
116
120
|
with program_file.open("r") as bpf_program:
|
|
117
121
|
return bpf_program.read()
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def check_pid_exe(pids, executable):
|
|
125
|
+
"""
|
|
126
|
+
Do the given PIDs belong to the executable
|
|
127
|
+
"""
|
|
128
|
+
if not pids:
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
for pid in pids:
|
|
132
|
+
if not os.path.isdir(f"/proc/{pid}"):
|
|
133
|
+
raise ValueError(
|
|
134
|
+
f"/proc entry for pid {pid} not found, does the process exist?"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
binary = os.readlink(f"/proc/{pid}/exe")
|
|
138
|
+
|
|
139
|
+
if binary != executable:
|
|
140
|
+
raise ValueError(
|
|
141
|
+
f"Pid {pid} does not belong to binary {executable}. Executable is {binary}"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
@staticmethod
|
|
145
|
+
def register_ebpf_probe(
|
|
146
|
+
path, bpf_instance, function_regex, bpf_fn_name, verbose, probe_on_enter=True
|
|
147
|
+
):
|
|
148
|
+
"""
|
|
149
|
+
Register a BPF probe
|
|
150
|
+
"""
|
|
151
|
+
addresses = set()
|
|
152
|
+
func_and_addr = BPF.get_user_functions_and_addresses(path, function_regex)
|
|
153
|
+
|
|
154
|
+
if not func_and_addr:
|
|
155
|
+
raise ValueError(f"Unable to locate function {function_regex}")
|
|
156
|
+
|
|
157
|
+
# Handle address duplicates
|
|
158
|
+
for function, address in func_and_addr:
|
|
159
|
+
if address in addresses:
|
|
160
|
+
continue
|
|
161
|
+
addresses.add(address)
|
|
162
|
+
|
|
163
|
+
if probe_on_enter:
|
|
164
|
+
bpf_instance.attach_uprobe(name=path, sym=function, fn_name=bpf_fn_name)
|
|
165
|
+
if verbose:
|
|
166
|
+
print(f"Attaching to {function} at address {address} on enter")
|
|
167
|
+
else:
|
|
168
|
+
bpf_instance.attach_uretprobe(
|
|
169
|
+
name=path, sym=function, fn_name=bpf_fn_name
|
|
170
|
+
)
|
|
171
|
+
if verbose:
|
|
172
|
+
print(f"Attaching to {function} at address {address} on return")
|