MySQL must know must know 12: transaction - ensure the execution of associated operations

The reading is compiled from "MySQL Must Know and Know" - Zhu Xiaofeng . For details, please log in to the purchase column on the official website of Geek Time .

affairs

Transaction is a function of MySQL, which can make a set of data operations (also called DML operations, which is the abbreviation of Data Manipulation Language in English, including select, insert, update and delete), either execute all or not execute at all, and will not Due to some abnormal situation (such as hardware failure, power failure, network interruption, etc.), only a part of the operation is performed.

start transaction 或者 begin (开始事务)
一组 DML 语句
commit (提交事务)
rollback(事务回滚)
  • start transaction and begin: Indicates the start of a transaction, and the DML operations after notifying MySQL are all part of the current transaction
  • commit: Indicates committing a transaction, performing all operations of the current transaction, and making data changes permanent
  • rollback: Indicates that the operation of rolling back the current transaction cancels the changes to the data

Transactions have four characteristics: atomicity, consistency, durability, and isolation.

  • Atomicity: The operations in the transaction are either all executed or not executed at all, like a whole, and cannot be interrupted in the middle
  • Consistency: the integrity of the data will not be destroyed due to the execution of the transaction
  • Isolation: When multiple transactions are executed at the same time, they do not interfere with each other; different isolation levels have different degrees of independence from each other
  • Persistence: The modification of data by transactions is permanently effective and will not be invalidated due to system failure

consistency

data preparation:

A simple scene where a cashier in a supermarket helps customers check out. In the system, the settlement action is mainly the generation of sales flow and the reduction of inventory. This will involve the sales flow table and inventory table, as follows:

demo.mytrans

transid itemnumber quantity

demo.inventory

itemnumber invquantity
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);

business:

Assuming that the store sells 5 products whose product number is 1, this action actually includes 2 interrelated database operations:

  • Insert a sales flow of "Product No. 1 sold 5" into the flow table;
  • Decrease the inventory of item 1 in the inventory table by 5

There are 2 DML operations here. In order to avoid the situation that one operation is executed but the other is not executed due to unexpected events, put them into a transaction, and use the atomicity of data operations in the transaction to ensure data consistency:

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)

search result:

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

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

In addition: the transaction will not automatically help to deal with the errors in the execution of the SQL statement . If you do not deal with the errors in a certain step of the data operation in the transaction and continue to submit, the data will still be inconsistent.


error in transaction

If there is one missing field in the statement for inserting a sales flow, and an error occurs during execution, if you do not roll back the error, continue to execute the following operations, and finally submit the transaction, the result will be that there is no flow but the inventory is reduced :

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 |   -- 库存消减成功了
+------------+-------------+

This is the problem of incomplete data caused by incorrect use of transactions.

In order to avoid this kind of incomplete data due to errors in a certain step or several steps in the transaction, it is necessary to use error handling and rollback in the transaction:

  • If an error occurs in an operation in the transaction, rollback should be used in time;
  • Commit only if all operations in the transaction can be executed normally

The key is to judge whether there is an error in the operation.

row_count()Judge whether a DML operation fails through the return of the MySQL function , -1 means the operation failed, otherwise it means the number of affected records.

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 |
+-------------+

Another place where transactions are often used are stored procedures .

Since stored procedures contain many interrelated data operations, transactions are heavily used. We can determine whether the transaction is committed or rolled back by getting the SQL error in the MySQL stored procedure:

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 |
+------------+-------------+

First, delimiter //change the end mark of the MySQL statement to //(the end mark of the default statement is ;) through the statement. The purpose of this is to tell MySQL that //the statement ends until the , otherwise, MySQL will ;think that the statement has ended when it encounters the first , and execute it. In this way, an error will be reported, and naturally there is no way to create a stored procedure.

After the creation is completed, you need to enter it //to tell MySQL that the stored procedure has been created and passed DELIMITER ;, and then change the statement end flag back ;.

In short, important associated operations should be placed in transactions to ensure the atomicity of operations and roll back failed operations . Only in this way can we really play the role of transactions, ensure that all associated operations succeed or fail, and ultimately ensure data consistency.


Make good use of isolation

case:

  • Zhang San opened a transaction A when he was in the store for settlement, including 3 operations:
    • Read the amount in the card as 100;
    • Update the amount in the card to 0;
    • Insert a sales flow
  • Zhang San's lover is shopping online, and opens a transaction B, also to read the amount in the card

If B's ​​operation of reading the amount in the card occurs after A updates the amount in the card and before inserting the sales flow, then what should the amount read by B be? If B reads 0 yuan, and at this time A may roll back due to the failure of subsequent operations, the amount will return to the original 100. Therefore, B may read an error message, causing an otherwise successful transaction to fail.

At this time, another mechanism of MySQL will be used: " lock ". MySQL can lock the modified and uncommitted data in A, and keep B in a waiting state until A submits, or rolls back on failure, and then releases the lock, allowing B to read the data. In this way, the possibility of B reading errors due to A rollback can be prevented.

Through the use of locks, mutual isolation between transactions can be achieved. Locks are used in different ways and have different degrees of isolation .

MySQL supports 4 transaction isolation levels.

  • read uncommitted: You can read the changed data that has not been committed in the transaction
  • read committed: can only read the changed data that has been committed in the transaction
  • Repeatable read: Indicates that in a transaction, the value read for a piece of data is always consistent with the value read for the first time, and is not affected by data operations in other transactions. This is also the default option for MySQL
  • serializable: Indicates that for any transaction, once any operation is performed on a certain data, MySQL will lock the data until the end of the transaction, prohibiting other transactions from performing any operations on the data

In actual business scenarios, after the operation calculation is completed, the isolation level needs to be restored to the default state of the system, otherwise, it will have a relatively large impact on the daily system operation efficiency.

On the one hand, for some core data modification operations, a higher isolation level may be required, such as modification involving money; on the other hand, resource consumption must be considered so that the overall efficiency of the system cannot be greatly affected. Therefore, transactions must be used correctly according to specific application scenarios.


summary

A transaction can ensure that a series of operations in a transaction are all executed without being interrupted; or not executed at all, waiting to be executed again.

Operations in transactions have the characteristics of atomicity, consistency, permanence, and isolation. But this does not mean that a series of DML data operations wrapped by transactions must all succeed or fail .

It is necessary to judge whether the operation is successful or not, and notify MySQL to complete the transaction commit or rollback operation according to different situations, so as to finally ensure that all operations in the transaction succeed or fail.

In MySQL, not all operations can be rolled back.

For example, create a database, create a data table, delete a database, delete a data table, etc. These operations cannot be rolled back, so be careful when operating, especially when deleting a database or data table, it is best to make a backup first , to prevent misuse.

Guess you like

Origin blog.csdn.net/qq_31362767/article/details/123602930