Statistiken sperren

Spanner bietet Sperrstatistiken, mit denen Sie während eines bestimmten Zeitraums die Zeilenschlüssel und Tabellenspalten identifizieren können, die die wichtigsten Quellen von Transaktionssperrekonflikten in Ihrer Datenbank waren. Sie können diese Statistiken mithilfe von SQL-Anweisungen aus den SPANNER_SYS.LOCK_STATS*-Systemtabellen abrufen.

Verfügbarkeit

SPANNER_SYS-Daten sind nur über SQL-Schnittstellen verfügbar. Beispiel:

Andere von Spanner bereitgestellte Methoden für einzelne Leseaufrufe werden nicht unterstützt SPANNER_SYS

Statistiken nach Zeilenschlüssel sperren

In den folgenden Tabellen wird der Zeilenschlüssel mit der höchsten Wartezeit nachverfolgt:

  • SPANNER_SYS.LOCK_STATS_TOP_MINUTE: Zeilenschlüssel mit der höchsten Wartezeit bei Sperren in Intervallen von 1 Minute.

  • SPANNER_SYS.LOCK_STATS_TOP_10MINUTE: Zeilenschlüssel mit der höchsten Sperrwartezeit in 10-Minuten-Intervallen.

  • SPANNER_SYS.LOCK_STATS_TOP_HOUR: Zeilenschlüssel mit der Sperrwartezeit in 1-Stunden-Intervallen.

Diese Tabellen haben folgende Attribute:

  • Jede Tabelle enthält Daten für nicht überlappende Zeitintervalle in der Länge, die der Tabellenname festlegt.

  • Die Intervalle basieren auf der Uhrzeit. 1-Minuten-Intervalle enden nach einer Minute, 10-Minuten-Intervalle enden alle 10 Minuten ab Beginn der vollen Stunde, 1-Stunden-Intervalle enden zu jeder vollen Stunde. Nach jedem Intervall erfasst Spanner Daten von allen Servern und stellt die Daten danach in den SPANNER_SYS-Tabellen bereit.

    Beispielsweise sind die neuesten, für SQL-Abfragen verfügbaren Intervalle um 11:59:30 Uhr:

    • 1 Minute: 11:58:00–11:58:59 Uhr
    • 10 Minuten: 11:40:00–11:49:59 Uhr
    • 1 Stunde: 10:00:00–10:59:59 Uhr
  • Spanner gruppiert die Statistiken, indem der Zeilenschlüsselbereich gestartet wird.

  • Jede Zeile enthält Statistiken für die Gesamtwartezeit bei Startzeilenschlüsselbereich, für den Spanner während des Zeitraums Statistiken erfasst das angegebene Intervall.

  • Wenn Spanner keine Informationen zu jedem Zeilenschlüsselbereich speichern kann bei Wartezeiten bei Sperren während des Intervalls, priorisiert das System den Zeilenschlüsselbereich mit die höchste Wartezeit bei Sperren während des angegebenen Intervalls.

  • Für alle Spalten in den Tabellen sind Nullwerte zulässig.

Tabellenschema

Spaltenname Typ Beschreibung
INTERVAL_END TIMESTAMP Ende des Zeitintervalls, in dem die enthaltenen Sperrkonflikte aufgetreten sind.
ROW_RANGE_START_KEY BYTES(MAX) Der Zeilenschlüssel, in dem der Sperrkonflikt aufgetreten ist. Wenn der Konflikt einen Bereich von Zeilen beinhaltet, stellt dieser Wert den Startschlüssel dieses Bereichs dar. Ein Pluszeichen, +, bezeichnet einen Bereich. Weitere Informationen finden Sie unter Was ist ein Startschlüssel für einen Zeilenbereich?.
LOCK_WAIT_SECONDS FLOAT64 Die kumulative Wartezeit der Sperre von Sperrkonflikten, die für alle Spalten im Zeilenschlüsselbereich aufgezeichnet wurden, in Sekunden.
SAMPLE_LOCK_REQUESTS ARRAY<STRUCT<
  column STRING,
  lock_mode STRING,
   transaction_tag STRING>>
