Spanner proporciona estadísticas de bloqueo que te permiten identificar la clave de fila y las columnas de la tabla que fueron las fuentes principales de conflictos de bloqueo de transacciones en tu base de datos durante un período particular. Puedes recuperar estas estadísticas de las tablas del sistema SPANNER_SYS.LOCK_STATS*
mediante instrucciones de SQL.
Disponibilidad
Los datos SPANNER_SYS
solo están disponibles a través de interfaces de SQL; por ejemplo:
Página de Spanner Studio de una base de datos en la consola de Google Cloud
El comando
gcloud spanner databases execute-sql
El panel Bloquear estadísticas
La API de
executeQuery
Otros métodos de lectura única que proporciona Spanner no son compatibles con SPANNER_SYS
.
Estadísticas de bloqueo por clave de fila
Las siguientes tablas hacen un seguimiento de la clave de fila con el tiempo de espera más alto:
SPANNER_SYS.LOCK_STATS_TOP_MINUTE
: Son las claves de fila con los tiempos de bloqueo más altos durante intervalos de 1 minuto.SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
: Son las claves de fila con los tiempos de bloqueo más altos durante intervalos de 10 minutos.SPANNER_SYS.LOCK_STATS_TOP_HOUR
: Las claves de fila con los tiempos de bloqueo más altos durante intervalos de 1 hora
Estas tablas tienen las siguientes propiedades:
Cada tabla contiene datos de intervalos de tiempo no superpuestos de la longitud que se especifica en el nombre de la tabla.
Los intervalos se basan en tiempos de reloj. Los intervalos de 1 minuto finalizan en el minuto, los intervalos de 10 minutos finalizan cada 10 minutos a partir de la hora y los intervalos de 1 hora finalizan en la hora. Después de cada intervalo, Spanner recopila datos de todos los servidores y, poco después, los pone a disposición en las tablas SPANNER_SYS.
Por ejemplo, a las 11:59:30 a.m., los intervalos más recientes disponibles para las consultas de SQL son los siguientes:
- 1 minuto: de 11:58:00 a 11:58:59 a.m.
- 10 minutos: de 11:40:00 a 11:49:59 a.m.
- 1 hora: de 10:00:00 a 10:59:59 a.m.
Spanner agrupa las estadísticas iniciando el rango de clave de fila.
Cada fila contiene estadísticas del tiempo total de espera de bloqueo de un rango de clave de fila de inicio específico para el que Spanner captura estadísticas durante el intervalo especificado.
Si Spanner no puede almacenar información sobre cada rango de clave de fila para las esperas de bloqueo durante el intervalo, el sistema prioriza el rango de clave de fila con el tiempo de espera de bloqueo más alto durante el intervalo especificado.
Esquema de la tabla
Nombre de la columna | Tipo | Descripción |
---|---|---|
INTERVAL_END |
TIMESTAMP |
Fin del intervalo de tiempo en el que ocurrieron los conflictos de bloqueo incluidos. |
ROW_RANGE_START_KEY |
BYTES(MAX) |
La clave de fila donde ocurrió el conflicto de bloqueo. Cuando el conflicto incluye un rango de filas, este valor representa la clave inicial de ese rango. Un signo más, + , significa un rango.
Para obtener más información, consulta ¿Qué es una clave de inicio de rango de filas?.
|
LOCK_WAIT_SECONDS |
FLOAT64 |
El tiempo de espera acumulado de los conflictos de bloqueo registrados para todas las columnas en el rango de clave de fila, en segundos. |
SAMPLE_LOCK_REQUESTS |
ARRAY<STRUCT<
|
Cada entrada de este array corresponde a una solicitud de bloqueo de muestra que contribuyó al conflicto de bloqueo, ya sea porque espera un bloqueo o bloqueando otras transacciones, en la clave de fila (rango). La cantidad máxima de muestras en este array es 20.
Cada muestra contiene los siguientes tres campos:
|
Modos de bloqueo
Las operaciones de Spanner adquieren bloqueos cuando las operaciones son parte de una transacción de lectura y escritura. Las transacciones de solo lectura no adquieren bloqueos. Spanner usa diferentes modos de bloqueo para maximizar la cantidad de transacciones que tienen acceso a una celda de datos específica en un momento determinado. Cada cerradura tiene diferentes características. Por ejemplo, algunos bloqueos se pueden compartir entre varias transacciones, mientras que otros no.
Puede producirse un conflicto de bloqueo cuando intentas adquirir uno de los siguientes modos de bloqueo en una transacción.
Bloqueo
ReaderShared
: Es un bloqueo que permite que otras lecturas aún accedan a los datos hasta que tu transacción esté lista para confirmarse. Este bloqueo compartido se adquiere cuando una transacción de lectura y escritura lee datos.Bloqueo
WriterShared
: Este bloqueo se adquiere cuando una transacción de lectura y escritura intenta confirmar una escritura.Bloqueo
Exclusive
: Se adquiere un bloqueo exclusivo cuando una transacción de lectura y escritura, que ya adquirió un bloqueo de ReaderShared, intenta escribir datos después de que se completa la lectura. Un bloqueo exclusivo es una mejora de un bloqueoReaderShared
. Un bloqueo exclusivo es un caso especial de una transacción que contiene el bloqueoReaderShared
y el bloqueoWriterShared
al mismo tiempo. Ninguna otra transacción puede adquirir bloqueos en la misma celda.Bloqueo
WriterSharedTimestamp
: Un tipo especial de bloqueoWriterShared
que se adquiere cuando se insertan filas nuevas en una tabla que tiene una marca de tiempo de confirmación como parte de la clave primaria. Este tipo de bloqueo evita que los participantes de la transacción creen exactamente la misma fila y, por lo tanto, entren en conflicto entre sí. Spanner actualiza la clave de la fila insertada para que coincida con la marca de tiempo de confirmación de la transacción que realizó la inserción.
Para obtener más información sobre los tipos de transacciones y los tipos de bloqueos disponibles, consulta Transacciones.
Conflictos con el modo de bloqueo
En la siguiente tabla, se muestran los posibles conflictos entre los diferentes modos bloqueados.
Modos bloqueado | ReaderShared |
WriterShared |
Exclusive |
WriterSharedTimestamp |
---|---|---|---|---|
ReaderShared |
No | Sí | Sí | Sí |
WriterShared |
Sí | No | Sí | No aplicable |
Exclusive |
Sí | Sí | Sí | No aplicable |
WriterSharedTimestamp |
Sí | No aplicable | No aplicable | Sí |
Los bloqueos de WriterSharedTimestamp
solo se usan cuando se insertan filas nuevas con una marca de tiempo como parte de su clave primaria. Los bloqueos WriterShared
y Exclusive
se usan cuando se escribe en celdas existentes o se insertan filas nuevas sin marcas de tiempo. Como resultado, WriterSharedTimestamp
no puede entrar en conflicto con otros tipos de bloqueos, y esas situaciones se muestran como No aplicable en la tabla anterior.
La única excepción es ReaderShared
, que se puede aplicar a filas que no existen y, por lo tanto, podría entrar en conflicto con WriterSharedTimestamp
. Por ejemplo, un análisis completo de la tabla bloquea toda la tabla, incluso para las filas que no se crearon, por lo que es posible que ReaderShared
entre en conflicto con WriterSharedTimestamp
.
¿Qué es una clave de inicio de rango de filas?
La columna ROW_RANGE_START_KEY
identifica la clave primaria compuesta, o la clave primaria inicial de un rango de filas, que tiene conflictos de bloqueo. El siguiente esquema se usa para ilustrar un ejemplo.
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);
Como se muestra en la siguiente tabla de claves y rangos de clave de fila, un rango se representa con un signo de más, “+” en la clave. En esos casos, la clave representa la clave de inicio de un rango de claves en el que ocurrió un conflicto de bloqueo.
ROW_RANGE_START_KEY | Explicación |
---|---|
cantantes(2) | Tabla de cantantes en la clave SingerId=2 |
cantantes(2,1) | Tabla de álbumes en la clave SingerId=2,AlbumId=1 |
canciones(2,1,5) | Tabla de canciones en la clave SingerId=2,AlbumId=1,TrackId=5 |
canciones(2,1,5+) | Rango de claves de la tabla de canciones a partir de SingerId=2,AlbumId=1,TrackId=5 |
albums(2,1+) | Rango de claves de la tabla de álbumes a partir de SingerId=2,AlbumId=1 |
usuarios(3, 2020-11-01 12:34:56.426426+00:00) | Tabla de usuarios en la clave UserId=3, LastAccess=commit_timestamp |
Estadísticas agregadas
SPANNER_SYS
también contiene tablas en las que puedes almacenar datos agregados de las estadísticas de bloqueo que captura Spanner en un período específico:
SPANNER_SYS.LOCK_STATS_TOTAL_MINUTE
: Estadísticas agregadas de todas las esperas de bloqueo durante intervalos de 1 minuto.SPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE
: Estadísticas agregadas de todas las esperas de bloqueo durante intervalos de 10 minutos.SPANNER_SYS.LOCK_STATS_TOTAL_HOUR
: Estadísticas agregadas de todas las esperas de bloqueo durante intervalos de 1 hora
Las tablas conjuntas de estadísticas tienen las siguientes propiedades:
Cada tabla contiene datos de intervalos de tiempo no superpuestos de la longitud que se especifica en el nombre de la tabla.
Los intervalos se basan en tiempos de reloj. Los intervalos de 1 minuto finalizan en el minuto, los intervalos de 10 minutos finalizan cada 10 minutos a partir de la hora y los intervalos de 1 hora finalizan en la hora.
Por ejemplo, a las 11:59:30 a.m., los intervalos más recientes disponibles para las consultas de SQL en las estadísticas de bloqueo agregadas son los siguientes:
- 1 minuto: de 11:58:00 a 11:58:59 a.m.
- 10 minutos: de 11:40:00 a 11:49:59 a.m.
- 1 hora: de 10:00:00 a 10:59:59 a.m.
Cada fila contiene estadísticas de todas las esperas de bloqueo en la base de datos durante el intervalo especificado, agregadas. Solo hay una fila por intervalo de tiempo.
Las estadísticas capturadas en las tablas
SPANNER_SYS.LOCK_STATS_TOTAL_*
incluyen las esperas de bloqueo que Spanner no capturó en las tablasSPANNER_SYS.LOCK_STATS_TOP_*
.Algunas columnas de estas tablas están expuestas como métricas en Cloud Monitoring. Las métricas expuestas son las siguientes:
- Tiempo de espera de bloqueo
Para obtener más información, consulta Métricas de Spanner.
Esquema de la tabla
Nombre de la columna | Tipo | Descripción |
---|---|---|
INTERVAL_END |
TIMESTAMP |
Fin del intervalo en el que se produjo el conflicto de bloqueo |
TOTAL_LOCK_WAIT_SECONDS |
FLOAT64 |
Tiempo de espera total de bloqueo para conflictos de bloqueo registrados en toda la base de datos, en segundos. |
Consultas de ejemplo
El siguiente es un ejemplo de una instrucción de SQL que puedes usar para recuperar estadísticas de bloqueo. Puedes ejecutar estas instrucciones de SQL con las bibliotecas cliente, gcloud spanner o la consola de Google Cloud.
Enumerar las estadísticas de bloqueo del intervalo de 1 minuto anterior
La siguiente consulta muestra la información de espera de bloqueo para cada clave de fila con un conflicto de bloqueo, incluida la fracción de conflictos de bloqueo totales, durante el intervalo de tiempo de 1 minuto más reciente.
La función CAST()
convierte el campo de BYTES fila_range_start_key en 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;
Resultado de la consulta
row_range_start_key | total_lock_wait_seconds | lock_wait_seconds | frac_of_total | sample_lock_requests |
---|---|---|---|---|
canciones(2,1,1) | 2.37 | 1.76 | 0.7426 | LOCK_MODE: ReaderShared COLUMN: Singers.SingerInfo LOCK_MODE: WriterShared COLUMN: Singers.SingerInfo |
Usuarios(3, 2020-11-01 12:34:56.426426+00:00) | 2.37 | 0.61 | 0.2573 | LOCK_MODE: ReaderShared COLUMN: users._exists1 LOCK_MODE: WriterShared COLUMN: users._exists1 |
1 _exists
es un campo interno que se usa para verificar si una fila determinada existe o no.
Retención de datos
Como mínimo, Spanner conserva los datos de cada tabla durante los siguientes períodos:
SPANNER_SYS.LOCK_STATS_TOP_MINUTE
ySPANNER_SYS.LOCK_STATS_TOTAL_MINUTE
: Intervalos que abarcan las 6 horas anteriores.SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
ySPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE
: Intervalos que abarcan los 4 días anteriores.SPANNER_SYS.LOCK_STATS_TOP_HOUR
ySPANNER_SYS.LOCK_STATS_TOTAL_HOUR
: Intervalos que abarcan los 30 días anteriores.
Soluciona problemas de conflictos de bloqueo en tu base de datos con estadísticas de bloqueo
Puedes usar SQL o el panel Estadísticas de bloqueo para ver los conflictos de bloqueo en tu base de datos.
En los siguientes temas, se muestra cómo puedes investigar estos conflictos de bloqueo mediante código SQL.
Selecciona un período para investigar
Examinarás las métricas de latencia de la base de datos de Spanner y descubrirás el período en el que la app experimentó una latencia alta y un uso de CPU. Por ejemplo, el problema comenzó alrededor de las 10:50 p.m. del 12 de noviembre de 2020.
Determina si la latencia de confirmación de la transacción aumentó junto con el tiempo de espera de bloqueo durante el período seleccionado.
Las transacciones adquieren los bloqueos, por lo que, si los conflictos de bloqueo provocan tiempos de espera largos, deberíamos poder ver el aumento en la latencia de confirmación de la transacción junto con el aumento en el tiempo de espera de bloqueo.
Después de seleccionar un período para comenzar nuestra investigación, uniremos las estadísticas de transacción TXN_STATS_TOTAL_10MINUTE
con las estadísticas de bloqueo LOCK_STATS_TOTAL_10MINUTE
alrededor de ese tiempo para ayudarnos a comprender si el aumento del tiempo de espera de bloqueo contribuye al aumento de la latencia de confirmación promedio.
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;
Tomemos los siguientes datos como ejemplo de los resultados que obtenemos de nuestra consulta.
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 |
Los resultados anteriores muestran un aumento considerable en avg_commit_latency_seconds
y total_lock_wait_seconds
durante el mismo período de 2020-11-12
22:40:00 a 2020-11-12 22:50:00, y disminuyeron después. Es importante tener en cuenta que avg_commit_latency_seconds
es el tiempo promedio empleado solo para el paso de confirmación. Por otro lado, total_lock_wait_seconds
es el tiempo de bloqueo agregado para el período, por lo que el tiempo parece mucho más largo que el tiempo de confirmación de la transacción.
Ahora que confirmamos que el tiempo de espera de bloqueo está estrechamente relacionado con el aumento en la latencia de escritura, investigaremos en el siguiente paso qué filas y columnas causan la larga espera.
Descubre qué claves de fila y columnas tuvieron tiempos de espera de bloqueo prolongados durante el período seleccionado.
Para descubrir qué claves de fila y columnas experimentaron los altos tiempos de espera de bloqueo durante el período que investigamos, consultamos la tabla LOCK_STAT_TOP_10MINUTE
, que enumera las claves de fila y las columnas que más contribuyen a la espera de bloqueo.
La función CAST()
en la siguiente consulta convierte el campo de BYTES fila_range_start_key en 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 |
---|---|---|---|---|
Cantantes(32) | 780.193 | 780.193 | 1 | LOCK_MODE: WriterShared COLUMN: Singers.SingerInfo LOCK_MODE: ReaderShared COLUMN: Singers.SingerInfo |
En esta tabla de resultados, podemos ver que el conflicto ocurrió en la tabla Singers
en la clave SingerId=32. Singers.SingerInfo
es la columna en la que se produjo el conflicto de bloqueo entre ReaderShared
y WriterShared
.
Este es un tipo común de conflicto cuando hay una transacción que intenta leer una celda determinada y la otra intenta escribir en la misma celda. Ahora sabemos cuál es la celda de datos exacta por la que las transacciones compiten por el bloqueo, por lo que en el siguiente paso identificaremos las transacciones que compiten por los bloqueos.
Descubre qué transacciones acceden a las columnas involucradas en el conflicto de bloqueo
Para identificar las transacciones que experimentan una latencia de confirmación significativa dentro de un intervalo específico debido a conflictos de bloqueo, debes consultar las siguientes columnas de la tabla SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE
:
fprint
read_columns
write_constructive_columns
avg_commit_latency_seconds
Debes filtrar las columnas bloqueadas identificadas en la tabla SPANNER_SYS.LOCK_STATS_TOP_10MINUTE
:
Las transacciones que leen cualquier columna que generó un conflicto de bloqueo cuando intentaron adquirir el bloqueo de
ReaderShared
Transacciones que escriben en cualquier columna que incurrieron en un conflicto de bloqueo cuando intentaron adquirir un bloqueo
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;
El resultado de la consulta se ordena según la columna avg_commit_latency_seconds
para que veas que la transacción experimenta la latencia de confirmación más alta primero.
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 |
Los resultados de la consulta muestran que dos transacciones intentaron acceder a la columna Singers.SingerInfo
, que es la columna que tuvo conflictos de bloqueo durante el período.
Una vez que identifiques las transacciones que causan los conflictos de bloqueo, podrás analizarlas con su huella digital, fprint
, para identificar posibles problemas que contribuyeron al conflicto de bloqueo.
Después de revisar la transacción con fprint=1866043996151916800, puedes usar las columnas read_columns
y write_constructive_columns
para identificar qué parte del código de la aplicación activó la transacción. Luego, puedes ver el DML subyacente que no se filtra en la clave primaria, SingerId
. Esto provocó
un análisis completo de la tabla y la bloqueó hasta que se confirmó la transacción.
Para resolver el conflicto de bloqueo, puedes hacer lo siguiente:
- Usa una transacción de solo lectura para identificar los valores
SingerId
obligatorios. - Usa una transacción de lectura y escritura independiente para actualizar las filas de los valores
SingerId
requeridos.
Aplicar prácticas recomendadas para reducir la contención de bloqueo
En la situación de nuestro ejemplo, pudimos usar estadísticas de bloqueo y de transacción para reducir el problema a una transacción que no usaba la clave primaria de nuestra tabla cuando se realizaban actualizaciones. Se nos ocurrieron ideas para mejorar la transacción en función de si sabíamos o no las claves de las filas que queríamos actualizar de antemano.
Cuando analices los posibles problemas en tu solución, o incluso cuando diseñes tu solución, ten en cuenta estas prácticas recomendadas para reducir la cantidad de conflictos de bloqueo en tu base de datos.
Evita lecturas extensas en las transacciones de lectura y escritura
Usa transacciones de solo lectura siempre que sea posible, ya que no adquieren ningún bloqueo.
Evita los análisis completos de la tabla en una transacción de lectura y escritura. Esto incluye escribir una condicional de DML en la clave primaria o asignar un rango de claves específico cuando se usa la API de Read.
Mantén el período de bloqueo corto confirmando el cambio lo antes posible después de leer los datos en una transacción de lectura y escritura. Una transacción de lectura y escritura garantiza que los datos no se modificarán después de leerlos hasta que confirmes el cambio de forma correcta. Para lograrlo, la transacción requiere el bloqueo de las celdas de datos durante la lectura y la confirmación. Como resultado, si puedes mantener un período de bloqueo corto, es menos probable que las transacciones tengan conflictos de bloqueo.
Prioriza las transacciones pequeñas sobre las grandes o considera usar DML particionado para las transacciones DML de larga duración. Una transacción de larga duración adquiere un bloqueo durante mucho tiempo, así que considera dividir una transacción que toque miles de filas en varias transacciones más pequeñas que actualicen cientos de filas siempre que sea posible.
Si no necesitas la garantía que proporciona una transacción de lectura y escritura, evita leer los datos de la transacción de lectura y escritura antes de confirmar el cambio, por ejemplo, si lees los datos en una transacción de solo lectura independiente. La mayoría de los conflictos de bloqueo se producen debido a la garantía sólida, para garantizar que los datos no se modifiquen entre la lectura y la confirmación. Por lo tanto, si la transacción de lectura y escritura no lee ningún dato, no necesita bloquear las celdas durante mucho tiempo.
Especifica solo el conjunto mínimo de columnas necesarias en una transacción de lectura y escritura. Como los bloqueos de Spanner se aplican por celda de datos, cuando una transacción de lectura y escritura lee columnas excesivas, adquiere un bloqueo
ReaderShared
en estas celdas. Esto puede causar conflictos de bloqueo cuando otras transacciones adquieren un bloqueoWriterShared
en escrituras en las columnas excesivas. Por ejemplo, considera especificar un conjunto de columnas en lugar de*
en las operaciones de lectura.Minimiza las llamadas a la API en una transacción de lectura y escritura. La latencia de las llamadas a la API puede generar una contención de bloqueo en Spanner, ya que las llamadas a la API están sujetas a retrasos de la red y del servicio. Te recomendamos que realices llamadas a la API fuera de las transacciones de lectura y escritura siempre que sea posible. Si debes ejecutar llamadas a la API dentro de una transacción de lectura y escritura, asegúrate de supervisar la latencia de tus llamadas a la API para minimizar el impacto en el período de bloqueo de adquisición.
Sigue las prácticas recomendadas para el diseño de esquemas.
¿Qué sigue?
- Obtén más información sobre otras herramientas de introspección.
- Obtén información sobre otros datos que Spanner almacena para cada base de datos en la tabla del esquema de información de las bases de datos.
- Obtén más información sobre las prácticas recomendadas de SQL para Spanner.