MySQL debe saber debe saber 12: transacción: garantizar la ejecución de las operaciones asociadas

La lectura se compila de "MySQL Must Know and Know" - Zhu Xiaofeng Para obtener más información, inicie sesión en la columna de compra en el sitio web oficial de Geek Time .

asuntos

La transacción es una función de MySQL, que puede realizar un conjunto de operaciones de datos (también llamadas operaciones DML, que es la abreviatura de Lenguaje de manipulación de datos en inglés, que incluye seleccionar, insertar, actualizar y eliminar), ya sea ejecutarlas todas o no ejecutarlas en absoluto. y no lo hará Debido a alguna situación anormal (como falla de hardware, falla de energía, interrupción de la red, etc.), solo se realiza una parte de la operación.

start transaction 或者 begin (开始事务)
一组 DML 语句
commit (提交事务)
rollback(事务回滚)
  • iniciar transacción y comenzar: indica el inicio de una transacción, y las operaciones DML después de notificar a MySQL son todas parte de la transacción actual
  • commit: Indica la confirmación de una transacción, la realización de todas las operaciones de la transacción actual y la realización de cambios de datos permanentes.
  • rollback: Indica que la operación de revertir la transacción actual cancela los cambios en los datos

Las transacciones tienen cuatro características: atomicidad, consistencia, durabilidad y aislamiento.

  • Atomicidad: las operaciones en la transacción se ejecutan todas o no se ejecutan en absoluto, como un todo, y no se pueden interrumpir en el medio
  • Consistencia: la integridad de los datos no será destruida debido a la ejecución de la transacción
  • Aislamiento: cuando se ejecutan múltiples transacciones al mismo tiempo, no interfieren entre sí; los diferentes niveles de aislamiento tienen diferentes grados de independencia entre sí.
  • Persistencia: La modificación de datos por transacciones tiene vigencia permanente y no será invalidada por falla del sistema

consistencia

preparación de datos:

Escena simple donde un cajero de un supermercado ayuda a los clientes a pagar, en el sistema la acción de liquidación es principalmente la generación de flujo de ventas y la reducción de inventario. Esto involucrará la tabla de flujo de ventas y la tabla de inventario, de la siguiente manera:

demo.mytrans

transido número de artículo cantidad

demo.inventory

número de artículo invcantidad
1 10
create table demo.mytrans 
(
transid int,
itemnumber int,
quantity int
);

create table demo.inventory
(
itemnumber int,
invquantity int
);
insert demo.inventory values (1, 10);

negocio:

Suponiendo que la tienda vende 5 productos cuyo número de producto es 1, esta acción en realidad incluye 2 operaciones de base de datos interrelacionadas:

  • Inserte un flujo de ventas de "Producto No. 1 vendido 5" en la tabla de flujo;
  • Disminuir el inventario del artículo 1 en la tabla de inventario en 5

Hay 2 operaciones DML aquí. Para evitar la situación de que una operación se ejecuta pero la otra no se ejecuta debido a eventos inesperados, póngalas en una transacción y use la atomicidad de las operaciones de datos en la transacción para garantizar la consistencia de los datos:

mysql> start transaction;
Query OK, 0 rows affected (3.06 sec)

mysql> insert into demo.mytrans values(1, 1, 5);
Query OK, 1 row affected (0.01 sec)

mysql> update demo.inventory set invquantity=invquantity-5 where itemnumber=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

resultado de búsqueda:

mysql> select * from demo.mytrans;
+---------+------------+----------+
| transid | itemnumber | quantity |
+---------+------------+----------+
|       1 |          1 |        5 |
+---------+------------+----------+

mysql> select * from demo.inventory;
+------------+-------------+
| itemnumber | invquantity |
+------------+-------------+
|          1 |           5 |
+------------+-------------+

Además: la transacción no ayudará automáticamente a solucionar los errores en la ejecución de la instrucción SQL . Si no soluciona los errores en un determinado paso de la operación de datos en la transacción y continúa enviando, los datos seguirán ser inconsistente


error en la transacción

Si falta un campo en la declaración para insertar un flujo de ventas y ocurre un error durante la ejecución, si no revierte el error, continúa ejecutando las siguientes operaciones y finalmente envía la transacción, el resultado será que no no hay flujo pero el inventario se reduce:

