MySQL学习笔记(二)—— 事务


本系列根据B站教学视频进行的知识点整理总结。

一、什么是事务(Transaction)

事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换为另一种状态。在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。事务需满足ACID原则才是一个正确的事务。

二、事务管理ACID的原则

1.原子性(Atomicity)

“要么都成功,要么都失败”

举例:
1.SQL执行:A给B转账,A当前余额1000元,B当前余额200元,A向B转账200元。
2. SQL执行:B收到A转账的钱,此时A余额为800元,B余额400元。

事务就是需要将1/2两条SQL语句放在同一个批次去执行,两条语句要不都执行成功,要不都执行失败。否则,若只执行第一条语句,未执行语句2则会出现:A对B进行转账,A的余额变成800,但B未接收到A的转账,B的余额还是200,则出错。

2.一致性(Consistency)

“某一事务操作前后的数据保持一致”

举例:
操作前:A + B = 1200
操作后:A + B = 1200

3.持久性(Durability)

“事务没有提交,恢复到原状;事务提交了,持久化到数据库”
举例:
操作前:A=1000 B=200
操作:A向B转账200元,B收到A转账的钱。
事务若没提交,服务器宕机或者断电,数据库重启后:A=1000 B=200
事务若已提交,服务器宕机或者断电,数据库重启后:A=800 B=400

4.隔离性(Isolation)

“事务之间相互独立,中间状态不可见”

举例:
操作1:A:1000 B:200 (A转账给B 200)
操作2:C:300 (C转账给B 100)

1)隔离(并发执行下)导致的问题

1> 脏读:一个事务读取了另一个事务未提交的数据
举例:
事务1:
提交前:A:1000 B:200 A转账给B 200
提交后:A:800 B:400
事务2:
提交前:C:300 B:200 C转账给B 100 (读取了事务1提交前B的数据)
提交后:C:200 B:300

2> 不可重复读:在一个事务内读取表中某一行数据,多次读取的结果不同。
第一次读取B:A:1000 B:200
第二次读取B:A:1000 B:500(其他事务又改变了B的值)

3> 虚读(幻读):一个事务内读取了另一个事务插入的数据,导致读取前后不一致。(第一次读C不存在,第二次读C就存在了)
读取前:A:1000 B:200
读取后:A:1000 B:200 C:300 (C为另一个事务插入的数据)

2)隔离级别

为解决脏读、不可重复读、幻读指定的标准。
1> read-uncommitted 已读未提交:最低级别,能够读取到没有被提交的数据,只能保证持久性。
2> read-committed 已读已提交: 语句级别的,可解决脏读。
3> repeatable-read 可重复读:事务级别。可解决脏读、不可重复读。
4> serializable 串行化:最高级别,事务与事务完全串行化执行,毫无并发可言,性能极低。可解决脏读、不可重复读、幻读。

3)隔离级别的实现(InnoDB)

(后续继续学习后补充代码实现)

· 锁机制

当一个事务执行的时候,阻止其他事务对数据进行操作。各个隔离级别主要体现在读取数据时加锁的时机和释放时机。
1> read-uncommitted 已读未提交:事务读取的时候,不加锁。
2> read-committed 已读已提交: 事务读取的时候加行级共享锁(读到加锁),一旦读完,立即释放锁(并不是事务的结束)。
3> repeatable-read 可重复读:事务读取的时候加行级共享锁,直到事务结束锁才释放。
4> serializable 串行化:事务读取的时候加表级共享锁,直到事务结束锁才释放。

· MVCC机制

生成一个数据快照,并用这个快照来提供一定级别的一致性的读取,也成为了多版本数据控制。
1>实际是 CAS版本控制 和 读写分离 的思想。
2>主要用于 read-committed 已读已提交 和 repeatable-read 可重复读。

三、事务的代码实现

1. TIPS

1)mysql默认开启事务自动提交

SET autocommit = 0 /*关闭自动提交*/
SET autocommit = 1 /*开启自动提交*/

2)可在一个事务操作过程中设置保存点

SAVEPOINT 保存点名 /*设置一个保存点*/
ROLLBACK TO 保存点名 /*回滚到该保存点*/
RELEASE SAVEPOINT 保存点名 /*删除一个保存点*/

2. 步骤

-- 1.关闭自动提交,手动处理事务
SET autocommit = 0 

-- 2.事务开启
START TRANSACTION

-- 3.对数据进行操作
INSERT
UPDATE
...
-- 4.操作成功后,提交操作后的数据结果
COMMIT
-- 或者操作失败后,回滚至原来的样子
ROLLBACK

-- 5.事务结束,开启事务自动提交
SET autocommit = 1

例:账户A 给账户B 转账

-- 1. 创建一个数据库
CREATE DATABASE bank CHARACTER SET utf8 COLLATE utf8_general_ci

-- 2. 对该数据库操作
USE bank

-- 3. 创建一个表
CREATE TABLE `account`(
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 4. 添加数据
INSERT INTO `account`(`name`,`money`)
VALUES('A',1000),('B',2000)

-- 5.实现一个转账事务
SET autocommit = 0
START TRANSACTION

UPDATE `account` SET money = money - 500 WHERE `name` = 'A'  -- A=500
UPDATE `account` SET money = money + 500 WHERE `name` = 'B'  -- B=2500

ROLLBACK  -- A=1000 B=2000
COMMIT -- A=500 B=2500

SET autocommit = 1
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值