Jeder Eintrag in diesem Array entspricht einer Beispiel-Sperranfrage, zum Sperrkonflikt beigetragen, da entweder auf eine Sperre gewartet oder andere Transaktionen daran hindern, die Sperre zu nutzen, für die angegebene Zeile Schlüssel (Bereich). Die maximale Anzahl von Stichproben in diesem Array beträgt 20.
Jedes Beispiel enthält die folgenden drei Felder:
  • lock_mode: Der angeforderte Sperrmodus. Für Weitere Informationen finden Sie unter Sperrmodi
  • column: Die Spalte, in der der Sperrkonflikt aufgetreten ist. Das Format dieses Werts ist tablename.columnname.
  • transaction_tag: Das Tag der Transaktion, die die Anfrage gesendet hat. Weitere Informationen zur Verwendung von Tags finden Sie unter Fehlerbehebung mit Transaktions-Tags.
Alle Sperranfragen, die zu Sperrkonflikten geführt haben, sind gleichmäßig zufällig erfasst werden, sodass es möglich ist, Konflikt (entweder der Inhaber oder der Waiter) wird in diesem Array aufgezeichnet.

Sperrmodi

Spanner-Vorgänge erhalten Sperren, wenn die Vorgänge Teil eines read-write-Transaktion ausführen. Bei schreibgeschützten Transaktionen Sperren zu erhalten. Spanner verwendet verschiedene Sperrmodi, um Anzahl der Transaktionen mit Zugriff auf eine bestimmte Datenzelle an einem bestimmten . Unterschiedliche Sperren haben unterschiedliche Eigenschaften. Beispielsweise können einige Sperren von mehreren Transaktionen gemeinsam genutzt werden, andere hingegen nicht.

Ein Sperrkonflikt kann auftreten, wenn Sie versuchen, eine der folgenden Sperren zu erhalten Modi in einer Transaktion.

  • ReaderShared: Eine Sperre, mit der andere Lesevorgänge weiterhin auf die Daten zugreifen können, bis die Transaktion zum Commit bereit ist. Diese gemeinsame Sperre wurde übernommen Eine Lese-Schreib-Transaktion liest Daten.

  • WriterShared-Sperre: Diese Sperre wird erhalten, wenn eine Lese-Schreib-Transaktion versucht, einen Schreibvorgang festzuschreiben.

  • Exclusive-Sperre: Bei einem Lese-/Schreibmodus wird eine exklusive Sperre eingerichtet. Transaktion, die bereits eine ReaderShared-Sperre erhalten hat, versucht, Daten nach Abschluss des Lesevorgangs. Eine exklusive Sperre ist ein Upgrade von einer ReaderShared-Schloss. Eine exklusive Sperre ist ein Sonderfall einer Transaktion, die gleichzeitig die ReaderShared-Sperre und die WriterShared-Sperre enthält. Keine andere Transaktion kann eine Sperre für dieselbe Zelle abrufen.

  • WriterSharedTimestamp-Schloss: eine spezielle Art von WriterShared-Sperre, die wird erfasst, wenn neue Zeilen in eine Tabelle mit einem Commit eingefügt werden Zeitstempel als Teil des Primärschlüssels. Diese Art von Sperre verhindert, dass Transaktionsteilnehmer dieselbe Zeile erstellen und die miteinander in Konflikt stehen. Spanner aktualisiert den Schlüssel von die eingefügte Zeile, um dem Commit-Zeitstempel der Transaktion zu entsprechen, ausgeführt haben.

Weitere Informationen zu Transaktionstypen und den verfügbaren Sperren finden Sie unter Transaktionen.

Konflikte mit Sperrmodus

Die folgende Tabelle zeigt die möglichen Konflikte zwischen verschiedenen Sperrmodi.

Sperrmodi ReaderShared WriterShared Exclusive WriterSharedTimestamp
ReaderShared Nein Ja Ja Ja
WriterShared Ja Nein Ja Nicht zutreffend
Exclusive Ja Ja Ja Nicht zutreffend
WriterSharedTimestamp Ja Nicht zutreffend Nicht zutreffend Ja

WriterSharedTimestamp-Sperren werden nur verwendet, wenn neue Zeilen mit einem Zeitstempel als Teil des Primärschlüssels eingefügt werden. Die Sperren WriterShared und Exclusive werden verwendet, wenn in vorhandene Zellen geschrieben oder neue Zeilen ohne Zeitstempel eingefügt werden. Daher kann WriterSharedTimestamp nicht mit anderen Arten von Sperren in Konflikt stehen und diese Szenarien werden in der obigen Tabelle als Nicht zutreffend angezeigt.

