MySQL事务-学习笔记

MySQL事务

事务的意义

案例:银行转账过程

A向B转账500,A原来有1000,B有500。

分析:

SQL处理过程:

  • A 减少 500
  • B 增加 500

以上两点必须同时生效,才算合理。

核心:要么都成功,要么都失败

事务(Transaction):一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)

事务管理(ACID)

原子性(Atomicity)

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

以上述例子为例:

  • 转账成功:A 转出500,B转入500是同时发生的。
  • 转账失败:A 转出500失败,B不会转入500。
  • 转账要么都成功,要么都失败,不能只发生一个动作,比如A少了500,但B没加。

一致性(Consistency)

事务前后数据的完整性必须保持一致。

  • 无论怎么转总价值 1500,不会少。

持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

  • 事务没有提交,则恢复到原状
  • 事务如果提交,则不可逆

隔离性(Isolation)

事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

  • A给B转账,C给B转账。两个是独立的,不会相互影响。

常见问题

脏读

指一个事务读取了另一个事务未提交的数据。

举例:

A :1000 B:500 C:1000

首先A 转账给B 500,记为事务1,此时A:500 B:1000,但事务没结束,结果还未提交。

这时C 也转账给B 500,该事务中B的初始值是500,C是1000,转账后 B:1000 ,C:500。

事务1提交结果,A:500,B:1000。

事务2提交结果,B:1000,C:500。

最后结果:A:500 B:1000 C:500,B 少了500!

错误原因是事务2读取的B的余额不准确。

不可重复读

在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)

比如报表功能,包含查询、生成报表,查询的时候,A :1000 B:500。在生成报表前,提交A完成转账500给B的事务,最终生成的报表中,A:500,B:1000

虚读(幻读)

和上面类似,是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
(一般是行影响,多了一行。)

执行事务

MySQL是默认开启事务自动提交的,需要关闭。语句如下:

SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启(默认的)

手动处理事务:

  • 关闭事务自动提交 SET autocommit = 0
  • 开启事务(标记一个事务的开始,之后的语句都在同一个事务内) Start transaction
  • 写SQL语句……
  • 执行操作
    • 提交(成功,持久化到数据库) commit
    • 回滚(失败,回到原来的样子) rollback
  • 事务结束
  • 打开事务自动提交
  • 其他(了解即可)
    • 事务语句较多时,可以设置保存点 savepoint
    • 回滚到保存点 rollback to savepoint
    • 释放保存点 release savepoint

案例:实现一个转账事务,A向B转账500

-- 创建数据库 Bank
CREATE DATABASE `Bank` CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 创建表
CREATE TABLE `account`(
   `id` INT(4) AUTO_INCREMENT NOT NULL,
   `name` VARCHAR(20) NOT NULL,
   `money` DECIMAL(9,2) NOT NULL,
   PRIMARY KEY(`id`)
)ENGINE INNODB DEFAULT CHARSET=utf8;
-- 插入A和B的账户数据
INSERT INTO `account`(`name`,`money`) VALUES ('A','1000.00'),('B','500.00');
-- 转账事务处理
-- 关闭事务自动提交
SET autocommit=0;
-- 开启事务
START TRANSACTION;
-- 写SQL语句
-- A - 500
UPDATE `account` SET money=money-500 WHERE `name`='A';
-- B + 500
UPDATE `account` SET money= money+500 WHERE `name`='B';
-- 提交事务
COMMIT;
-- 重新打开事务自动提交
SET autocommit=1;

以上为事务相关的基础内容学习记录及案例练习。

posted @ 2021-02-07 17:59  大川NV  阅读(55)  评论(0)    收藏  举报