📜  MySQL事务

📅  最后修改于: 2020-11-19 00:52:40             🧑  作者: Mango

MySQL事务

MySQL中的事务是一组连续的语句,查询或操作,例如选择,插入,更新或删除,以作为可以提交或回滚的单个工作单元执行。如果事务对数据库进行了多次修改,则会发生两件事:

  • 提交事务后,所有修改都将成功。
  • 或者,当事务回滚时,所有修改都将被撤消。

换句话说,如果不完成集合中的每个可用操作,交易就不会成功。这意味着如果任何语句失败,则事务操作将无法产生结果。

MySQL中的事务从第一个可执行的SQL语句开始,并在找到提交或显式或隐式回滚时结束。它显式使用COMMIT或ROLLBACK语句,并且在使用DDL语句时隐式使用。

让我们通过以下解释了解交易的概念。

通过考虑银行数据库,我们可以了解MySQL中事务的概念。假设银行客户希望将钱从一个帐户转移到另一个帐户。我们可以通过使用将分为以下步骤的SQL语句来实现此目的:

  • 首先,需要检查第一个帐户中所请求金额的可用性。
  • 接下来,如果有可用金额,请从第一个帐户中扣除。然后,更新第一个帐户。
  • 最后,将金额存入第二个帐户。然后更新第二个帐户以完成交易。
  • 如果以上任何过程失败,则事务将回滚到其先前状态。

交易性质

该事务主要包含四个属性,称为ACID属性。现在,我们将详细讨论ACID属性。 ACID属性代表:

  • 原子性
  • 一致性
  • 隔离
  • 耐用性

原子性:此属性确保必须成功执行事务单元内的所有语句或操作。否则,如果任何操作失败,则整个事务将中止,并且它将回滚到其先前状态。它包括以下功能:

  • COMMIT语句。
  • ROLLBACK语句。
  • 自动提交设置。
  • 来自INFORMATION_SCHEMA表的操作数据。

一致性:此属性确保仅在成功提交事务时,数据库才会更改状态。它还负责保护数据免于崩溃。它包括以下功能:

  • InnoDB双写缓冲区。
  • InnoDB崩溃恢复。

隔离:此属性保证事务处理单元中的每个操作独立运行。它还可以确保语句彼此透明。它包括以下功能:

  • SET ISOLATION LEVEL语句。
  • 自动提交设置。
  • InnoDB锁定的底层细节。

持久性:此属性保证即使系统崩溃或失败,已提交事务的结果也将永久保留。它包括以下功能:

  • 在存储设备中写入缓冲区。
  • 电池后备存储设备中的缓存。
  • 配置选项innodb_file_per_table。
  • 配置选项innodb_flush_log_at_trx_commit。
  • 配置选项sync_binlog。

MySQL交易声明

MySQL通过以下语句控制事务:

  • MySQL提供了START TRANSACTION语句来开始事务。它还提供“ BEGIN”和“ BEGIN WORK”作为“开始交易”的别名。
  • 我们将使用COMMIT语句来提交当前事务。它允许数据库永久进行更改。
  • 我们将使用ROLLBACK语句回滚当前事务。它允许数据库取消所有更改并进入其先前状态。
  • 我们将使用SET自动提交语句为当前交易禁用/启用自动提交模式。默认情况下,COMMIT语句自动执行。因此,如果我们不想自动提交更改,请使用以下语句:
SET autocommit = 0;
OR,
SET autocommit = OFF:

同样,使用以下语句启用自动提交模式:

SET autocommit = 1;
OR,
SET autocommit = ON:

MySQL事务示例

假设我们有两个名为“员工”和“订单”的表,其中包含以下数据:

表:员工

表:订单

提交示例

如果要使用事务,则需要将SQL语句分成逻辑部分。之后,我们可以定义是应该提交数据还是回滚数据。

以下步骤说明了如何创建事务:

  • 使用START TRANSACTION语句开始事务。
  • 然后,在员工中选择最大收入。
  • 将新记录添加到员工表。
  • 将新记录添加到订单表中。
  • 使用COMMIT语句完成事务。

以下是执行上述操作的命令:

-- 1. Start a new transaction

START TRANSACTION;

-- 2. Get the highest income

SELECT @income:= MAX(income) FROM employees;

-- 3. Insert a new record into the employee table

INSERT INTO employees(emp_id, emp_name, emp_age, city, income) 
VALUES (111, 'Alexander', 45, 'California', 70000);

-- 4. Insert a new record into the order table

INSERT INTO Orders(order_id, prod_name, order_num, order_date) 
VALUES (6, 'Printer', 5654, '2020-01-10');