Die einzige Ausnahme ist ReaderShared, das auf nicht vorhandene Zeilen angewendet werden kann und daher mit WriterSharedTimestamp in Konflikt stehen kann. Beispiel: Ein vollständiger Tabellenscan sperrt die gesamte Tabelle auch für Zeilen, die noch nicht erstellt wurden. Daher kann ReaderShared mit WriterSharedTimestamp in Konflikt stehen.

Was ist ein Startschlüssel für einen Zeilenbereich?

Die Spalte ROW_RANGE_START_KEY gibt den zusammengesetzten Primärschlüssel an oder beginnt den Primärschlüssel eines Zeilenbereichs mit Sperrenkonflikten. Das folgende Schema dient zur Veranschaulichung eines Beispiels.

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE TABLE Songs (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  TrackId      INT64 NOT NULL,
  SongName     STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId, TrackId),
  INTERLEAVE IN PARENT Albums ON DELETE CASCADE;

CREATE TABLE Users (
  UserId     INT64 NOT NULL,
  LastAccess TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true),
  ...
) PRIMARY KEY (UserId, LastAccess);

Wie die folgende Tabelle mit den Zeilenschlüsseln und Zeilenschlüsselbereichen zeigt, wird ein Bereich durch das Pluszeichen "+" angezeigt. Der Schlüssel in diesen Fällen stellt den Startschlüssel eines Schlüsselbereichs dar, in dem ein Sperrkonflikt aufgetreten ist.

ROW_RANGE_START_KEY Erklärung
Singers(2) Tabelle "Singers" bei Schlüssel "SingerId=2"
Alben(2,1) Album-Tabelle bei Schlüssel SingerId=2,AlbumId=1
Songs(2,1,5) Tabelle "Songs" unter dem Schlüssel "SingerId=2,AlbumId=1,TrackId=5"
Songs(2,1,5+) Schlüsselbereich der Songstabelle, beginnend bei SingerId=2,AlbumId=1,TrackId=5
Alben(2,1+) Album-Tabellenschlüsselbereich ab SingerId=2,AlbumId=1
Nutzer(3, 2020-11-01 12:34:56.426426+00:00) Nutzertabelle bei Schlüssel "UserId=3, LastAccess=commit_timestamp"

Zusammengefasste Statistiken

SPANNER_SYS enthält auch Tabellen zum Speichern aggregierter Daten für Sperrstatistiken von Spanner in einem bestimmten Zeitraum erfasst:

  • SPANNER_SYS.LOCK_STATS_TOTAL_MINUTE: Zusammengefasste Statistiken für alle Sperren wartet in Intervallen von 1 Minute.

  • SPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE: Zusammengefasste Statistiken für alle Sperrzeiten in 10-Minuten-Intervallen

  • SPANNER_SYS.LOCK_STATS_TOTAL_HOUR: Zusammengefasste Statistiken für alle Sperrzeiten in 1-Stunden-Intervallen.

Zusammengefasste Statistiktabellen haben die folgenden Eigenschaften:

  • Jede Tabelle enthält Daten für nicht überlappende Zeitintervalle der Länge der Tabellenname angibt.

  • Die Intervalle beziehen sich auf die Uhrzeit. 1-Minuten-Intervalle enden nach einer vollen Minute, 10-Minuten-Intervalle enden alle 10 Minuten ab Beginn der vollen Stunde, 1-Stunden-Intervalle enden zu jeder vollen Stunde.

    Zum Beispiel sind um 11:59:30 Uhr die neuesten Intervalle, die für SQL-Abfragen zu zusammengefassten Sperrstatistiken zur Verfügung stehen:

    • 1 Minute: 11:58:00–11:58:59 Uhr
    • 10 Minuten: 11:40:00–11:49:59 Uhr
    • 1 Stunde: 10:00:00–10:59:59 Uhr
  • Jede Zeile enthält zusammengefasste Statistiken für alle Sperren der Datenbank während des angegebenen Intervalls. Es gibt nur je eine Zeile pro Zeitintervall.

  • Die in den SPANNER_SYS.LOCK_STATS_TOTAL_*-Tabellen erfassten Statistiken Sperrwartezeiten einschließen, die Spanner nicht im SPANNER_SYS.LOCK_STATS_TOP_* Tabellen.

  • Einige Spalten in diesen Tabellen werden in Cloud Monitoring als Messwerte angezeigt. Die verfügbaren Messwerte sind:

    • Wartezeit bei Sperren

    Weitere Informationen finden Sie unter Spanner Messwerte.

