

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Lock:advisory
<a name="apg-waits.lockadvisory"></a>

Das `Lock:advisory`-Ereignis tritt auf, wenn eine PostgreSQL-Anwendung eine Sperre verwendet, um Aktivitäten über mehrere Sitzungen hinweg zu koordinieren.

**Topics**
+ [Relevante Engine-Versionen](#apg-waits.lockadvisory.context.supported)
+ [Kontext](#apg-waits.lockadvisory.context)
+ [Ursachen](#apg-waits.lockadvisory.causes)
+ [Aktionen](#apg-waits.lockadvisory.actions)

## Relevante Engine-Versionen
<a name="apg-waits.lockadvisory.context.supported"></a>

Diese Warteereignisinformationen sind für Aurora PostgreSQL Versionen 9.6 und höher relevant.

## Kontext
<a name="apg-waits.lockadvisory.context"></a>

PostgreSQL-Beratungssperren sind Anwendungsebene, kooperative Sperren werden explizit durch den Anwendungscode des Benutzers gesperrt und freigeschaltet. Eine Anwendung kann PostgreSQL-Beratungssperren verwenden, um Aktivitäten über mehrere Sitzungen hinweg zu koordinieren. Im Gegensatz zu normalen Sperren auf Objekt- oder Zeilenebene hat die Anwendung die volle Kontrolle über die Lebensdauer des Schlosses. Weitere Informationen finden Sie unter [Empfohlene Sperren](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) in der PostgreSQL-Dokumentation.

Beratungssperren können vor dem Ende einer Transaktion freigegeben werden oder von einer Sitzung über Transaktionen hinweg gehalten werden. Dies gilt nicht für implizite, vom System erzwungene Sperren, wie z. B. eine zugriffsexklusive Sperre für eine Tabelle, die von einer `CREATE INDEX`-Anweisung abgerufen wird.

Eine Beschreibung der Funktionen zum Erlangen (Sperren) und Freigeben (Entsperren) von Advisory Locks finden Sie unter [Advisory Lock Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) in der PostgreSQL-Dokumentation.

Advisory Locks werden zusätzlich zum regulären PostgreSQL-Locking-System implementiert und sind in der `pg_locks`-Systemansicht sichtbar.

## Ursachen
<a name="apg-waits.lockadvisory.causes"></a>

Dieser Schlosstyp wird ausschließlich von einer Anwendung gesteuert, die ihn explizit verwendet. Beratungssperren, die für jede Zeile als Teil einer Abfrage erworben werden, können zu einem Anstieg der Sperren oder zu einem langfristigen Aufbau führen.

Diese Effekte treten auf, wenn die Abfrage so ausgeführt wird, dass Sperren für mehr Zeilen erwirbt, als von der Abfrage zurückgegeben werden. Die Anwendung muss schließlich jede Sperre freigeben, aber wenn Sperren für Zeilen erworben werden, die nicht zurückgegeben werden, kann die Anwendung nicht alle Sperren finden.

Das folgende Beispiel stammt aus [Empfohlene Sperren](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) in der PostgreSQL-Dokumentation.

```
SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100;
```

In diesem Beispiel kann die `LIMIT`-Klausel die Ausgabe der Abfrage nur stoppen, nachdem die Zeilen bereits intern ausgewählt und ihre ID-Werte gesperrt wurden. Dies kann plötzlich passieren, wenn ein wachsendes Datenvolumen dazu führt, dass der Planer einen anderen Ausführungsplan auswählt, der während der Entwicklung nicht getestet wurde. Der Aufbau erfolgt in diesem Fall, weil die Anwendung `pg_advisory_unlock` explizit für jeden gesperrten ID-Wert aufruft. In diesem Fall kann es jedoch nicht die Sperren finden, die für Zeilen erworben wurden, die nicht zurückgegeben wurden. Da die Sperren auf Sitzungsebene erworben werden, werden sie am Ende der Transaktion nicht automatisch freigegeben.

Eine weitere mögliche Ursache für Spikes bei blockierten Sperrversuchen sind unbeabsichtigte Konflikte. In diesen Konflikten teilen sich nicht verwandte Teile der Anwendung versehentlich denselben Sperren-ID-Raum.

## Aktionen
<a name="apg-waits.lockadvisory.actions"></a>

Überprüfen Sie die Anwendungsnutzung von Beratungssperren und Details, wo und wann im Anwendungsablauf jede Art von Beratungssperre erworben und freigegeben wird.

Stellen Sie fest, ob eine Sitzung zu viele Sperren erwirbt oder eine lang andauernde Sitzung keine Sperren früh genug freigibt, was zu einem langsamen Aufbau von Sperren führt. Sie können einen langsamen Aufbau von Sperren auf Sitzungsebene korrigieren, indem Sie die Sitzung mit `pg_terminate_backend(pid)` beenden. 

Ein Client, der auf eine Beratungssperre wartet, erscheint in `pg_stat_activity` mit `wait_event_type=Lock` und `wait_event=advisory`. Sie können bestimmte Sperrwerte erhalten, indem Sie die `pg_locks`-Systemansicht nach demselben `pid` abfragen und nach `locktype=advisory` und `granted=f` suchen.

Sie können dann die blockierende Sitzung identifizieren, indem Sie `pg_locks` nach derselben beratenden Sperre mit `granted=t` abfragen, wie im folgenden Beispiel gezeigt.

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_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;
```

Alle API-Funktionen für beratende Sperren haben zwei Sätze von Argumenten, entweder ein `bigint`-Argument oder zwei `integer`-Argumente:
+ Bei den API-Funktionen mit einem `bigint`-Argument befinden sich die oberen 32 Bit in `pg_locks.classid` und die unteren 32 Bit in `pg_locks.objid`.
+ Bei den API-Funktionen mit zwei `integer`-Argumenten ist das erste Argument `pg_locks.classid` und das zweite Argument ist `pg_locks.objid`.

Der `pg_locks.objsubid`-Wert gibt an, welches API-Formular verwendet wurde: `1` bedeutet ein `bigint`-Argument; `2` bedeutet zwei `integer`-Argumente.