-- 5. Commit changes    
COMMIT;

下图更清楚地说明了这一点:

回滚示例

我们可以借助下图了解回滚事务。首先,打开MySQL命令提示符,然后使用密码登录数据库服务器。接下来,我们必须选择一个数据库。

假设我们的数据库包含“ Orders”表。现在,以下是执行回滚操作的脚本:

-- 1. Start a new transaction
START TRANSACTION;

-- 2. Delete data from the order table
DELETE FROM Orders;

执行完上面的语句后,我们将获得如下输出,该输出显示表Orders已成功删除的所有记录。

现在,我们需要打开一个单独的MySQL数据库服务器会话,并执行以下语句来验证Orders表中的数据:

SELECT * FROM Orders;

它将给出如下输出。

尽管我们在第一个会话中进行了更改,但是我们仍然可以看到表中的记录可用。这是因为在我们没有在第一个会话中执行COMMIT或ROLLBACK语句之前,更改不是永久的。

因此,如果我们想使更改永久生效,请使用COMMIT语句。否则,请执行ROLLBACK语句以回滚第一个会话中的更改。

-- 3. Rollback changes    
ROLLBACK;

-- 4. Verify the records in the first session
SELECT * FROM Orders;

成功执行后,它将产生以下结果,我们可以看到更改已回滚。

使用MySQL Transaction不能回滚的语句。

MySQL Transaction不能回滚所有语句。例如,这些语句包括DDL(数据定义语言)命令,例如CREATE,ALTER或DROP数据库,以及CREATE,UPDATE或DROP表或存储的例程。我们必须确保在设计交易时不包括这些声明。

保存点,回滚到保存点,释放保存点

SAVEPOINT语句使用事务内的标识符名称创建一个特殊标记。它允许回滚保存点之后执行的所有语句。使事务恢复到保存点之前的先前状态。如果我们在当前事务中使用相同的名称设置了多个保存点,则新保存点负责回滚。

ROLLBACK TO SAVEPOINT语句允许我们将所有事务回滚到已建立的给定保存点,而不会中止该事务。

RELEASE SAVEPOINT语句从当前事务中销毁命名的保存点,而不会撤消在建立保存点之后执行的查询的影响。这些语句之后,不会发生任何回滚命令。如果该事务中不存在该保存点,则会产生错误。

以下是MySQL Transaction中上述语句的语法:

SAVEPOINT savepoint_name
ROLLBACK TO [SAVEPOINT] savepoint_name
RELEASE SAVEPOINT savepoint_name

让我们通过示例了解如何使用这些语句。在下面的示例中,我们将使用SAVEPOINT和ROLLBACK TO SAVEPOINT语句,这些语句说明保存点如何确定可以回滚当前事务的哪些记录。

START TRANSACTION;

SELECT * FROM Orders;

INSERT INTO Orders(order_id, prod_name, order_num, order_date) 
VALUES (6, 'Printer', 5654, '2020-01-10');

SAVEPOINT my_savepoint;

INSERT INTO Orders(order_id, prod_name, order_num, order_date) 
VALUES (7, 'Ink', 5894, '2020-03-10');

ROLLBACK TO SAVEPOINT my_savepoint;

INSERT INTO Orders(order_id, prod_name, order_num, order_date) 
VALUES (8, 'Speaker', 6065, '2020-02-18');

COMMIT;

在上面,

  • 我们必须首先开始交易,然后在“订单”表中显示可用的记录。
  • 接下来,我们在表中插入了一条记录,然后创建一个保存点标记。
  • 再次,我们在表中插入了一条记录,然后使用ROLLBACK TO SAVEPOINT语句删除在保存点已建立的位置的更改。
  • 同样,我们在表中插入了一条记录。
  • 最后,执行COMMIT语句以永久进行更改。

以下输出按顺序说明了上述步骤,有助于您轻松理解。

现在,我们将使用SELECT语句来验证上述操作。在输出中,我们可以看到成功添加了order_id = 6和order_id = 8,但是未将order_id = 7插入表中。建立保存点后,它将回滚输入的值:

现在,我们再来看一个示例RELEASE SAVEPOINT,该示例建立my_savepoint,然后删除一个保存点。

START TRANSACTION;

INSERT INTO Orders(order_id, prod_name, order_num, order_date) 
VALUES (7, 'Ink', 5894, '2020-03-10');

SAVEPOINT my_savepoint;

UPDATE Orders SET prod_name='Scanner' WHERE order_id=8;

RELEASE SAVEPOINT my_savepoint;

COMMIT;

在输出中,我们可以看到事务中的所有语句都已成功执行。在这里,INSERT和UPDATE语句都在COMMIT修改表。