Tabellenschema

Spaltenname Typ Beschreibung
INTERVAL_END TIMESTAMP Ende des Zeitintervalls, in dem der Sperrkonflikt aufgetreten ist.
TOTAL_LOCK_WAIT_SECONDS FLOAT64 Gesamtwartezeit für Sperrungen für Sperrkonflikte, die für die gesamte Datenbank aufgezeichnet wurden, in Sekunden.

Beispielabfragen

Das folgende Beispiel zeigt eine SQL-Anweisung, mit der Sie Sperrstatistiken abrufen können. Sie können diese SQL-Anweisungen mit dem Client Bibliotheken, die gcloud spanner oder der Google Cloud Console:

Sperrstatistiken für das vorherige 1-Minuten-Intervall auflisten

Die folgende Abfrage gibt die Informationen zur Sperre für jeden Zeilenschlüssel mit einem Sperrkonflikt zurück, einschließlich des Anteils der Gesamtsperrekonflikte während des letzten 1-Minuten-Zeitintervalls.

Die Funktion CAST() konvertiert das BYTES-Feld "row_range_start_key" in einen STRING.

SELECT CAST(s.row_range_start_key AS STRING) AS row_range_start_key,
       t.total_lock_wait_seconds,
       s.lock_wait_seconds,
       s.lock_wait_seconds/t.total_lock_wait_seconds frac_of_total,
       s.sample_lock_requests
FROM spanner_sys.lock_stats_total_minute t, spanner_sys.lock_stats_top_minute s
WHERE t.interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.lock_stats_total_minute)
AND s.interval_end = t.interval_end
ORDER BY s.lock_wait_seconds DESC;
Screenshot: Ausgabe der Abfrage
row_range_start_key total_lock_wait_seconds lock_wait_seconds frac_of_total sample_lock_requests
Songs(2,1,1) 2,37 1,76 0,7426 LOCK_MODE: ReaderShared

SPALTE: Singers.SingerInfo

LOCK_MODE: WriterShared

Spalte: Singers.SingerInfo
Nutzer(3, 2020-11-01 12:34:56.426426+00:00) 2,37 0,61 0,2573 LOCK_MODE: ReaderShared

SPALTE: users._exists1

LOCK_MODE: WriterShared

SPALTE: users._exists1

1 _exists ist ein internes Feld, mit dem geprüft wird, ob eine bestimmte Zeile vorhanden ist.

Datenaufbewahrung

Spanner speichert Daten für jede Tabelle zumindest für die folgende Zeit Zeiträume:

  • SPANNER_SYS.LOCK_STATS_TOP_MINUTE und SPANNER_SYS.LOCK_STATS_TOTAL_MINUTE: Intervalle der letzten 6 Stunden.

  • SPANNER_SYS.LOCK_STATS_TOP_10MINUTE und SPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE: Intervalle der letzten 4 Tage.

  • SPANNER_SYS.LOCK_STATS_TOP_HOUR und SPANNER_SYS.LOCK_STATS_TOTAL_HOUR: Intervalle der letzten 30 Tage.

Sperrkonflikte in Ihrer Datenbank mithilfe von Sperrstatistiken beheben

Sie können SQL oder die Sperrfunktion Statistiken Dashboard, um Sperrkonflikte in Ihrer Datenbank anzuzeigen.

In den folgenden Themen wird gezeigt, wie Sie solche Sperrkonflikte mit SQL untersuchen können. Code.

Zu untersuchenden Zeitraum auswählen

Sie prüfen die Latenzmesswerte für Ihren Spanner. und einen Zeitraum ermitteln, in dem Ihre App eine hohe Latenz aufweist und CPU-Auslastung. Das Problem trat beispielsweise gegen 22:50 Uhr auf. am 12. November 2020.

Ermitteln, ob die Latenz für den Commit von Transaktionen zusammen mit der Wartezeit für die Sperre während des ausgewählten Zeitraums gestiegen ist

Sperren werden von Transaktionen abgerufen. Wenn Sperrkonflikte lange Wartezeiten verursachen, sollten wir neben der Erhöhung der Wartezeit für die Sperre auch eine Erhöhung der Commit-Latenz der Transaktion erkennen können.