mysql> select * from demo.mytrans;
+---------+------------+----------+
| transid | itemnumber | quantity |
+---------+------------+----------+
|       1 |          1 |        5 |
+---------+------------+----------+

mysql> select * from demo.inventory;
+------------+-------------+
| itemnumber | invquantity |
+------------+-------------+
|          1 |           5 |
+------------+-------------+

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into demo.mytrans values (1,5);
ERROR 1136 (21S01): Column count does not match value count at row 1  -- 开启事务后,报错

mysql> update demo.inventory set invquantity=invquantity-5 where itemnumber=1;  -- 后面的语句仍然执行成功了
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)  -- 事务提交成功了

mysql> select * from demo.mytrans;
+---------+------------+----------+
| transid | itemnumber | quantity |
+---------+------------+----------+
|       1 |          1 |        5 |   -- 流水没有插入成功,还是原来的数据
+---------+------------+----------+

mysql> select * from demo.inventory;
+------------+-------------+
| itemnumber | invquantity |
+------------+-------------+
|          1 |           0 |   -- 库存消减成功了
+------------+-------------+

Este es el problema de los datos incompletos causados ​​por el uso incorrecto de las transacciones.

Para evitar este tipo de datos incompletos debido a errores en un determinado paso o en varios pasos de la transacción, es necesario utilizar el manejo de errores y el rollback en la transacción:

  • Si ocurre un error en una operación en la transacción, se debe utilizar la reversión a tiempo;
  • Confirmar solo si todas las operaciones en la transacción se pueden ejecutar normalmente

La clave es juzgar si hay un error en la operación.

row_count()Juzgue si una operación DML falla mediante el retorno de la función MySQL , -1 significa que la operación falló; de lo contrario, significa la cantidad de registros afectados.

mysql> insert into demo.mytrans values(1, 5);
ERROR 1136 (21S01): Column count does not match value count at row 1

mysql> select row_count();
+-------------+
| row_count() |
+-------------+
|          -1 |
+-------------+

Otro lugar donde las transacciones se utilizan con frecuencia son los procedimientos almacenados .

Dado que los procedimientos almacenados contienen muchas operaciones de datos interrelacionadas, las transacciones se utilizan mucho. Podemos determinar si la transacción se confirma o revierte al obtener el error de SQL en el procedimiento almacenado de MySQL:

mysql> select * from demo.inventory;   -- 测试前数据
+------------+-------------+
| itemnumber | invquantity |
+------------+-------------+
|          1 |          10 |
+------------+-------------+

mysql> select * from demo.mytrans;
Empty set (0.00 sec)
mysql> delimiter //                                -- 修改分隔符为 //
mysql> create procedure demo.test_rollback()       -- 创建存储过程
-> begin                                           -- 开始程序体
-> declare exit handler for sqlexception rollback; -- 定义SQL操作发生错误是自动回滚
-> start transaction;                              -- 开始事务
-> insert into demo.mytrans values (1,5);
-> update demo.inventory set invquantity = invquantity - 5;
-> commit;                                         -- 提交事务
-> end
-> //                                              -- 完成创建存储过程
Query OK, 0 rows affected (0.01 sec)
 
mysql> delimiter ;                                 -- 恢复分隔符为 ; 这里 delimiter 需要和 ; 之间有一个空格
mysql> call demo.test_rollback();                  -- 调用存储过程
Query OK, 0 rows affected (0.00 sec)

mysql> select * from demo.mytrans;    -- 销售流水没有插入
Empty set (0.00 sec)

mysql> select * from demo.inventory;   -- 库存也没有消减,说明事务回滚了
+------------+-------------+
| itemnumber | invquantity |
+------------+-------------+
|          1 |          10 |
+------------+-------------+

Primero, delimiter //cambie la marca final de la declaración de MySQL a //(la marca final de la declaración predeterminada es ;) a través de la declaración. El propósito de esto es decirle a MySQL que //la declaración termina hasta el , de lo contrario, MySQL pensará ;que la declaración ha terminado cuando encuentre el primer , y la ejecutará. De esta manera, se informará un error y, naturalmente, no hay forma de crear un procedimiento almacenado.

Una vez completada la creación, debe ingresarlo //para decirle a MySQL que el procedimiento almacenado se ha creado y aprobado DELIMITER ;, y luego cambiar el indicador de finalización de la declaración nuevamente ;.

