Bloquear estadísticas

Spanner proporciona estadísticas de bloqueo que le permiten identificar la clave de fila y las columnas de la tabla que fueron las principales fuentes de conflictos de bloqueo de transacciones en su base de datos durante un periodo concreto. Puedes obtener estas estadísticas de las tablas de sistema SPANNER_SYS.LOCK_STATS* mediante instrucciones SQL.

Acceder a las estadísticas de bloqueo

Spanner proporciona las estadísticas de los bloqueos en el esquema SPANNER_SYS. Puedes acceder a los datos de SPANNER_SYS de las siguientes formas:

  • Página de Spanner Studio de una base de datos en la Google Cloud consola

  • El comando gcloud spanner databases execute-sql.

  • El panel de control Información útil sobre el bloqueo.

  • El método executeSql o el método executeStreamingSql.

    Los siguientes métodos de lectura única que proporciona Spanner no admiten SPANNER_SYS:

    • Realizar una lectura fuerte desde una sola fila o varias filas en una tabla.
    • Realizar una lectura inactiva de una sola fila o varias filas en una tabla.
    • Leer desde una sola fila o varias filas en un índice secundario.

Bloquear estadísticas por clave de fila

En las siguientes tablas se hace un seguimiento de la clave de fila con el tiempo de espera más alto:

  • SPANNER_SYS.LOCK_STATS_TOP_MINUTE: teclas de fila con los tiempos de espera de bloqueo más altos durante intervalos de 1 minuto.

  • SPANNER_SYS.LOCK_STATS_TOP_10MINUTE: teclas de fila con los tiempos de espera de bloqueo más altos durante intervalos de 10 minutos.

  • SPANNER_SYS.LOCK_STATS_TOP_HOUR: claves de fila con los tiempos de espera 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 duración que se especifica en el nombre de la tabla.

  • Los intervalos se basan en la hora del reloj. Los intervalos de 1 minuto terminan en el minuto, los intervalos de 10 minutos terminan cada 10 minutos a partir de la hora en punto y los intervalos de 1 hora terminan a la hora en punto. Después de cada intervalo, Spanner recoge 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, los intervalos más recientes disponibles para las consultas SQL son los siguientes:

    • 1 minuto: de 11:58:00 a 11:58:59
    • 10 minutos: de 11:40:00 a 11:49:59
    • 1 hora: de 10:00:00 a 10:59:59
  • Spanner agrupa las estadísticas por intervalo de claves de fila inicial.

  • Cada fila contiene estadísticas sobre el tiempo total de espera de bloqueo de un intervalo de claves de fila inicial concreto para el que Spanner recoge estadísticas durante el intervalo especificado.

  • Si Spanner no puede almacenar información sobre todos los intervalos de claves de fila para las esperas de bloqueo durante el intervalo, el sistema prioriza el intervalo de claves de fila con el tiempo de espera de bloqueo más alto durante el intervalo especificado.

  • Todas las columnas de las tablas admiten valores nulos.

Esquema de tabla

Nombre de la columna Tipo Descripción
INTERVAL_END TIMESTAMP Fin del intervalo de tiempo en el que se han producido los conflictos de bloqueo incluidos.
ROW_RANGE_START_KEY BYTES(MAX) La clave de fila en la que se ha producido el conflicto de bloqueo. Cuando el conflicto implica un intervalo de filas, este valor representa la clave inicial de ese intervalo. El signo más (+) indica un intervalo. Para obtener más información, consulta ¿Qué es una clave de inicio de intervalo de filas?
LOCK_WAIT_SECONDS FLOAT64 Tiempo de espera acumulativo de los conflictos de bloqueo registrados en todas las columnas del intervalo de claves de fila, en segundos.
SAMPLE_LOCK_REQUESTS ARRAY<STRUCT<
  column STRING,
  lock_mode STRING,
   transaction_tag STRING>>