Nachdem ein Zeitraum zum Starten der Prüfung ausgewählt wurde, führen wir die Transaktionsstatistiken TXN_STATS_TOTAL_10MINUTE mit den Sperrstatistiken LOCK_STATS_TOTAL_10MINUTE zusammen, um uns bei der Ermittlung zu unterstützen, ob die Erhöhung der durchschnittlichen Commit-Latenz durch die Erhöhung der Wartezeit der Sperre ausgelöst wird.

SELECT t.interval_end, t.avg_commit_latency_seconds, l.total_lock_wait_seconds
FROM spanner_sys.txn_stats_total_10minute t
LEFT JOIN spanner_sys.lock_stats_total_10minute l
ON t.interval_end = l.interval_end
WHERE
  t.interval_end >= "2020-11-12T21:50:00Z"
  AND t.interval_end <= "2020-11-12T23:50:00Z"
ORDER BY interval_end;

Nehmen wir die folgenden Daten als Beispiel für die Ergebnisse, die wir von unserem Abfrage.

interval_end avg_commit_latency_seconds total_lock_wait_seconds
2020-11-12 21:40:00-07:00 0,002 0,090
2020-11-12 21:50:00-07:00 0,003 0,110
2020-11-12 22:00:00-07:00 0,002 0,100
2020-11-12 22:10:00-07:00 0,002 0,080
2020-11-12 22:20:00-07:00 0,030 0,240
2020-11-12 22:30:00-07:00 0,034 0,220
2020-11-12 22:40:00-07:00 0,034 0,218
2020-11-12 22:50:00-07:00 3,741 780,193
2020-11-12 23:00:00-07:00 0,042 0,240
2020-11-12 23:10:00-07:00 0,038 0,129
2020-11-12 23:20:00-07:00 0,021 0,128
2020-11-12 23:30:00-07:00 0,038 0,231

Diese vorherigen Ergebnisse zeigen einen deutlichen Anstieg bei avg_commit_latency_seconds und total_lock_wait_seconds im selben Zeitraum vom 12.11.2020 22:40:00 bis 2020-11-12 22:50:00 und danach wieder abgebrochen. Beachten Sie eine Möglichkeit: avg_commit_latency_seconds ist die durchschnittliche Zeit, die nur für den Commit-Schritt aufgewendet wird. total_lock_wait_seconds ist jedoch die zusammengefasste Sperrzeit für den Zeitraum, sodass die Zeit viel länger als die Commit-Zeit der Transaktion dauert.

Da wir nun bestätigt haben, dass die Wartezeit beim Sperren eng mit der Zunahme der Schreiblatenz untersuchen, untersuchen wir im nächsten Schritt, die lange Wartezeit verursachen.

Ermitteln Sie, für welche Zeilenschlüssel und Spalten im ausgewählten Zeitraum lange Wartezeiten aufgrund von Sperren aufgetreten sind

Um herauszufinden, für welche Zeilenschlüssel und Spalten in dem von uns untersuchten Zeitraum die hohen Sperrzeiten aufgetreten sind, fragen wir dieLOCK_STAT_TOP_10MINUTE Table. Diese Tabelle enthält die Zeilenschlüssel und Spalten, die am meisten zum Sperren warten.

Die Funktion CAST() in der folgenden Abfrage wandelt das BYTES-Feld "row_range_start_key" in einen STRING um.

SELECT CAST(s.row_range_start_key AS STRING) AS row_range_start_key,
       t.total_lock_wait_seconds,
       s.lock_wait_seconds,
       s.lock_wait_seconds/t.total_lock_wait_seconds frac_of_total,
       s.sample_lock_requests
FROM spanner_sys.lock_stats_total_10minute t, spanner_sys.lock_stats_top_10minute s
WHERE
  t.interval_end = "2020-11-12T22:50:00Z" and s.interval_end = t.interval_end;
row_range_start_key total_lock_wait_seconds lock_wait_seconds frac_of_total sample_lock_requests
Singers(32) 780,193 780,193 1 LOCK_MODE: WriterShared

SPALTE: Singers.SingerInfo

LOCK_MODE: ReaderShared

SPALTE: Singers.SingerInfo

In dieser Ergebnistabelle sehen Sie, dass der Konflikt in der Tabelle Singers unter dem Schlüssel SingerId=32 aufgetreten ist. Singers.SingerInfo ist die Spalte, in der der Sperrkonflikt zwischen ReaderShared und WriterShared ist aufgetreten.