En resumen, las operaciones asociadas importantes deben colocarse en transacciones para garantizar la atomicidad de las operaciones y revertir las operaciones fallidas . Solo de esta manera podemos realmente desempeñar el papel de las transacciones, garantizar que todas las operaciones asociadas tengan éxito o fracasen y, en última instancia, garantizar la coherencia de los datos.


Aprovecha bien el aislamiento

caso:

  • Zhang San abrió una transacción A cuando estaba en la tienda para la liquidación, incluidas 3 operaciones:
    • Lea la cantidad en la tarjeta como 100;
    • Actualizar el monto de la tarjeta a 0;
    • Insertar un flujo de ventas
  • El amante de Zhang San está comprando en línea y abre una transacción B, también para leer el monto de la tarjeta.

Si la operación de B de leer el monto de la tarjeta ocurre después de que A actualice el monto de la tarjeta y antes de insertar el flujo de ventas, entonces ¿cuál debe ser el monto leído por B? Si B lee 0 yuanes, y en este momento A puede retroceder debido a la falla de las operaciones posteriores, la cantidad volverá a los 100 originales. Por lo tanto, B puede leer un mensaje de error, lo que hace que falle una transacción exitosa.

En este momento, se utilizará otro mecanismo de MySQL: " lock ". MySQL puede bloquear los datos modificados y no confirmados en A, y mantener a B en un estado de espera hasta que A confirme, o retroceda en caso de falla, y luego libere el bloqueo, permitiendo que B lea los datos. De esta forma, se puede evitar la posibilidad de errores de lectura de B debido a la reversión de A.

Mediante el uso de bloqueos, se puede lograr el aislamiento mutuo entre transacciones. Las cerraduras se utilizan de diferentes maneras y tienen diferentes grados de aislamiento .

MySQL admite 4 niveles de aislamiento de transacciones.

  • lectura no confirmada: puede leer los datos modificados que no se han confirmado en la transacción
  • lectura confirmada: solo puede leer los datos modificados que se han confirmado en la transacción
  • Lectura repetible: indica que en una transacción, el valor leído para un dato siempre es coherente con el valor leído por primera vez y no se ve afectado por las operaciones de datos en otras transacciones. Esta es también la opción predeterminada para MySQL
  • serializable: indica que para cualquier transacción, una vez que se realiza una operación en ciertos datos, MySQL bloqueará los datos hasta el final de la transacción, prohibiendo que otras transacciones realicen cualquier operación en los datos

En escenarios comerciales reales, una vez que se completa el cálculo de la operación, el nivel de aislamiento debe restaurarse al estado predeterminado del sistema; de lo contrario, tendrá un impacto relativamente grande en la eficiencia de la operación diaria del sistema.

Por un lado, para algunas operaciones de modificación de datos centrales, puede ser necesario un mayor nivel de aislamiento, como la modificación que involucra dinero; por otro lado, se debe considerar el consumo de recursos para que la eficiencia general del sistema no se vea muy afectada. Por lo tanto, las transacciones deben usarse correctamente según los escenarios de aplicación específicos.


resumen

Una transacción puede garantizar que una serie de operaciones en una transacción se ejecuten todas sin ser interrumpidas, o que no se ejecuten en absoluto, esperando a ser ejecutadas nuevamente.

Las operaciones en las transacciones tienen las características de atomicidad, consistencia, permanencia y aislamiento. Pero esto no significa que una serie de operaciones de datos DML envueltas por transacciones deban tener éxito o fallar .

Es necesario juzgar si la operación es exitosa o no, y notificar a MySQL para completar la operación de confirmación o reversión de la transacción de acuerdo con diferentes situaciones, para garantizar finalmente que todas las operaciones en la transacción tengan éxito o fallen.

En MySQL, no todas las operaciones se pueden revertir.

Por ejemplo, crear una base de datos, crear una tabla de datos, eliminar una base de datos, eliminar una tabla de datos, etc. Estas operaciones no se pueden deshacer, así que tenga cuidado al operar, especialmente al eliminar una base de datos o una tabla de datos, es mejor hacer una copia de seguridad primero, para evitar el mal uso.

Supongo que te gusta

Origin blog.csdn.net/qq_31362767/article/details/123602930
Recomendado
Clasificación