Cada entrada de esta matriz corresponde a una solicitud de bloqueo de muestra que ha contribuido al conflicto de bloqueo, ya sea esperando un bloqueo o impidiendo que otras transacciones obtengan el bloqueo en la clave (intervalo) de la fila dada. El número máximo de muestras de esta matriz es 20.
Cada muestra contiene los tres campos siguientes:
  • lock_mode: el modo de bloqueo que se ha solicitado. Para obtener más información, consulta Modos de bloqueo .
  • column: la columna que ha tenido un conflicto de bloqueo. El formato de este valor es tablename.columnname.
  • transaction_tag: la etiqueta de la transacción que ha enviado la solicitud. Para obtener más información sobre el uso de etiquetas, consulta Solucionar problemas con etiquetas de transacción.
Todas las solicitudes de bloqueo que han contribuido a los conflictos de bloqueo se muestrean de forma aleatoria y uniforme, por lo que es posible que solo se registre en esta matriz la mitad de un conflicto (ya sea el propietario o el elemento en espera).

Modos de bloqueo

Las operaciones de Spanner adquieren bloqueos cuando forman 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 el número de transacciones que tienen acceso a una celda de datos concreta en un momento dado. Cada cerradura tiene unas características diferentes. Por ejemplo, algunos bloqueos se pueden compartir entre varias transacciones, mientras que otros no.

Se puede producir un conflicto de bloqueo cuando intentas adquirir uno de los siguientes modos de bloqueo en una transacción.

  • ReaderShared Bloqueo: un bloqueo que permite que otras lecturas sigan accediendo a los datos hasta que tu transacción esté lista para confirmarse. Este bloqueo compartido se obtiene cuando una transacción de lectura y escritura lee datos.

  • WriterShared Bloqueo: este bloqueo se adquiere cuando una transacción de lectura y escritura intenta confirmar una escritura.

  • Exclusive Bloqueo: se adquiere un bloqueo exclusivo cuando una transacción de lectura y escritura, que ya ha adquirido un bloqueo ReaderShared, intenta escribir datos después de completar la lectura. Una cerradura exclusiva es una mejora de una cerradura ReaderShared. Un bloqueo exclusivo es un caso especial de una transacción que tiene tanto el bloqueo ReaderShared como el bloqueo WriterShared al mismo tiempo. Ninguna otra transacción puede adquirir ningún bloqueo en la misma celda.

  • WriterSharedTimestamp Bloqueo: un tipo especial de bloqueo WriterShared que se adquiere al insertar filas nuevas en una tabla que tiene una marca de tiempo de confirmación como parte de la clave principal. Este tipo de bloqueo impide que los participantes de la transacción creen la misma fila y, por lo tanto, que 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 ha realizado la inserción.

Para obtener más información sobre los tipos de transacciones y los tipos de bloqueos disponibles, consulta Transacciones.

Conflictos de modo de bloqueo

En la siguiente tabla se muestran los posibles conflictos entre los diferentes modos de bloqueo.

Modos de bloqueo ReaderShared WriterShared Exclusive WriterSharedTimestamp
ReaderShared No
WriterShared No No aplicable
Exclusive No aplicable
WriterSharedTimestamp No aplicable No aplicable

Las WriterSharedTimestamp solo se usan al insertar filas nuevas con una marca de tiempo como parte de su clave principal. Los bloqueos WriterShared y Exclusive se usan al escribir en celdas o insertar filas nuevas sin marcas de tiempo. Por lo tanto, WriterSharedTimestamp no puede entrar en conflicto con otros tipos de cerraduras, y esos casos 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 una tabla bloquea toda la tabla, incluso las filas que no se han creado, por lo que es posible que ReaderShared entre en conflicto con WriterSharedTimestamp.

¿Qué es una clave de inicio de intervalo de filas?

La columna ROW_RANGE_START_KEY identifica la clave principal compuesta o la clave principal inicial de un intervalo 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 de fila e intervalos de claves de fila, un intervalo se representa con el signo más ("+") en la clave. En esos casos, la clave representa la clave inicial de un intervalo de claves en el que se ha producido un conflicto de bloqueo.

