Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Transcripción de la charla de Bruce Momjian de 2020 "Desbloqueo del administrador de bloqueo de Postgres".

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

(Nota: todas las consultas SQL de las diapositivas se pueden obtener desde este enlace: http://momjian.us/main/writings/pgsql/locking.sql)

¡Hola! Es fantástico estar nuevamente aquí en Rusia. Lamento no haber podido venir el año pasado, pero este año Iván y yo tenemos grandes planes. Espero estar aquí mucho más a menudo. Me encanta venir a Rusia. Visitaré Tyumen, Tver. Estoy muy contento de poder visitar estas ciudades.

Mi nombre es Bruce Momjian. Trabajo en EnterpriseDB y llevo más de 23 años trabajando con Postgres. Vivo en Filadelfia, EE. UU. Viajo unos 90 días al año. Y asisto a unas 40 conferencias. Mi Sitio web, que contiene las diapositivas que ahora les mostraré. Por tanto, después de la conferencia podréis descargarlos desde mi web personal. También contiene alrededor de 30 presentaciones. También hay vídeos y una gran cantidad de entradas de blog, más de 500. Este es un recurso bastante informativo. Y si te interesa este material, entonces te invito a utilizarlo.

Solía ​​ser profesor, profesor antes de empezar a trabajar con Postgres. Y estoy muy contento de poder ahora decirles lo que estoy a punto de decirles. Esta es una de mis presentaciones más interesantes. Y esta presentación contiene 110 diapositivas. Empezaremos a hablar de cosas sencillas y al final el informe se irá poniendo cada vez más complejo y se volverá bastante complejo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esta es una conversación bastante desagradable. El bloqueo no es el tema más popular. Queremos que esto desaparezca en alguna parte. Es como ir al dentista.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

  1. El bloqueo es un problema para muchas personas que trabajan en bases de datos y tienen múltiples procesos ejecutándose al mismo tiempo. Necesitan bloqueo. Es decir, hoy les daré conocimientos básicos sobre el bloqueo.
  2. Identificadores de transacciones. Esta es una parte bastante aburrida de la presentación, pero es necesario entenderla.
  3. A continuación hablaremos de los tipos de bloqueo. Esta es una parte bastante mecánica.
  4. Y a continuación daremos algunos ejemplos de bloqueo. Y será bastante difícil de entender.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Hablemos de bloqueo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Nuestra terminología es bastante compleja. ¿Cuántos de ustedes saben de dónde viene este pasaje? Dos personas. Esto es de un juego llamado Colossal Cave Adventure. Creo que era un juego de computadora basado en texto de los años 80. Allí había que entrar en una cueva, en un laberinto, y el texto cambiaba, pero el contenido era aproximadamente el mismo cada vez. Así recuerdo este juego.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y aquí vemos el nombre de las cerraduras que nos llegaron de Oracle. Nosotros los usamos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Aquí vemos términos que me confunden. Por ejemplo, COMPARTE ACTUALIZACIÓN ECXLUSIVO. Siguiente COMPARTE RAW ECXLUSIVO. Para ser honesto, estos nombres no están muy claros. Intentaremos considerarlos con más detalle. Algunos contienen la palabra “compartir”, que significa separar. Algunos contienen la palabra “exclusivo”. Algunos contienen ambas palabras. Me gustaría comenzar con cómo funcionan estas cerraduras.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y la palabra “acceso” también es muy importante. Y las palabras "fila" son una cadena. Es decir, distribución de acceso, distribución de filas.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Otro tema que debe entenderse en Postgres, que desafortunadamente no podré cubrir en mi charla, es MVCC. Tengo una presentación separada sobre este tema en mi sitio web. Y si crees que esta presentación es difícil, MVCC es probablemente la más difícil. Y si os interesa podéis verlo en la web. Puedes ver el vídeo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Otra cosa que debemos entender son los ID de las transacciones. Muchas transacciones no pueden funcionar sin identificadores únicos. Y aquí tenemos una explicación de qué es una transacción. Postgres tiene dos sistemas de numeración de transacciones. Sé que esta no es una solución muy bonita.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

También tenga en cuenta que las diapositivas serán bastante difíciles de entender, por lo que debe prestar atención a lo que está resaltado en rojo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

http://momjian.us/main/writings/pgsql/locking.sql

Vamos a ver. El número de transacción está resaltado en rojo. La función SELECT pg_back se muestra aquí. Devuelve mi transacción y el ID de la transacción.

Una cosa más, si le gusta esta presentación y desea ejecutarla en su base de datos, puede ir a este enlace en rosa y descargar el SQL para esta presentación. Y simplemente puede ejecutarlo en su PSQL y toda la presentación estará en su pantalla inmediatamente. No contendrá flores, pero al menos podremos verlo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

En este caso vemos el ID de la transacción. Este es el número que le asignamos. Y hay otro tipo de ID de transacción en Postgres, que se llama ID de transacción virtual.

Y debemos entender esto. Esto es muy importante, de lo contrario no podremos entender el bloqueo en Postgres.

Un ID de transacción virtual es un ID de transacción que no contiene valores persistentes. Por ejemplo, si ejecuto un comando SELECT, lo más probable es que no cambie la base de datos, no bloquearé nada. Entonces, cuando ejecutamos un SELECT simple, no le damos a esa transacción una ID persistente. Allí solo le damos una identificación virtual.

Y esto mejora el rendimiento de Postgres, mejora las capacidades de limpieza, por lo que la ID de la transacción virtual consta de dos números. El primer número antes de la barra diagonal es el ID del backend. Y a la derecha vemos solo un mostrador.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Por lo tanto, si ejecuto una solicitud, dice que el ID del backend es 2.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si ejecuto una serie de transacciones de este tipo, vemos que el contador aumenta cada vez que ejecuto una consulta. Por ejemplo, cuando ejecuto la consulta 2/10, 2/11, 2/12, etc.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Tenga en cuenta que aquí hay dos columnas. A la izquierda vemos el ID de transacción virtual: 2/12. Y a la derecha tenemos una identificación de transacción permanente. Y este campo está vacío. Y esta transacción no modifica la base de datos. Entonces no le doy una identificación de transacción permanente.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Tan pronto como ejecuto el comando de análisis ((ANALYZE)), la misma consulta me proporciona una ID de transacción permanente. Mira cómo esto ha cambiado para nosotros. Antes no tenía esta identificación, pero ahora la tengo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Así que aquí hay otra solicitud, otra transacción. El número de transacción virtual es 2/13. Y si solicito un ID de transacción persistente, cuando ejecute la consulta, lo obtendré.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Entonces, una vez más. Tenemos un ID de transacción virtual y un ID de transacción persistente. Simplemente comprenda este punto para comprender el comportamiento de Postgres.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Pasamos a la tercera sección. Aquí simplemente repasaremos los diferentes tipos de bloqueos en Postgres. No es muy interesante. La última sección será mucho más interesante. Pero debemos considerar las cosas básicas, porque de lo contrario no entenderemos lo que sucederá después.

Revisaremos esta sección, veremos cada tipo de cerradura. Y les mostraré ejemplos de cómo se instalan, cómo funcionan, les mostraré algunas consultas que pueden usar para ver cómo funciona el bloqueo en Postgres.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Para crear una consulta y ver qué sucede en Postgres, debemos emitir la consulta en la vista del sistema. En este caso, pg_lock está resaltado en rojo. Pg_lock es una tabla del sistema que nos dice qué bloqueos están actualmente en uso en Postgres.

Sin embargo, me resulta muy difícil mostrarles pg_lock por sí solo porque es bastante complejo. Entonces creé una vista que muestra pg_locks. Y también me ayuda a comprender mejor. Es decir, excluye mis bloqueos, mi propia sesión, etc. Es solo SQL estándar y le permite mostrarle mejor lo que está pasando.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Otro problema es que esta vista es muy amplia, por lo que tengo que crear una segunda: lockview2.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian Y me muestra más columnas de la tabla. Y otro que me muestra el resto de columnas. Esto es bastante complejo, así que intenté presentarlo de la forma más sencilla posible.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Entonces creamos una tabla llamada Lockdemo. Y creamos una línea allí. Esta es nuestra tabla de muestra. Y crearemos secciones solo para mostrarle ejemplos de candados.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Entonces, una fila, una columna. El primer tipo de bloqueo se llama ACCESS SHARE. Este es el bloqueo menos restrictivo. Esto significa que prácticamente no entra en conflicto con otras cerraduras.

Y si queremos definir explícitamente un bloqueo, ejecutamos el comando "bloquear tabla". Y obviamente se bloqueará, es decir, en modo ACCESS SHARE lanzamos la tabla de bloqueo. Y si ejecuto PSQL en segundo plano, comienzo la segunda sesión desde la primera de esta manera. Es decir, ¿qué haré aquí? Voy a otra sesión y le digo "muéstrame la vista de bloqueo para esta solicitud". Y aquí tengo AccessShareLock en esta tabla. Esto es exactamente lo que solicité. Y dice que el bloque está asignado. Muy simple.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Además, si miramos la segunda columna, entonces no hay nada allí. Están vacíos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si ejecuto el comando "SELECT", entonces esta es la forma implícita (explícita) de solicitar AccessShareLock. Entonces libero mi tabla y ejecuto la consulta y la consulta devuelve varias filas. Y en una de las líneas vemos AccessShareLock. Por lo tanto, SELECT llama a AccessShareLock en la mesa. Y no entra en conflicto con prácticamente nada porque es un bloqueo de bajo nivel.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué pasa si ejecuto un SELECT y tengo tres tablas diferentes? Anteriormente solo ejecutaba una tabla, ahora estoy ejecutando tres: pg_class, pg_namespace y pg_attribute.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y ahora, cuando miro la consulta, veo 9 AccessShareLocks en tres tablas. ¿Por qué? Tres tablas están resaltadas en azul: pg_attribute, pg_class, pg_namespace. Pero también puede ver que todos los índices definidos a través de estas tablas también tienen AccessShareLock.

Y este es un candado que prácticamente no entra en conflicto con los demás. Y lo único que hace es simplemente impedirnos resetear la tabla mientras la seleccionamos. Que tiene sentido. Es decir, si seleccionamos una tabla, en ese momento desaparece, entonces esto está mal, entonces AccessShare es un bloqueo de bajo nivel que nos dice "no dejes caer esta tabla mientras estoy trabajando". Básicamente, eso es todo lo que hace.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

COMPARTIR FILA: este candado es un poco diferente.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Tomemos un ejemplo. Método SELECT ROW SHARE para bloquear cada fila individualmente. De esta forma nadie podrá borrarlos ni cambiarlos mientras los estamos viendo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce MomjianEntonces, ¿qué hace SHARE LOCK? Vemos que el ID de transacción es 681 para SELECT. Y esto es interesante. ¿Que pasó aquí? La primera vez que vemos el número es en el campo “Bloquear”. Tomamos el ID de la transacción y dice que la está bloqueando en modo exclusivo. Todo lo que hace es decir que tengo una fila que técnicamente está bloqueada en algún lugar de la tabla. Pero no dice dónde exactamente. Veremos esto con más detalle un poco más adelante.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Aquí decimos que la cerradura la usamos nosotros.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Entonces, un bloqueo exclusivo dice explícitamente que es exclusivo. Y también si eliminas una fila en esta tabla, esto es lo que sucederá, como puedes ver.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

SHARE EXCLUSIVE es un candado más largo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Este es el comando del analizador (ANALYZE) que se utilizará.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

BLOQUEO COMPARTIDO: puede bloquear explícitamente el modo compartir.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

También puede crear un índice único. Y ahí puedes ver SHARE LOCK, que forma parte de ellos. Y bloquea la mesa y le pone un BLOQUEO COMPARTIDO.

De forma predeterminada, SHARE LOCK en una tabla significa que otras personas pueden leer la tabla, pero nadie puede modificarla. Y esto es exactamente lo que sucede cuando creas un índice único.

Si creo un índice concurrente único, tendré un tipo diferente de bloqueo porque, como recordará, el uso de índices concurrentes reduce el requisito de bloqueo. Y si uso un bloqueo normal, un índice normal, evitaré escribir en el índice de la tabla mientras se crea. Si uso un índice simultáneamente, entonces necesito usar un tipo diferente de bloqueo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

COMPARTIR FILA EXCLUSIVA: nuevamente se puede configurar explícitamente (explícitamente).

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

O podemos crear una regla, es decir, tomar un caso específico en el que se utilizará.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

El bloqueo EXCLUSIVO significa que nadie más puede cambiar la mesa.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Aquí vemos diferentes tipos de cerraduras.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

ACCESS EXCLUSIVE, por ejemplo, es un comando de bloqueo. Por ejemplo, si lo haces CLUSTER table, entonces esto significará que nadie podrá escribir allí. Y bloquea no sólo la tabla en sí, sino también los índices.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esta es la segunda página del bloqueo de ACCESO EXCLUSIVO, donde vemos exactamente lo que bloquea en la tabla. Bloquea filas de tablas individuales, lo cual es bastante interesante.

Esa es toda la información básica que quería dar. Hablamos de bloqueos, de ID de transacciones, hablamos de ID de transacciones virtuales, de ID de transacciones permanentes.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y ahora veremos algunos ejemplos de bloqueo. Esta es la parte más interesante. Veremos casos muy interesantes. Y mi objetivo en esta presentación es brindarles una mejor comprensión de lo que realmente hace Postgres cuando intenta bloquear ciertas cosas. Creo que es muy bueno bloqueando partes.

Veamos algunos ejemplos específicos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Comenzaremos con tablas y una fila de una tabla. Cuando inserto algo, aparece ExclusiveLock, Transaction ID y ExclusiveLock en la tabla.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué pasa si inserto dos filas más? Y ahora nuestra mesa tiene tres filas. E inserté una fila y obtuve esto como resultado. Y si inserto dos filas más, ¿qué tiene de extraño? Hay algo extraño aquí porque agregué tres filas a esta tabla, pero todavía tengo dos filas en la tabla de bloqueo. Y este es esencialmente el comportamiento fundamental de Postgres.

Mucha gente piensa que si en una base de datos bloquea 100 filas, necesitará crear 100 entradas de bloqueo. Si bloqueo 1 filas a la vez, necesitaré 000 consultas de este tipo. Y si necesito un millón o mil millones para bloquear. Pero si hacemos esto, no funcionará muy bien. Si ha utilizado un sistema que crea entradas de bloqueo para cada fila individual, podrá ver que esto es complicado. Porque necesita definir inmediatamente una tabla de bloqueo que pueda desbordarse, pero Postgres no hace eso.

Y lo realmente importante de esta diapositiva es que demuestra claramente que hay otro sistema que se ejecuta dentro de MVCC y que bloquea filas individuales. Entonces, cuando bloqueas miles de millones de filas, Postgres no crea mil millones de comandos de bloqueo separados. Y esto tiene un muy buen efecto en la productividad.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué tal una actualización? Estoy actualizando la fila ahora y puedes ver que ha realizado dos operaciones diferentes a la vez. Bloqueó la tabla al mismo tiempo, pero también bloqueó el índice. Y necesitaba bloquear el índice porque existen restricciones únicas en esta tabla. Y queremos asegurarnos de que nadie lo cambie, por eso lo bloqueamos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué pasa si quiero actualizar dos filas? Y vemos que él se comporta de la misma manera. Hacemos el doble de actualizaciones, pero exactamente la misma cantidad de líneas de bloqueo.

Si se pregunta cómo hace esto Postgres, deberá escuchar mis charlas sobre MVCC para saber cómo Postgres marca internamente estas líneas que cambian. Y Postgres tiene una manera de hacer esto, pero no lo hace en el nivel de bloqueo de la tabla, lo hace en un nivel inferior y más eficiente.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué pasa si quiero eliminar algo? Si elimino, por ejemplo, una fila y todavía tengo mis dos entradas de bloqueo, e incluso si quiero eliminarlas todas, todavía están allí.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y, por ejemplo, quiero insertar 1 líneas y luego eliminar o agregar 000 líneas, luego esas líneas individuales que agrego o cambio no se registran aquí. Están escritos en un nivel inferior dentro de la propia serie. Y durante el discurso de MVCC hablé de esto en detalle. Pero es muy importante cuando analizas los bloqueos asegurarte de que estás bloqueando en el nivel de la tabla y que no estás viendo cómo se registran las filas individuales aquí.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué pasa con el bloqueo explícito?

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Si hago clic en actualizar, tengo dos filas bloqueadas. Y si los selecciono todos y hago clic en "actualizar en todas partes", todavía tengo dos registros de bloqueo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

No creamos registros separados para cada fila individual. Como entonces la productividad cae, es posible que haya demasiada. Y podemos encontrarnos en una situación desagradable.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y lo mismo, si lo compartimos, podemos hacerlo todo 30 veces.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Restauramos nuestra tabla, eliminamos todo y luego insertamos una fila nuevamente.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Otro comportamiento que ves en Postgres que es muy conocido y deseado es que puedes hacer una actualización o una selección. Y puedes hacer esto al mismo tiempo. Y select no bloquea la actualización y lo mismo en sentido contrario. Le decimos al lector que no bloquee al escritor, y el escritor no bloqueó al lector.

Te mostraré un ejemplo de esto. Tomaré una decisión ahora. Luego haremos el INSERT. Y luego podrá ver: 694. Puede ver el ID de la transacción que realizó esta inserción. Y así es como funciona.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si miro mi ID de backend ahora, ahora es 695.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y puedo ver 695 que aparece en mi tabla.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si actualizo aquí de esta manera, obtengo un caso diferente. En este caso, 695 es un bloqueo exclusivo y la actualización tiene el mismo comportamiento, pero no hay conflicto entre ellos, lo cual es bastante inusual.

Y puedes ver que en la parte superior está ShareLock y en la parte inferior está ExclusiveLock. Y ambas transacciones funcionaron.

Y necesitas escuchar mi charla en MVCC para entender cómo sucede esto. Pero esta es una ilustración de que puedes hacerlo al mismo tiempo, es decir, hacer un SELECCIONAR y un ACTUALIZAR al mismo tiempo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Reiniciemos y hagamos una operación más.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Si intenta ejecutar dos actualizaciones simultáneamente en la misma fila, se bloqueará. Y recuerden, dije que el lector no bloquea al escritor, y el escritor no bloquea al lector, sino que un escritor bloquea a otro escritor. Es decir, no podemos tener dos personas actualizando la misma fila al mismo tiempo. Tienes que esperar hasta que uno de ellos termine.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y para ilustrar esto, miraré la tabla Lockdemo. Y veremos una fila. Por transacción 698.

Hemos actualizado esto a 2. 699 es la primera actualización. Y fue exitoso o está en una transacción pendiente y está esperando que la confirmemos o la cancelemos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Pero mire algo más: 2/51 es nuestra primera transacción, nuestra primera sesión. 3/112 es la segunda solicitud que vino desde arriba que cambió ese valor a 3. Y si se dan cuenta, la de arriba se bloqueó sola, que es 699. Pero 3/112 no concedió el bloqueo. La columna Lock_mode dice lo que está esperando. Espera 699. Y si miras dónde está 699, es más alto. ¿Y qué hizo la primera sesión? Creó un bloqueo exclusivo en su propio ID de transacción. Así es como lo hace Postgres. Bloquea su propia ID de transacción. Y si desea esperar a que alguien confirme o cancele, debe esperar mientras haya una transacción pendiente. Y es por eso que podemos ver una línea extraña.

Miremos de nuevo. A la izquierda vemos nuestro ID de procesamiento. En la segunda columna vemos nuestro ID de transacción virtual y en la tercera vemos lock_type. ¿Qué quiere decir esto? Básicamente, lo que dice es que está bloqueando el ID de la transacción. Pero observe que todas las filas en la parte inferior dicen relación. Y entonces tienes dos tipos de cerraduras sobre la mesa. Hay un bloqueo de relación. Y luego está el bloqueo del ID de transacción, donde usted mismo bloquea, que es exactamente lo que sucede en la primera fila o en la parte inferior, donde está el ID de transacción, donde esperamos a que 699 finalice su operación.

Veré qué pasa aquí. Y aquí suceden dos cosas simultáneamente. Estás viendo un bloqueo de ID de transacción en la primera fila que se bloquea solo. Y se bloquea para hacer esperar a la gente.

Si nos fijamos en la sexta línea, es la misma entrada que la primera. Y por tanto la transacción 6 está bloqueada. 699 también es autoblocante. Y luego en la fila inferior verás que estamos esperando que 700 finalice su operación.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y en lock_type, tupla ves números.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Puedes ver que es 0/10. Y este es el número de página y también el desplazamiento de esta fila en particular.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y ves que se convierte en 0/11 cuando actualizamos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Pero en realidad es 0/10, porque hay que esperar para esta operación. Tenemos la oportunidad de ver que esta es la serie que estoy esperando confirmar.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Una vez que lo hemos confirmado y presionado confirmar, y cuando finaliza la actualización, esto es lo que obtenemos nuevamente. La transacción 700 es el único bloqueo, no espera a nadie más porque fue confirmada. Simplemente espera a que se complete la transacción. Una vez que se acaba el 699, ya no esperamos nada. Y ahora la transacción 700 dice que todo está bien, que tiene todos los bloqueos que necesita en todas las tablas permitidas.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y para complicar aún más todo esto, creamos otra vista, que esta vez nos proporcionará una jerarquía. No espero que entiendas esta petición. Pero esto nos dará una visión más clara de lo que está pasando.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esta es una vista recursiva que también tiene otra sección. Y luego vuelve a unir todo. Usemos esto.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Qué pasa si hacemos tres actualizaciones simultáneas y decimos que la fila ahora es tres? Y cambiaremos 3 por 4.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y aquí vemos 4. Y el ID de transacción 702.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y luego cambiaré 4 por 5. Y 5 por 6, y 6 por 7. Y alinearé a varias personas que estarán esperando que finalice esta transacción.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y todo se aclara. ¿Cuál es la primera fila? Este es 702. Este es el ID de transacción que originalmente estableció este valor. ¿Qué está escrito en mi columna Concedido? tengo marcas f. Estas son mis actualizaciones que (5, 6, 7) no se pueden aprobar porque estamos esperando que finalice la transacción ID 702. Ahí tenemos el bloqueo de ID de transacción. Y esto da como resultado 5 bloqueos de identificación transaccional.

Y si miras el 704, el 705, ahí todavía no se ha escrito nada, porque todavía no saben lo que está pasando. Simplemente escriben que no tienen idea de lo que está pasando. Y simplemente se irán a dormir porque están esperando que alguien termine y los despierte cuando haya una oportunidad de cambiar de fila.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esto es lo que parece. Está claro que todos están esperando la línea 12.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esto es lo que vimos aquí. Aquí está 0/12.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Entonces, una vez que se aprueba la primera transacción, puedes ver aquí cómo funciona la jerarquía. Y ahora todo queda claro. Todos quedan limpios. Y en realidad todavía están esperando.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esto es lo que está pasando. 702 confirmaciones. Y ahora 703 obtiene este bloqueo de fila, y luego 704 comienza a esperar a que 703 se comprometa. Y el 705 también está esperando esto. Y cuando todo esto termina, se limpian. Y me gustaría señalar que todo el mundo está haciendo cola. Y esto es muy similar a una situación en un atasco cuando todos esperan el primer automóvil. El primer coche se detiene y todos forman una larga fila. Luego se mueve, luego el siguiente automóvil puede avanzar y obtener su bloque, etc.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si esto no te parece lo suficientemente complicado, ahora te hablaremos de los puntos muertos. No sé quién de ustedes los ha encontrado. Este es un problema bastante común en los sistemas de bases de datos. Pero los puntos muertos ocurren cuando una sesión está esperando que otra sesión haga algo. Y en este momento otra sesión está esperando que la primera sesión haga algo.

Y, por ejemplo, si Iván dice: “Dame algo”, y yo le digo: “No, sólo te lo daré si me das algo más”. Y él dice: “No, no te lo daré si tú no me lo das”. Y terminamos en una situación de punto muerto. Estoy seguro de que Iván no hará esto, pero entiendes el significado de que tenemos dos personas que quieren conseguir algo y no están dispuestas a regalarlo hasta que la otra persona les dé lo que quieren. Y no hay solución.

Y esencialmente, su base de datos necesita detectar esto. Y luego debes eliminar o cerrar una de las sesiones, porque de lo contrario permanecerán allí para siempre. Y lo vemos en las bases de datos, lo vemos en los sistemas operativos. Y en todos los lugares donde tenemos procesos paralelos esto puede suceder.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y ahora instalaremos dos puntos muertos. Pondremos 50 y 80. En la primera fila, actualizaré de 50 a 50. Obtendré la transacción número 710.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y luego cambiaré 80 por 81 y 50 por 51.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y así es como se verá. Entonces el 710 tiene una fila bloqueada y el 711 está esperando confirmación. Vimos esto cuando actualizamos. 710 es el dueño de nuestra serie. Y el 711 espera a que el 710 complete la transacción.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

E incluso dice en qué fila se producen los puntos muertos. Y aquí es donde empieza a ponerse raro.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Ahora estamos actualizando 80 a 80.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y aquí es donde empiezan los estancamientos. El 710 está esperando una respuesta del 711 y el 711 está esperando el 710. Y esto no terminará bien. Y no hay salida a esto. Y esperarán una respuesta mutua.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y empezará a retrasar todo. Y no queremos eso.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y Postgres tiene formas de darse cuenta cuando esto sucede. Y cuando esto sucede, aparece este error. Y de esto queda claro que tal o cual proceso está esperando un BLOQUEO COMPARTIDO de otro proceso, es decir, que está bloqueado por el proceso 711. Y ese proceso estaba esperando que se otorgara un BLOQUEO COMPARTIDO en tal o cual ID de transacción y fue bloqueado por tal o cual proceso. Por lo tanto, aquí existe una situación de punto muerto.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

¿Hay tres puntos muertos? ¿Es posible? Sí.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Ingresamos estos números en una tabla. Cambiamos 40 por 40, hacemos bloqueo.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Cambiamos 60 por 61, 80 por 81.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y luego cambiamos 80 y ¡boom!

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y el 714 ahora está esperando al 715. El 716 está esperando al 715. Y no se puede hacer nada al respecto.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Aquí ya no hay dos personas, aquí ya hay tres personas. Yo quiero algo de ti, éste quiere algo de una tercera persona y la tercera persona quiere algo de mí. Y terminamos en una espera de tres vías porque todos estamos esperando que la otra persona complete lo que tiene que hacer.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y Postgres sabe en qué fila sucede esto. Entonces le dará el siguiente mensaje, que muestra que tiene un problema en el que tres entradas se bloquean entre sí. Y aquí no hay restricciones. Este puede ser el caso en el que 20 entradas se bloquean entre sí.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

El siguiente problema es serializable.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Si es un bloqueo serializable especial.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y volvemos al 719. Su salida es bastante normal.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y puede hacer clic para realizar la transacción desde serializable.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y te das cuenta de que ahora tienes un tipo diferente de bloqueo SA: significa serializable.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y entonces tenemos un nuevo tipo de bloqueo llamado SARieadLock, que es un bloqueo en serie y permite ingresar números de serie.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y también puedes insertar índices únicos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

En esta tabla tenemos índices únicos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Entonces, si pongo el número 2 aquí, tengo un 2. Pero en la parte superior, pongo otro 2. Y pueden ver que 721 tiene un bloqueo exclusivo. Pero ahora 722 está esperando a que 721 complete su operación porque no puede insertar 2 hasta que sepa qué pasará con 721.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si hacemos subtransacciones.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Aquí tenemos 723.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y si guardamos el punto y luego lo actualizamos, obtenemos una nueva ID de transacción. Este es otro patrón de comportamiento que debes tener en cuenta. Si devolvemos esto, el ID de la transacción desaparecerá. 724 se va. Pero ahora tenemos 725.

Entonces, ¿qué estoy tratando de hacer aquí? Estoy tratando de mostrarle ejemplos de bloqueos inusuales que puede encontrar: ya sean bloqueos serializables o SAVEPOINT, estos son diferentes tipos de bloqueos que aparecerán en la tabla de bloqueos.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esta es la creación de bloqueos explícitos (explícitos), que tienen pg_advisory_lock.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y verá que el tipo de bloqueo aparece como de aviso. Y aquí dice “aviso” en rojo. Y puedes bloquear simultáneamente así con pg_advisory_unlock.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y para concluir, me gustaría mostrarles una cosa más alucinante. Crearé otra vista. Pero uniré la tabla pg_locks con la tabla pg_stat_activity. ¿Y por qué quiero hacer esto? Porque esto me permitirá mirar todas las sesiones actuales y ver exactamente qué tipo de bloqueos están esperando. Y esto es bastante interesante cuando juntamos la tabla de bloqueos y la tabla de consultas.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y aquí creamos pg_stat_view.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y actualizamos la fila por uno. Y aquí vemos 724. Y luego actualizamos nuestra fila a tres. ¿Y qué ves aquí ahora? Estas son solicitudes, es decir, verá la lista completa de solicitudes que se enumeran en la columna de la izquierda. Y luego, en el lado derecho, puedes ver los bloqueos y lo que crean. Y puede ser más claro para usted, de modo que no tenga que volver a cada sesión cada vez y ver si necesita unirse o no. Lo hacen por nosotros.

Otra característica que es muy útil es pg_blocking_pids. Probablemente nunca hayas oído hablar de ella. ¿Qué está haciendo? Nos permite decirle a esta sesión 11740 qué ID de proceso específicos está esperando. Y puedes ver que 11740 está esperando a 724. Y 724 está en la cima. Y 11306 es su ID de proceso. Básicamente, esta función pasa por la tabla de bloqueo. Y sé que es un poco complicado, pero logras entenderlo. Básicamente, esta función recorre esta tabla de bloqueos e intenta encontrar dónde se le dan a este ID de proceso los bloqueos que está esperando. Y también intenta averiguar qué ID de proceso tiene el proceso que está esperando el bloqueo. Entonces puedes ejecutar esta función. pg_blocking_pids.

Y esto puede resultar muy útil. Solo agregamos esto en la versión 9.6, por lo que esta característica tiene solo 5 años, pero es muy, muy útil. Y lo mismo se aplica a la segunda solicitud. Muestra exactamente lo que necesitamos ver.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Esto es de lo que quería hablarte. Y como esperaba, usamos todo nuestro tiempo porque había tantas diapositivas. Y las diapositivas están disponibles para descargar. Me gustaría agradecerles por estar aquí. Estoy seguro de que disfrutarás el resto de la conferencia, ¡muchas gracias!

Preguntas:

Por ejemplo, si intento actualizar filas y la segunda sesión intenta eliminar toda la tabla. Según tengo entendido, debería haber algo así como un bloqueo de intención. ¿Existe tal cosa en Postgres?

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Volvamos al principio. Quizás recuerde que cuando hace algo, por ejemplo cuando hace un SELECT, emitimos un AccessShareLock. Y esto evita que la mesa se caiga. Entonces, si, por ejemplo, desea actualizar una fila en una tabla o eliminar una fila, entonces alguien no puede eliminar toda la tabla al mismo tiempo porque está manteniendo este AccessShareLock sobre toda la tabla y sobre la fila. Y una vez que hayas terminado, pueden eliminarlo. Pero mientras cambies algo directamente allí, no podrán hacerlo.

Hagámoslo de nuevo. Pasemos al ejemplo de eliminación. Y ves cómo hay un candado exclusivo en la fila encima de toda la tabla.

Esto parecerá exclusivo de bloqueo, ¿verdad?

Sí, lo parece. Entiendo de qué estás hablando. Estás diciendo que si hago un SELECT entonces tengo un ShareExclusive y luego lo hago Row Exclusive, ¿eso se convierte en un problema? Pero, sorprendentemente, esto no supone ningún problema. Esto parece aumentar el grado de bloqueo, pero esencialmente tengo un bloqueo que impide la eliminación. Y ahora, cuando hago este bloqueo más poderoso, todavía impide la eliminación. Entonces no es como si estuviera subiendo. Es decir, también evitó que sucediera cuando estaba en un nivel inferior, por lo que cuando subo su nivel todavía evita que se elimine la tabla.

Entiendo de qué estás hablando. Aquí no hay ningún caso de escalada de bloqueo, en el que se intenta renunciar a un bloqueo para introducir uno más fuerte. Aquí simplemente aumenta esta prevención en todos los ámbitos, por lo que no causa ningún conflicto. Pero es una buena pregunta. ¡Muchas gracias por preguntar esto!

¿Qué debemos hacer para evitar una situación de punto muerto cuando tenemos muchas sesiones y una gran cantidad de usuarios?

Postgres detecta automáticamente situaciones de punto muerto. Y eliminará automáticamente una de las sesiones. La única forma de evitar el bloqueo total es bloquear a las personas en el mismo orden. Entonces, cuando miras tu aplicación, a menudo el motivo de los interbloqueos... Imaginemos que quiero bloquear dos cosas diferentes. Una aplicación bloquea la tabla 1, otra aplicación bloquea la 2 y luego la tabla 1. Y la forma más sencilla de evitar interbloqueos es mirar su aplicación e intentar asegurarse de que el bloqueo se produzca en el mismo orden en todas las aplicaciones. Y esto suele eliminar el 80% de los problemas, porque todo tipo de personas escriben estas aplicaciones. Y si los bloquea en el mismo orden, no encontrará una situación de punto muerto.

¡Muchas gracias por tu actuación! Usted habló de vacío lleno y, si entendí correctamente, vacío lleno distorsiona el orden de los registros en el almacenamiento separado, por lo que mantienen los registros actuales sin cambios. ¿Por qué el vacío lleno tiene acceso de bloqueo exclusivo y por qué entra en conflicto con las operaciones de escritura?

Buena pregunta. La razón es que el vacío se lleva la mesa llena. Y básicamente estamos creando una nueva versión de la tabla. Y la mesa será nueva. Resulta que esta será una versión completamente nueva de la mesa. Y el problema es que cuando hacemos esto, no queremos que la gente lo lea porque necesitamos que vean la nueva tabla. Y esto se conecta con la pregunta anterior. Si pudiéramos leer al mismo tiempo, no podríamos moverlo y dirigir a las personas a una nueva mesa. Tendríamos que esperar a que todos terminen de leer esta tabla, por lo que se trata esencialmente de una situación exclusiva de bloqueo.
Simplemente decimos que bloqueamos desde el principio porque sabemos que al final necesitaremos un bloqueo exclusivo para poder mover a todos a la nueva copia. Entonces potencialmente podemos resolver esto. Y lo hacemos así con indexación simultánea. Pero esto es mucho más difícil de hacer. Y esto se relaciona mucho con su pregunta anterior sobre la exclusiva de bloqueo.

¿Es posible agregar un tiempo de espera de bloqueo a Postgres? En Oracle, puedo, por ejemplo, escribir "seleccionar para actualizar" y esperar 50 segundos antes de actualizar. Fue bueno para la aplicación. Pero en Postgres, necesito hacerlo de inmediato y no esperar en absoluto, o esperar hasta algún tiempo.

Sí, puedes elegir un tiempo de espera en tus cerraduras, en tus cerraduras. También puede emitir un comando de no camino, que... si no puede obtener el bloqueo inmediatamente. Por lo tanto, ya sea un tiempo de espera de bloqueo o algo más que le permita hacer esto. Esto no se hace a nivel sintáctico. Esto se hace como una variable en el servidor. A veces esto no se puede utilizar.

¿Puedes abrir la diapositiva 75?

Sí.

Desbloqueo del Administrador de bloqueo de Postgres. Bruce Momjian

Y mi pregunta es la siguiente. ¿Por qué ambos procesos de actualización esperan 703?

Y esta es una gran pregunta. Por cierto, no entiendo por qué Postgres hace esto. Pero cuando se creó 703, esperaba 702. Y cuando aparecen 704 y 705, parece que no saben lo que esperan porque todavía no hay nada allí. Y Postgres lo hace de esta manera: cuando no puedes conseguir un bloqueo, escribe "¿Cuál es el punto de procesarte?", porque ya estás esperando a alguien. Así que lo dejaremos en el aire y no lo actualizará en absoluto. ¿Pero qué pasó aquí? Tan pronto como 702 completó el proceso y 703 recibió su bloqueo, el sistema regresó. Y dijo que ahora tenemos dos personas esperando. Y luego actualicémoslos juntos. Y indiquemos que ambos están esperando.

No sé por qué Postgres hace esto. Pero hay un problema llamado f…. Me parece que éste no es un término en ruso. Aquí es cuando todos esperan por un castillo, incluso si hay 20 autoridades esperando por el castillo. Y de repente todos se despiertan al mismo tiempo. Y todos empiezan a intentar reaccionar. Pero el sistema hace que todos estén esperando el 703. Porque todos están esperando, e inmediatamente los alinearemos a todos. Y si aparece alguna otra solicitud nueva que se generó después de esta, por ejemplo, 707, entonces habrá vacío nuevamente.

Y me parece que esto se hace para que podamos decir que en esta etapa el 702 está esperando al 703, y todos los que vengan después no tendrán ninguna entrada en este campo. Pero en cuanto se va el primer camarero, todos los que estaban esperando en ese momento antes de la actualización reciben el mismo token. Y entonces creo que esto se hace para que podamos procesar en orden para que estén ordenados correctamente.

Siempre vi esto como un fenómeno bastante extraño. Porque aquí, por ejemplo, no los enumeramos en absoluto. Pero me parece que cada vez que damos una cerradura nueva, miramos a todos los que están en proceso de espera. Luego los alineamos todos. Y luego, cualquier persona nueva que llegue sólo entrará en la cola cuando la siguiente persona haya terminado de ser procesada. Muy buena pregunta. ¡Muchas gracias por tu pregunta!

Me parece que es mucho más lógico cuando 705 espera 704.

Pero el problema aquí es el siguiente. Técnicamente, puedes despertar uno u otro. Y así despertaremos a uno o al otro. ¿Pero qué sucede en el sistema? Puedes ver cómo 703 en la parte superior ha bloqueado su propia ID de transacción. Así es como funciona Postgres. Y 703 está bloqueado por su propio ID de transacción, por lo que si alguien quiere esperar, esperará a 703. Y, en esencia, 703 se completa. Y sólo después de su finalización se despierta uno de los procesos. Y no sabemos cuál será exactamente este proceso. Luego procesamos todo gradualmente. Pero no está claro qué proceso se despierta primero, porque podría ser cualquiera de estos procesos. Básicamente, teníamos un programador que decía que ahora podemos activar cualquiera de estos procesos. Simplemente elegimos uno al azar. Así que es necesario tener en cuenta a ambos porque podemos despertar a cualquiera de ellos.

Y el problema es que tenemos CP-infinito. Y por tanto, es bastante probable que podamos despertar el último. Y si, por ejemplo, despertamos al último, esperaremos al que acaba de recibir el bloque, por lo que no determinamos quién exactamente se despertará primero. Simplemente creamos tal situación y el sistema los despertará en un orden aleatorio.

Hay artículos sobre cerraduras de Egor Rogov. Mira, también son interesantes y útiles. El tema, por supuesto, es terriblemente complejo. ¡Muchas gracias Bruce!

Fuente: habr.com

Añadir un comentario