Dies ist ein häufiger Konflikttyp, wenn eine Transaktion versuchen, eine bestimmte Zelle zu lesen, und die andere Transaktion versucht, in dieselbe Zelle zu schreiben. Wir kennen jetzt die genaue Datenzelle, um die die Transaktionen konkurrieren auf das Schlosssymbol. Im nächsten Schritt identifizieren wir die Transaktionen, um die Schlösser kämpfen.

Ermitteln, welche Transaktionen auf die Spalten zugreifen, die am Sperrkonflikt beteiligt sind

Um die Transaktionen zu identifizieren, bei denen eine erhebliche Commit-Latenz auftritt innerhalb eines bestimmten Zeitintervalls aufgrund von Sperrkonflikten auftreten, müssen Sie aus der Tabelle Tabelle SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE:

  • fprint
  • read_columns
  • write_constructive_columns
  • avg_commit_latency_seconds

Sie müssen nach gesperrten Spalten filtern, die aus der Tabelle SPANNER_SYS.LOCK_STATS_TOP_10MINUTE:

  • Transaktionen, die eine Spalte lesen, die einen Sperrkonflikt verursacht hat wenn versucht wird, die ReaderShared-Sperre zu erhalten.

  • Transaktionen, die in eine Spalte schreiben, die während des Versuchs, eine WriterShared-Sperre zu erhalten, in Konflikt stehen.

SELECT
  fprint,
  read_columns,
  write_constructive_columns,
  avg_commit_latency_seconds
FROM spanner_sys.txn_stats_top_10minute t2
WHERE (
  EXISTS (
    SELECT * FROM t2.read_columns columns WHERE columns IN (
      SELECT DISTINCT(req.COLUMN)
      FROM spanner_sys.lock_stats_top_10minute t, t.SAMPLE_LOCK_REQUESTS req
      WHERE req.LOCK_MODE = "ReaderShared" AND t.interval_end ="2020-11-12T23:50:00Z"))
OR
  EXISTS (
    SELECT * FROM t2.write_constructive_columns columns WHERE columns IN (
      SELECT DISTINCT(req.COLUMN)
      FROM spanner_sys.lock_stats_top_10minute t, t.SAMPLE_LOCK_REQUESTS req
      WHERE req.LOCK_MODE = "WriterShared" AND t.interval_end ="2020-11-12T23:50:00Z"))
)
AND t2.interval_end ="2020-11-12T23:50:00Z"
ORDER BY avg_commit_latency_seconds DESC;

Das Abfrageergebnis wird nach der Spalte avg_commit_latency_seconds sortiert, sodass die Transaktion mit der höchsten Commit-Latenz zuerst angezeigt wird.

fprint read_columns write_constructive_columns avg_commit_latency_seconds
1866043996151916800


['Singers.SingerInfo',
'Singers.FirstName',
'Singers.LastName',
'Singers._exists']
['Singers.SingerInfo'] 4,89
4168578515815911936 [] ['Singers.SingerInfo'] 3,65

Die Abfrageergebnisse zeigen, dass zwei Transaktionen versucht haben, auf das Singers.SingerInfo: Dies ist die Spalte, bei der im ausgewählten Zeitraum Sperrkonflikte aufgetreten sind. Sobald Sie die Transaktionen identifiziert haben, die die Sperrkonflikte verursachen, können Sie die Transaktionen mit ihrem Fingerabdruck (fprint) analysieren, um potenzielle Probleme zu identifizieren, die zu dem Problem beigetragen haben.

Nach der Überprüfung der Transaktion mit fprint=1866043996151916800 können Sie den read_columns und write_constructive_columns, um anzugeben, welcher Teil Ihres Anwendungscodes die Transaktion ausgelöst hat. Sie können sich dann die zugrunde liegende DML ansehen, die nicht nach dem Primärschlüssel SingerId gefiltert wird. Dies verursachte einen vollständigen Tabellenscan durchgeführt und die Tabelle gesperrt, bis der Commit der Transaktion durchgeführt wurde.

So beheben Sie den Sperrkonflikt:

  1. Verwenden Sie eine schreibgeschützte Transaktion, um die erforderlichen SingerId-Werte zu identifizieren.
  2. Verwenden Sie eine separate Lese-Schreib-Transaktion, um die Zeilen für die erforderlichen SingerId-Werte zu aktualisieren.