ROW_RANGE_START_KEY Explicación
cantantes(2) Tabla Singers con la clave SingerId=2
albums(2,1) Tabla Albums con las claves SingerId=2 y AlbumId=1
canciones(2,1,5) Tabla Songs en la clave SingerId=2,AlbumId=1,TrackId=5
canciones(2,1,5+) Intervalo de claves de la tabla Songs que empieza en SingerId=2, AlbumId=1 y TrackId=5
albums(2,1+) Intervalo de claves de la tabla Albums que empieza en SingerId=2,AlbumId=1
users(3, 2020-11-01 12:34:56.426426+00:00) Tabla de usuarios con la clave UserId=3 y LastAccess=commit_timestamp

Estadísticas agregadas

SPANNER_SYS también contiene tablas para almacenar datos agregados de las estadísticas de bloqueo capturadas por Spanner en un periodo específico:

  • SPANNER_SYS.LOCK_STATS_TOTAL_MINUTE: estadísticas agregadas de todos los tiempos de espera de bloqueos durante intervalos de 1 minuto.

  • SPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE: estadísticas agregadas de todos los tiempos de espera de bloqueos durante intervalos de 10 minutos.

  • SPANNER_SYS.LOCK_STATS_TOTAL_HOUR: estadísticas agregadas de todas las esperas de bloqueo en intervalos de 1 hora.

Las tablas de estadísticas agregadas tienen las siguientes propiedades:

  • Cada tabla contiene datos de intervalos de tiempo no superpuestos de la duración que se especifica en el nombre de la tabla.

  • Los intervalos se basan en la hora del reloj. Los intervalos de 1 minuto terminan en el minuto, los intervalos de 10 minutos terminan cada 10 minutos a partir de la hora en punto y los intervalos de 1 hora terminan a la hora en punto.

    Por ejemplo, a las 11:59:30, los intervalos más recientes disponibles para las consultas SQL sobre estadísticas de bloqueo agregadas son los siguientes:

    • 1 minuto: de 11:58:00 a 11:58:59
    • 10 minutos: de 11:40:00 a 11:49:59
    • 1 hora: de 10:00:00 a 10:59:59
  • Cada fila contiene estadísticas de todas las esperas de bloqueo de la base de datos durante el intervalo especificado, agregadas. Solo hay una fila por intervalo de tiempo.

  • Las estadísticas recogidas en las tablas SPANNER_SYS.LOCK_STATS_TOTAL_* incluyen esperas de bloqueo que Spanner no ha recogido en las tablas SPANNER_SYS.LOCK_STATS_TOP_*.

  • Algunas columnas de estas tablas se muestran 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 las métricas de Spanner.

Esquema de tabla

Nombre de la columna Tipo Descripción
INTERVAL_END TIMESTAMP Fin del intervalo de tiempo en el que se ha producido el conflicto de bloqueo.
TOTAL_LOCK_WAIT_SECONDS FLOAT64 Tiempo total de espera de los bloqueos por conflictos de bloqueo registrados en toda la base de datos, en segundos.

Consultas de ejemplo

A continuación, se muestra un ejemplo de una instrucción SQL que puede usar para obtener estadísticas de bloqueo. Puedes ejecutar estas instrucciones SQL mediante las bibliotecas de cliente, gcloud spanner o la Google Cloud consola.

Lista las estadísticas de bloqueo del intervalo de 1 minuto anterior

La siguiente consulta devuelve la información de espera de bloqueo de cada clave de fila con un conflicto de bloqueo, incluida la fracción del total de conflictos de bloqueo, durante el intervalo de tiempo de 1 minuto más reciente.

La función CAST() convierte el campo BYTES de row_range_start_key en una cadena.

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;
Salida 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

COLUMNA: users._exists1

LOCK_MODE: WriterShared

COLUMNA: users._exists1

1 _exists es un campo interno que se usa para comprobar si existe una fila determinada.

Conservación de datos

