Spanner fornisce statistiche di blocco che ti consentono di identificare la chiave di riga e
le colonne delle tabelle che sono state le principali origini dei conflitti di blocco delle transazioni nel
durante un determinato periodo di tempo. Puoi recuperare queste statistiche da
le tabelle di sistema SPANNER_SYS.LOCK_STATS*
utilizzando istruzioni SQL.
Disponibilità
I dati di SPANNER_SYS
sono disponibili solo tramite le interfacce SQL. Ad esempio:
Pagina Spanner Studio di un database nella console Google Cloud
La
gcloud spanner databases execute-sql
comandoLa sezione Approfondimenti sui blocchi dashboard
API
executeQuery
Gli altri metodi di lettura singoli forniti da Spanner non supportano
SPANNER_SYS
.
Bloccare le statistiche per chiave di riga
Le seguenti tabelle monitorano la chiave di riga con il tempo di attesa più alto:
SPANNER_SYS.LOCK_STATS_TOP_MINUTE
: chiavi di riga con il livello di attesa più alto per il blocco volte a intervalli di 1 minuto.SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
: chiavi di riga con il livello di attesa più alto per il blocco volte a intervalli di 10 minuti.SPANNER_SYS.LOCK_STATS_TOP_HOUR
: chiavi di riga con i tempi di attesa per il blocco più alti a intervalli di 1 ora
Queste tabelle hanno le seguenti proprietà:
Ogni tabella contiene dati per intervalli di tempo non sovrapposti della durata specificato dal nome della tabella.
Gli intervalli sono basati sugli orari dell'orologio. Gli intervalli di 1 minuto terminano ogni minuto, 10 gli intervalli di minuti terminano ogni 10 minuti a partire dall'ora e ogni ora che terminano dopo un'ora. Dopo ogni intervallo, Spanner raccoglie i dati da tutti i server e poi li rende disponibili nel file SPANNER_SYS tabelle.
Ad esempio, alle 11:59:30, gli intervalli più recenti disponibili per SQL le query sono:
- 1 minuto: 11:58:00-11:58:59
- 10 minuti: 11:40:00-11:49:59
- 1 ora: 10:00:00–10:59:59
Spanner raggruppa le statistiche iniziando l'intervallo di chiave di riga.
Ogni riga contiene le statistiche sul tempo totale di attesa del blocco di una determinata intervallo di chiave di riga iniziale per cui Spanner acquisisce statistiche durante per l'intervallo specificato.
Se Spanner non è in grado di archiviare le informazioni su ogni intervallo di chiave di riga per il tempo di attesa della serratura durante l'intervallo, il sistema assegna la priorità all'intervallo di chiave di riga con il tempo di attesa per il blocco più alto durante l'intervallo specificato.
Tutte le colonne delle tabelle sono nullable.
Schema tabella
Nome colonna | Tipo | Descrizione |
---|---|---|
INTERVAL_END |
TIMESTAMP |
Fine dell'intervallo di tempo in cui si sono verificati conflitti nei blocchi inclusi. |
ROW_RANGE_START_KEY |
BYTES(MAX) |
La chiave di riga in cui si è verificato il conflitto di blocco. Quando il conflitto
coinvolge un intervallo di righe, questo valore rappresenta il valore iniziale
chiave di quell'intervallo. Un segno più, + , indica un intervallo.
Per ulteriori informazioni,
consulta la sezione Cos'è una chiave iniziale dell'intervallo di righe.
|
LOCK_WAIT_SECONDS |
FLOAT64 |
Il tempo di attesa cumulativo del blocco per i conflitti registrati per tutti i blocchi le colonne nell'intervallo di chiave di riga, in secondi. |
SAMPLE_LOCK_REQUESTS |
ARRAY<STRUCT<
|
Ogni voce di questo array corrisponde a una richiesta di blocco di esempio che
ha contribuito al conflitto di blocco in attesa di un blocco o
impedendo ad altre transazioni di acquisire il blocco, sulla chiave
(intervallo) della riga specificata. Il numero massimo di campioni in questo array è 20.
Ogni esempio contiene i seguenti tre campi:
|
Modalità di blocco
Le operazioni Spanner acquisiscono blocchi quando le operazioni fanno parte di un una transazione di lettura/scrittura. Le transazioni di sola lettura per acquisire i blocchi. Spanner usa diverse modalità di blocco per massimizzare numero di transazioni che hanno accesso a una particolare cella di dati in un dato nel tempo. Serrature diverse hanno caratteristiche diverse. Ad esempio, alcune serrature possono essere condivisi tra più transazioni, mentre altri no.
Può verificarsi un conflitto di blocco quando tenti di acquisire uno dei seguenti blocchi in una transazione.
Blocco di
ReaderShared
: un blocco che consente ad altre letture di accedere comunque al fino a quando la transazione non è pronta per il commit. Questo blocco condiviso viene acquisito quando una transazione di lettura-scrittura legge i dati.Blocco
WriterShared
: questo blocco viene acquisito quando una transazione di lettura-scrittura di eseguire il commit di una scrittura.Blocco
Exclusive
: viene acquisito un blocco esclusivo durante una lettura/scrittura transazione, che ha già acquisito un blocco ReaderShared, tenta di scrivere al termine della lettura. Un blocco esclusivo è l'upgrade di SerraturaReaderShared
. Un blocco esclusivo è un caso speciale di una transazione tenendo premuti contemporaneamente la serraturaReaderShared
e la serraturaWriterShared
. Nessun'altra transazione può acquisire blocchi sulla stessa cella.Serratura
WriterSharedTimestamp
: un tipo speciale di serraturaWriterShared
che viene acquisito quando si inseriscono nuove righe in una tabella con un commit il timestamp all'interno della chiave primaria. Questo tipo di serratura impedisce ai partecipanti alla transazione di creare esattamente la stessa riga. pertanto sono in conflitto tra loro. Spanner aggiorna la chiave della riga inserita in modo che corrisponda al timestamp del commit della transazione che ha eseguito l'inserimento.
Per ulteriori informazioni sui tipi di transazioni e sui tipi di blocchi disponibili, consulta la sezione Transazioni.
Conflitti della modalità di blocco
La tabella seguente mostra i possibili conflitti tra le diverse modalità di blocco.
Modalità di blocco | ReaderShared |
WriterShared |
Exclusive |
WriterSharedTimestamp |
---|---|---|---|---|
ReaderShared |
No | Sì | Sì | Sì |
WriterShared |
Sì | No | Sì | Non applicabile |
Exclusive |
Sì | Sì | Sì | Non applicabile |
WriterSharedTimestamp |
Sì | Non applicabile | Non applicabile | Sì |
I blocchi WriterSharedTimestamp
vengono utilizzati solo quando inserisci nuove righe con un
come parte della chiave primaria. Le serrature WriterShared
e Exclusive
sono
utilizzata durante la scrittura nelle celle esistenti o l'inserimento di nuove righe senza timestamp. Di conseguenza, WriterSharedTimestamp
non può entrare in conflitto con altri tipi di serrature e questi scenari sono contrassegnati come Non applicabile nella tabella precedente.
L'unica eccezione è ReaderShared
, che può essere applicata a righe che non esistono
e, di conseguenza, potrebbe entrare in conflitto con WriterSharedTimestamp
. Ad esempio, una scansione completa della tabella blocca l'intera tabella anche per le righe che non sono state create, pertanto è possibile che ReaderShared
entri in conflitto con WriterSharedTimestamp
.
Che cos'è una chiave iniziale di un intervallo di righe?
La colonna ROW_RANGE_START_KEY
identifica la chiave primaria composita oppure
chiave primaria iniziale di un intervallo di righe, che presenta conflitti di blocco. Le seguenti
schema viene utilizzato per illustrare un esempio.
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);
Come mostrato nella seguente tabella di chiavi di riga e intervalli di chiavi di riga, un intervallo è rappresentato con un segno più "+" nella chiave. In questi casi, la chiave rappresenta La chiave iniziale di un intervallo di chiavi in cui si è verificato un conflitto di blocco.
ROW_RANGE_START_KEY | Spiegazione |
---|---|
cantanti(2) | Tabella Cantanti con chiave SingerId=2 |
album(2,1) | Tabella album nella chiave SingerId=2,AlbumId=1 |
brani(2,1,5) | Tabella dei brani al tasto SingerId=2,AlbumId=1,TrackId=5 |
brani(2,1,5+) | Intervallo tasti della tabella dei brani che inizia da SingerId=2,AlbumId=1,TrackId=5 |
album(2,1+) | Intervallo chiavi della tabella album che inizia da SingerId=2,AlbumId=1 |
utenti(3, 2020-11-01 12:34:56.426426+00:00) | Tabella degli utenti nella chiave UserId=3, LastAccess=commit_timestamp |
Statistiche aggregate
SPANNER_SYS
contiene anche tabelle per archiviare i dati aggregati per le statistiche di blocco
acquisite da Spanner in un periodo di tempo specifico:
SPANNER_SYS.LOCK_STATS_TOTAL_MINUTE
: statistiche aggregate per tutti i blocchi attende durante intervalli di 1 minuto.SPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE
: statistiche aggregate per tutti i blocchi attende durante intervalli di 10 minuti.SPANNER_SYS.LOCK_STATS_TOTAL_HOUR
: statistiche aggregate per tutti i tempi di attesa della serratura a intervalli di 1 ora.
Le tabelle delle statistiche aggregate hanno le seguenti proprietà:
Ogni tabella contiene dati per intervalli di tempo non sovrapposti della durata specificato dal nome della tabella.
Gli intervalli sono basati sugli orari dell'orologio. Gli intervalli di 1 minuto terminano ogni minuto, 10 gli intervalli di minuti terminano ogni 10 minuti a partire dall'ora e ogni ora che terminano dopo un'ora.
Ad esempio, alle 00:59:30, gli intervalli più recenti disponibili per le query SQL sulle statistiche di blocco aggregate sono:
- 1 minuto: 11:58:00-11:58:59
- 10 minuti: 11:40:00-11:49:59
- 1 ora: 10:00:00–10:59:59
Ogni riga contiene le statistiche relative a tutte le attese dei blocchi nel database durante l'intervallo specificato, aggregate insieme. È presente una sola riga per volta intervallo di tempo.
Le statistiche acquisite nelle tabelle
SPANNER_SYS.LOCK_STATS_TOTAL_*
includi i tempi di attesa del blocco che Spanner non ha acquisito nellaSPANNER_SYS.LOCK_STATS_TOP_*
tabelle.Alcune colonne di queste tabelle sono esposte come metriche in Cloud Monitoring. Le metriche esposte sono:
- Tempo di attesa per il blocco
Per ulteriori informazioni, consulta le metriche di Spanner.
Schema tabella
Nome colonna | Tipo | Descrizione |
---|---|---|
INTERVAL_END |
TIMESTAMP |
Fine dell'intervallo di tempo in cui si è verificato il conflitto di blocco. |
TOTAL_LOCK_WAIT_SECONDS |
FLOAT64 |
Tempo di attesa totale per i conflitti di blocco registrati per l'intero database, in secondi. |
Esempi di query
Di seguito è riportato un esempio di istruzione SQL che puoi usare per recuperare un blocco statistiche. Puoi eseguire queste istruzioni SQL utilizzando il comando librerie, gcloud spanner, o il Console Google Cloud.
Elenca le statistiche di blocco per l'intervallo di 1 minuto precedente
La seguente query restituisce le informazioni di attesa della serratura per ogni chiave di riga con un conflitto di blocchi, inclusa la frazione dei conflitti totali di blocchi, durante la maggior parte a un intervallo di tempo recente di 1 minuto.
La funzione CAST()
converte il valore row_range_start_key BYTES
su una 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;
Output query
row_range_start_key | total_lock_wait_seconds | lock_wait_seconds | frac_of_total | sample_lock_requests |
---|---|---|---|---|
Brani(2; 1; 1) | 2,37 | 1,76 | 0,7426 | LOCK_MODE: Condivisione con Reader COLONNA: Cantanti.SingerInfo LOCK_MODE: WriterShared COLONNA: Cantanti.SingerInfo |
Utenti(3, 2020-11-01 12:34:56.426426+00:00) | 2,37 | 0,61 | 0,2573 | LOCK_MODE: Condivisione con Reader COLONNA: users._exists1 LOCK_MODE: WriterShared COLONNA: users._exists1 |
1 _exists
è un campo interno utilizzato per verificare se una
che una determinata riga esista o meno.
Conservazione dei dati
Spanner conserva i dati di ogni tabella come minimo per il periodo di tempo seguente periodi:
SPANNER_SYS.LOCK_STATS_TOP_MINUTE
eSPANNER_SYS.LOCK_STATS_TOTAL_MINUTE
: intervalli che coprono i 6 precedenti nell'orario lavorativo locale del TAM.SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
eSPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE
: intervalli che coprono i 4 precedenti giorni.SPANNER_SYS.LOCK_STATS_TOP_HOUR
eSPANNER_SYS.LOCK_STATS_TOTAL_HOUR
: Intervalli che coprono i 30 giorni precedenti.
Risolvere i conflitti di blocco nel database utilizzando le statistiche sui blocchi
Puoi utilizzare SQL o il blocco approfondimenti dashboard per visualizzare i conflitti dei blocchi nel tuo database.
Gli argomenti che seguono mostrano come esaminare questi conflitti di blocco utilizzando il codice SQL.
Seleziona un periodo di tempo da esaminare
Esaminerai le metriche Latenza per Spanner e scoprire un periodo di tempo in cui la tua app riscontra un'alta latenza e utilizzo della CPU. Ad esempio, il problema ha iniziato a verificarsi intorno alle 22:50 del 12 novembre 2020.
Determina se la latenza di commit della transazione è aumentata insieme al tempo di attesa del blocco durante il periodo selezionato
I blocchi vengono acquisiti dalle transazioni. Pertanto, se i conflitti di blocco causano lunghi tempi di attesa, dovremmo essere in grado di vedere l'aumento della latenza di commit delle transazioni con l'aumento del tempo di attesa della serratura.
Dopo aver selezionato un periodo di tempo per l'inizio dell'indagine, parteciperemo al
statistiche delle transazioni TXN_STATS_TOTAL_10MINUTE
con statistiche di blocco LOCK_STATS_TOTAL_10MINUTE
a quell'ora per aiutarci
capire se l'aumento della latenza media di commit è contribuito a
aumenta il tempo di attesa della serratura.
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;
Prendi i seguenti dati come esempio dei risultati che otteniamo dai nostri query.
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 |
12-11-2020 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 |
12-11-2020 22:50:00-07:00 | 3,741 | 780,193 |
12-11-2020 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 |
Questi risultati precedenti mostrano un aumento significativo della metrica avg_commit_latency_seconds
e total_lock_wait_seconds
nello stesso periodo di tempo 12/11/2020
22:40:00 a 2020-11-12 22:50:00 e successivamente è sceso. Tieni presente che
è che avg_commit_latency_seconds
è il tempo medio trascorso solo
il passaggio di commit. D'altra parte, total_lock_wait_seconds
è
tempo di blocco aggregate per il periodo, quindi sembra molto più lungo rispetto a
e il tempo di commit della transazione.
Ora che abbiamo confermato che il tempo di attesa per il blocco è strettamente correlato all'aumento della latenza di scrittura, nel passaggio successivo indagheremo quali righe e colonne causa una lunga attesa.
Scopri quali chiavi di riga e colonne hanno avuto lunghi tempi di attesa per il blocco durante il periodo selezionato
Per scoprire quali chiavi di riga e colonne hanno riscontrato i tempi di attesa elevati per il blocco
durante il periodo in cui stiamo indagando, eseguiamo query sul LOCK_STAT_TOP_10MINUTE
che elenca le chiavi di riga e le colonne che contribuiscono maggiormente al blocco
attendere.
La funzione CAST()
nella seguente query converte il valore
riga_range_start_key BYTES su una 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_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 |
---|---|---|---|---|
Cantanti(32) | 780,193 | 780,193 | 1 | LOCK_MODE: WriterShared COLONNA: Cantanti.SingerInfo LOCK_MODE: Condivisione con Reader COLONNA: Cantanti.SingerInfo |
Da questa tabella dei risultati, possiamo vedere che il conflitto si è verificato nella Singers
nella chiave SingerId=32. Singers.SingerInfo
è la colonna in cui
si è verificato un conflitto di blocco tra ReaderShared
e WriterShared
.
Si tratta di un tipo comune di conflitto quando una transazione tenta di leggere una determinata cella e l'altra transazione tenta di scrivere nella stessa cella. Ora sappiamo la cella di dati esatta per la quale le transazioni competono per la serratura, quindi nel passaggio successivo identificheremo le transazioni in competizione per le serrature.
Trovare le transazioni che accedono alle colonne coinvolte nel conflitto di blocco
Identificare le transazioni che stanno riscontrando una latenza di commit significativa
in un intervallo di tempo specifico a causa di conflitti di blocco, devi eseguire una query
le seguenti colonne dal
Tabella SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE
:
fprint
read_columns
write_constructive_columns
avg_commit_latency_seconds
Devi filtrare in base alle colonne bloccate identificate dal
Tabella SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
:
Transazioni che leggono le colonne interessate da un conflitto di blocco durante il tentativo di acquisire il blocco
ReaderShared
.Transazioni che scrivono in qualsiasi colonna che ha generato un conflitto di blocco quando si tenta di acquisire un blocco
WriterShared
.
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;
Il risultato della query viene ordinato in base alla colonna avg_commit_latency_seconds
, in modo che sia visibile
con la latenza di commit più alta.
Fprint | read_columns | write_constructive_columns | avg_commit_latency_seconds |
---|---|---|---|
1866043996151916800 |
['Singers.SingerInfo', 'Singers.FirstName', 'Singers.LastName', 'Singers._exists'] |
['Cantanti.InfoSinger'] | 4,89 |
4168578515815911936 | [] | ['Cantanti.InfoSinger'] | 3,65 |
I risultati della query mostrano che due transazioni hanno tentato di accedere
Colonna Singers.SingerInfo
, ovvero la colonna con conflitti di blocco durante il periodo di tempo in questione.
Dopo aver identificato le transazioni che causano i conflitti di blocco, puoi analizzare
le transazioni utilizzando la propria impronta, fprint
, per identificare potenziali problemi
che hanno contribuito al conflitto di blocchi.
Dopo aver esaminato la transazione con fprint=1866043996151916800, puoi utilizzare il metodo
read_columns
e write_constructive_columns
colonne per identificare quale parte
del codice dell'applicazione ha attivato la transazione. Puoi quindi visualizzare
DML sottostante che non filtra in base alla chiave primaria, SingerId
. Ciò ha causato
una scansione completa della tabella e bloccata la tabella fino al commit della transazione.
Per risolvere il conflitto di blocchi, puoi procedere come segue:
- Utilizza una transazione di sola lettura per identificare i valori
SingerId
obbligatori. - Utilizza una transazione di lettura e scrittura separata per aggiornare le righe dei valori
SingerId
richiesti.
Applica le best practice per ridurre il conflitto di blocchi
Nel nostro scenario di esempio, siamo riusciti a utilizzare le statistiche di blocco e le statistiche per limitare il problema a una transazione che non utilizzava chiave primaria della tabella quando esegui gli aggiornamenti. Abbiamo elaborato delle idee per migliorare la transazione se conosciamo le chiavi delle righe che volevamo aggiornarli prima o meno.
Quando esamini potenziali problemi nella tua soluzione o anche quando progetti di sicurezza, considera queste best practice per ridurre il numero di conflitti di blocchi nel tuo database.
Evita letture di grandi dimensioni all'interno di transazioni di lettura-scrittura.
Se possibile, utilizza transazioni di sola lettura, in quanto non acquisiscono serrature.
Evita scansioni complete delle tabelle in una transazione di lettura-scrittura. Ciò include la scrittura di un comando DML condizionale sulla chiave principale o l'assegnazione di un intervallo di chiavi specifico quando si utilizza l'API Read.
Per evitare un periodo di blocco breve, esegui il commit della modifica subito dopo Leggere i dati possibili in una transazione di lettura/scrittura. Un sistema di lettura/scrittura transazione garantisce che i dati rimangano invariati dopo la lettura del fino a quando non esegui il commit della modifica. A questo scopo, richiede il blocco delle celle di dati durante la lettura e eseguire il commit. Di conseguenza, se riuscite a limitare il periodo di blocco, le transazioni hanno meno probabilità di avere conflitti di blocchi.
Prediligi le transazioni di piccola entità rispetto alle transazioni di grandi dimensioni oppure considera la modalità Partizionata DML per le transazioni DML a lunga esecuzione. A lungo termine una transazione acquisisce un blocco per un lungo periodo, quindi valuta la possibilità di interrompere transazione che tocca migliaia di righe in più righe che aggiornano centinaia di righe, se possibile.
Se non ti occorre la garanzia fornita da una transazione di lettura/scrittura, evita leggere qualsiasi dato nella transazione di lettura/scrittura prima di eseguire il commit della modifica, ad esempio leggendo i dati in una transazione separata di sola lettura. La maggior parte delle serrature si verificano conflitti a causa dell'efficace garanzia, per garantire che i dati rimangano invariati tra la lettura e il commit. Quindi, se la transazione di lettura/scrittura non viene dati, non occorre bloccare le celle per molto tempo.
Specifica solo l'insieme minimo di colonne richieste in una procedura di lettura/scrittura transazione. Poiché i blocchi di Spanner sono per cella di dati, quando la transazione di lettura/scrittura legge un numero eccessivo di colonne, acquisisce un valore
ReaderShared
bloccare queste celle. Ciò potrebbe causare conflitti di blocco quando altre transazioni acquisiscono un bloccoWriterShared
durante le scritture nelle colonne in eccesso. Per Ad esempio, valuta la possibilità di specificare un insieme di colonne anziché*
alla lettura.Riduci al minimo le chiamate API in una transazione di lettura-scrittura. Latenza delle chiamate API potrebbe comportare la contesa del blocco in Spanner, poiché le chiamate API vengono soggetti a ritardi di rete e a ritardi lato servizio. I nostri suggerimenti effettuare chiamate API al di fuori delle transazioni di lettura/scrittura quando possibile. Se è necessario eseguire chiamate API all'interno di una transazione di lettura/scrittura, monitora la latenza delle chiamate API per ridurre al minimo l'impatto sul blocco periodo di acquisizione.
Passaggi successivi
- Scopri di più sugli altri strumenti di introspezione.
- Scopri di più sulle altre informazioni che Spanner archivia per ogni database in Lo schema di informazioni dei database tabella.
- Scopri di più sulle best practice per SQL per Spanner.