MySQL学习(12)事务.md

发布时间 2023-11-07 15:47:56作者: 哪过晓得

前言

“古之欲正世调天下者,必先观国政,料事务,察民俗。“出自《管子·正世》,事务就是指要做的或所做的事情。

一件事情要么做了,要么没做,才符合原则。转账不存在转了一半,也不存在我转给你10元,你却到账5元。

ACID原则

原子性(Atomicity)

事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。在现实世界里,转账是一个不可分割的操作。如果在执行过程中发生了错误,就要恢复到执行之前的样子。

一致性(Consistency)

事务的执行不能破坏数据库数据的完整性和一致性,同时也要保证数据库中的数据符合现实世界的约束。一致性指数据满足所有数据库的条件,比如字段约束、外键约束、触发器等,事务从一致性开始,以一致性结束。更多的要求需要靠业务代码保证。

隔离性(Isolation)

事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务是透明的。

持久性(Durability)

对于提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

注:DBMS一般采用日志来保证事务的原子性、一致性和持久性。

事务的概念

在数据库管理系统中,事务是单个逻辑或工作单元,有时由多个操作组成,在数据库中以一致模式完成的逻辑处理称为事务。一个例子是从一个银行账户转账到另一个账户:完整的交易需要减去从一个账户转账的金额,然后将相同的金额添加到另一个账户。

事务其实是一个抽象的概念,MySQL把需要保证原子性、隔离性、一致性和持久性的一个或多个数据库操作称为事务。事务执行的过程中分为不同的阶段。

  • 活动的(active)

事务对应的数据库操作正在执行过程中。

  • 部分提交的(partially committed)

事务中的操作已经全部执行完,但未保存到磁盘。

  • 失败的(failed)

事务处于活动状态或部分提交的状态,遇到了程序错误或机器故障而无法继续执行,或者人为中止事务。

  • 中止的(aborted)

处于失败的状态的事务,撤销事务对当前数据库造成的影响,执行完回滚后的状态。

  • 提交的(committed)

处于部分提交的状态的事务完成了刷盘后,就是提交的状态。

事务的状态转换图

注意:只有当事务处于提交的或者中止的状态时,一个事务的生命周期才算结束。提交的事务对数据库所做的修改将永久生效;中止的事务对数据库做的修改都会被回滚到没执行该事务前的状态。

MySQL中如何使用事务

开启事务

使用下面这两种写法都可以显式的开启事务,然后在后续写入需要对数据进行操作的语句。

  • BEGIN

BEGIN;
UPDATE ......
DELETE ......

 

  • START TRANSACTION

    • READ ONLY:表示当前事务是一个只读事务

    • READ WRITE:表示当前事务是一个读写事务

    • WITH CONSISTENCY SNAPSHOT:启动一致性读

START TRANSACTION;
UPDATE ......
DELETE ......

 



START TRANSACTION READ ONLY;
SELECT .....

 

 

实例:

CREATE TABLE account (
  id INT NOT NULL AUTO_INCREMENT COMMENT '自增id',
  name VARCHAR(100) COMMENT '客户名称',
  balance INT COMMENT '余额',
  PRIMARY KEY (id)
); Engine=InnoDB CHARSET=utf8;
INSERT INTO account (name, balance) VALUES ('张三', 11);
INSERT INTO account (name, balance) VALUES ('李四', 2);
CREATE TABLE account (
  id INT NOT NULL AUTO_INCREMENT COMMENT '自增id',
  name VARCHAR(100) COMMENT '客户名称',
  balance INT COMMENT '余额',
  PRIMARY KEY (id),
  CHECK (balance >= 0)
); Engine=InnoDB CHARSET=utf8;
 

SELECT * FROM account;
BEGIN;
UPDATE account SET balance = balance - 1 WHERE id = 1;
UPDATE account SET balance = balance + 1 WHERE id = 2;
COMMIT;
SELECT * FROM account;

 

提交事务

当最后一条语句写完后,就可以提交这个事务了。

手动提交

使用COMMIT提交事务。

BEGIN;
UPDATE ......
DELETE ......
COMMIT;

 

自动提交

系统变量autocommit可以设置是否自动提交事务。它的默认值是ON,也就是默认情况下,如果不显示地开启事务,MySQL认为每一条语句都是一个独立的事务,这种事务自动开启,自动提交;若把autocommit设置为OFF,或显式开起事务,则必须手动提交或回滚事务,不会自动提交。

SHOW VARIABLES LIKE 'autocommit';

 

image-20231107121618773

隐式提交

当显式的开启事务后,会因为一些特殊的语句导致事务提交,这种情况叫做隐式提交。

  • DDL语言

使用CREATE、ALTER、DROP等语句操作数据库对象时,会隐式地自动提交前面语句的事务。

  • 隐式使用或修改mysql数据库中的表

使用ALTER USER、CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD等语句时,会隐式地自动提交前面语句的事务。

  • 事务控制或关于锁定的语句

当一个事务还没有提交或回滚,又使用BEGIN或START TRANSACTION开启一个新的事务,就会隐式地自动提交前面语句的事务。

使用LOCK TABLES、UNLOCK TABLES等语句也会隐式地自动提交前面语句的事务。

  • 加载数据的语句

使用LOAD DATA语句想数据库中批量导入数据时,会隐式地自动提交前面语句的事务。

  • 复制的语句

使用START SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO等语句时,会隐式地自动提交前面语句的事务。

  • 其他

ANALYZE TABLE、CACHE INDEX、CHECK TABLE、FLUSH、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE、RESET等。

中止事务

手动中止

在已开启的事务中,使用ROLLBACK语句让数据库状态恢复到事务执行之前的样子。

BEGIN;
UPDATE ......;
ROLLBACK;

 

注意:ROLLBACK是手动调用来回滚事务。

错误中止

执行过程中遇到程序错误而无法继续执行,会回滚失败的语句,在某些情况下可能会回滚整个事务。

保存点

使用ROLLBACK不仅可以回滚整个事务,还可以对事务设置保存点,让ROLLBACK回滚到指定的保存点。

定义保存点的语法:

SAVEPOINT sp_name;

 

想回滚到保存点这样即可:

ROLLBACK TO sp_name;

 

删除保存点:

RELEASE SAVEPOINT sp_name;