Como mínimo, Spanner conserva los datos de cada tabla durante los siguientes periodos:

  • SPANNER_SYS.LOCK_STATS_TOP_MINUTE y SPANNER_SYS.LOCK_STATS_TOTAL_MINUTE: intervalos que abarcan las 6 horas anteriores.

  • SPANNER_SYS.LOCK_STATS_TOP_10MINUTE y SPANNER_SYS.LOCK_STATS_TOTAL_10MINUTE: intervalos que abarcan los 4 días anteriores.

  • SPANNER_SYS.LOCK_STATS_TOP_HOUR y SPANNER_SYS.LOCK_STATS_TOTAL_HOUR: intervalos que abarcan los 30 días anteriores.

Solucionar problemas de conflictos de bloqueo en una base de datos mediante estadísticas de bloqueo

Puedes usar SQL o el panel de control Estadísticas de bloqueos para ver los conflictos de bloqueo de tu base de datos.

En los siguientes temas se muestra cómo investigar estos conflictos de bloqueo mediante código SQL.

Seleccionar un periodo para investigar

Examina las métricas de latencia de tu base de datos de Spanner y detectas un periodo en el que tu aplicación experimenta una latencia y un uso de CPU elevados. Por ejemplo, el problema empezó a producirse alrededor de las 22:50 del 12 de noviembre del 2020.

Determina si la latencia de confirmación de las transacciones ha aumentado junto con el tiempo de espera de los bloqueos durante el periodo seleccionado.

Las transacciones adquieren los bloqueos, por lo que, si los conflictos de bloqueo provocan tiempos de espera prolongados, deberíamos poder ver el aumento de la latencia de confirmación de la transacción junto con el aumento del tiempo de espera del bloqueo.

Una vez que hayamos seleccionado el periodo para iniciar la investigación, combinaremos las estadísticas de transacciones TXN_STATS_TOTAL_10MINUTE con las estadísticas de bloqueos LOCK_STATS_TOTAL_10MINUTE de ese periodo para determinar si el aumento de la latencia media de confirmación se debe al aumento del tiempo de espera de los bloqueos.

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 3741 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 drástico de avg_commit_latency_seconds y total_lock_wait_seconds durante el mismo periodo, del 12 de noviembre del 2020 a las 22:40:00 al 12 de noviembre del 2020 a las 22:50:00, y después disminuyeron. Es importante tener en cuenta que avg_commit_latency_seconds es el tiempo medio dedicado solo al paso de confirmación. Por otro lado, total_lock_wait_seconds es el tiempo de bloqueo agregado del periodo, por lo que el tiempo parece mucho mayor que el tiempo de confirmación de la transacción.

Ahora que hemos confirmado que el tiempo de espera del bloqueo está estrechamente relacionado con el aumento de la latencia de escritura, investigaremos en el siguiente paso qué filas y columnas provocan el tiempo de espera prolongado.

Descubrir qué claves de fila y columnas han tenido tiempos de espera de bloqueo largos durante el periodo seleccionado

Para saber qué claves de fila y columnas han experimentado tiempos de espera de bloqueo elevados durante el periodo que estamos investigando, consultamos la tabla LOCK_STAT_TOP_10MINUTE, que muestra las claves de fila y las columnas que más contribuyen a la espera de bloqueo.

La función CAST() de la siguiente consulta convierte el campo BYTES row_range_start_key en una cadena.

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 se ha producido en la Singers tabla con la clave SingerId=32. La Singers.SingerInfo es la columna en la que se produjo el conflicto de bloqueo entre ReaderShared y WriterShared.

Este es un tipo de conflicto habitual cuando una transacción intenta leer una celda determinada y la otra transacción intenta escribir en la misma celda. Ahora sabemos la celda de datos exacta por la que compiten las transacciones, por lo que, en el siguiente paso, identificaremos las transacciones que compiten por los bloqueos.

Buscar las transacciones que acceden a las columnas implicadas en el conflicto de bloqueo