Best Practices anwenden, um Konflikte durch Sperren zu reduzieren

In unserem Beispielszenario konnten wir Sperrstatistiken und Transaktionsstatistiken verwenden, um unser Problem auf eine Transaktion einzugrenzen, die nicht den Primärschlüssel unserer Tabelle bei Aktualisierungen verwendet hat. Wir haben Ideen zur Verbesserung der Transaktion entwickelt, die darauf basiert, ob wir die Schlüssel der Zeilen, die wir aktualisieren möchten, schon vorher kennen konnten.

Beachten Sie diese Best Practices, um die Anzahl von Sperrkonflikten in Ihrer Datenbank zu reduzieren, wenn Sie potenzielle Probleme in Ihrer Lösung betrachten oder auch beim Entwerfen Ihrer Lösung.

  • Große Lesevorgänge in Lese-Schreib-Transaktionen vermeiden.

  • Verwenden Sie nach Möglichkeit schreibgeschützte Transaktionen, da dadurch keine Schlösser.

  • Vermeiden Sie vollständige Tabellenscans in einer Lese-Schreib-Transaktion. Dazu gehört das Schreiben einer DML-Bedingung für den Primärschlüssel oder die Zuweisung eines bestimmten Schlüsselbereichs bei Verwendung der Lese-API.

  • Halten Sie die Sperrzeit kurz, indem Sie die Änderung sofort nach wie möglich in einer Lese-Schreib-Transaktion lesen. Einen Lese-/Schreibmodus Transaktion garantiert, dass die Daten unverändert bleiben, nachdem Sie den Daten gespeichert, bis Sie die Änderung erfolgreich per Commit festgeschrieben haben. Um dies zu erreichen, Transaktion erfordert das Sperren der Datenzellen während des Lesevorgangs und während des Commit durchführen. Wenn Sie die Sperrzeit kurz halten, haben weniger Sperrkonflikte.

  • Bevorzugen Sie kleine Transaktionen gegenüber großen Transaktionen oder partitionierte DML für lang andauernde DML-Transaktionen. Ein lang andauernder Transaktion lange Zeit eine Sperre erwirbt, sollten Sie daher in Erwägung ziehen, eine Transaktion, die Tausende von Zeilen in mehrere kleinere Transaktionen, bei denen nach Möglichkeit Hunderte von Zeilen aktualisiert werden.

  • Wenn Sie die von einer Lese-Schreib-Transaktion bereitgestellte Garantie nicht benötigen, sollten Sie vor dem Commit der Änderung keine Daten in der Lese-Schreib-Transaktion lesen, z. B. durch Lesen der Daten in einer separaten schreibgeschützten Transaktion. Die meisten Sperrkonflikte treten aufgrund der starken Garantie auf, um sicherzustellen, dass die Daten zwischen dem Lese- und Commit unverändert bleiben. Wenn die Lese-Schreib-Transaktion müssen die Zellen nicht für lange Zeit gesperrt werden.

  • In einem Lese-/Schreibmodus nur den minimalen Satz von Spalten angeben, der erforderlich ist Transaktion. Spanner-Sperren pro Datenzelle sind möglich, Lese-Schreib-Transaktion liest überflüssige Spalten und erhält eine ReaderShared. auf diese Zellen. Dies kann zu Sperrkonflikten führen, wenn andere Transaktionen eine WriterShared-Sperre für Schreibvorgänge in den zu vielen Spalten erwerben. Für Beispiel: Sie können beim Lesen statt * eine Gruppe von Spalten angeben.

  • Minimieren Sie API-Aufrufe in einer Lese-Schreib-Transaktion. Latenz von API-Aufrufen zu Sperrkonflikten in Spanner führen, da API-Aufrufe Netzwerkverzögerungen und dienstseitigen Verzögerungen. Wir empfehlen, Ausführen von API-Aufrufen außerhalb von Lese-/Schreibtransaktionen nach Möglichkeit Wenn Sie API-Aufrufe in einer Lese-/Schreibtransaktion ausführen müssen, sollten Sie die Latenz Ihrer API-Aufrufe überwachen, um die Auswirkungen auf die Sperrdauer zu minimieren.

  • Orientieren Sie sich an den Best Practices für Schemadesign.

Nächste Schritte