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:
Die Spanner Studio-Seite einer Datenbank in der Google Cloud Console
Die Statistiken zu Sperren Dashboard
Mit der
executeQuery
API
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<
|
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:
|
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 einerReaderShared
-Schloss. Eine exklusive Sperre ist ein Sonderfall einer Transaktion, die gleichzeitig dieReaderShared
-Sperre und dieWriterShared
-Sperre enthält. Keine andere Transaktion kann eine Sperre für dieselbe Zelle abrufen.WriterSharedTimestamp
-Schloss: eine spezielle Art vonWriterShared
-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-IntervallenSPANNER_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 imSPANNER_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
undSPANNER_SYS.LOCK_STATS_TOTAL_MINUTE
: Intervalle der letzten 6 Stunden.SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
undSPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE
: Intervalle der letzten 4 Tage.SPANNER_SYS.LOCK_STATS_TOP_HOUR
undSPANNER_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:
- Verwenden Sie eine schreibgeschützte Transaktion, um die erforderlichen
SingerId
-Werte zu identifizieren. - 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.
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 eineWriterShared
-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
- Weitere Informationen zu Tools zur Selbstbeobachtung
- Weitere Informationen zu den anderen Informationen, die Spanner für jede Datenbank in der Informationsschematabelle der Datenbank speichert
- Best Practices für SQL für Spanner.