Para identificar las transacciones que experimentan una latencia de confirmación significativa en un intervalo de tiempo específico debido a conflictos de bloqueo, debe consultar las siguientes columnas de la tabla SPANNER_SYS.TXN_STATS_TOTAL_10MINUTE:

  • fprint
  • read_columns
  • write_constructive_columns
  • avg_commit_latency_seconds

Debe filtrar las columnas bloqueadas identificadas en la tabla SPANNER_SYS.LOCK_STATS_TOP_10MINUTE:

  • Transacciones que leen cualquier columna que haya provocado un conflicto de bloqueo al intentar adquirir el bloqueo ReaderShared.

  • Transacciones que escriben en cualquier columna que haya provocado un conflicto de bloqueo al intentar 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 por la columna avg_commit_latency_seconds para que veas primero la transacción que tiene la latencia de confirmación más alta.

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 que tuvo conflictos de bloqueo durante el periodo. Una vez que haya identificado las transacciones que provocan los conflictos de bloqueo, podrá analizarlas mediante su huella digital, fprint, para identificar posibles problemas que hayan contribuido 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 tu aplicación ha activado la transacción. A continuación, puede ver el DML subyacente que no está filtrando por la clave principal, SingerId. Esto provocó un análisis completo de la tabla y bloqueó la tabla hasta que se confirmó la transacción.

Para resolver el conflicto de bloqueo, puedes hacer lo siguiente:

  1. Usa una transacción de solo lectura para identificar los valores de SingerId necesarios.
  2. Usa una transacción de lectura y escritura independiente para actualizar las filas de los valores SingerId necesarios.

Aplicar prácticas recomendadas para reducir la contención de bloqueos

En nuestro ejemplo, hemos podido usar las estadísticas de bloqueo y de transacciones para acotar el problema a una transacción que no usaba la clave principal de nuestra tabla al hacer actualizaciones. Se nos ocurrieron ideas para mejorar la transacción en función de si conocíamos las claves de las filas que queríamos actualizar de antemano o no.

Cuando analice posibles problemas en su solución o incluso cuando la diseñe, tenga en cuenta estas prácticas recomendadas para reducir el número de conflictos de bloqueo en su base de datos.

  • Evita las lecturas grandes en 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 de tabla completos en una transacción de lectura y escritura. Esto incluye escribir una instrucción DML condicional en la clave principal o asignar un intervalo de claves específico al usar la API Read.

  • Mantén el periodo 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 cambien después de leerlos hasta que confirmes el cambio correctamente. Para ello, la transacción requiere bloquear las celdas de datos durante la lectura y la confirmación. Por lo tanto, si puedes mantener el periodo de bloqueo corto, es menos probable que las transacciones tengan conflictos de bloqueo.

  • Prioriza las transacciones pequeñas sobre las grandes o considera la posibilidad de usar DML particionado para las transacciones DML de larga duración. Una transacción de larga duración adquiere un bloqueo durante mucho tiempo, por lo que es recomendable dividir una transacción que afecte a 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 datos en la transacción de lectura y escritura antes de confirmar el cambio. Por ejemplo, puedes leer 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 asegurar que los datos no cambien 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 son por celda de datos, cuando una transacción de lectura y escritura lee demasiadas columnas, adquiere un ReaderSharedbloqueo en esas celdas. Esto puede provocar conflictos de bloqueo cuando otras transacciones obtengan un bloqueo WriterShared en las escrituras de las columnas excesivas. Por ejemplo, puedes especificar un conjunto de columnas en lugar de * en la lectura.

  • Minimiza las llamadas a la API en una transacción de lectura y escritura. La latencia de las llamadas a la API puede provocar conflictos de bloqueo en Spanner, ya que las llamadas a la API están sujetas a retrasos de red y del lado del servicio. Te recomendamos que hagas 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 monitorizar la latencia de las llamadas a la API para minimizar el impacto en el periodo de adquisición del bloqueo.

  • Sigue las prácticas recomendadas para el diseño de esquemas.

Siguientes pasos