MySQL事务的示例分析
编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天golang学习网就整理分享《MySQL事务的示例分析》,文章讲解的知识点主要包括,如果你对数据库方面的知识点感兴趣,就不要错过golang学习网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。
ACID 特性
事务处理是一种对必须整批执行的 MySQL 操作的管理机制,在事务过程中,除非整批操作全部正确执行,否则中间的任何一个操作出错,都会回滚 (Rollback)
到最初的安全状态以确保不会对系统数据造成错误的改动。
之前的文章中我们提到过,MySQL 5.5 之后,默认的存储引擎从 MyISAM 替换成了 InnoDB,这其中的一个重要原因就是因为 InnoDB 支持事务,我们用 SHOW ENGINES
来看一下 MySQL 中对各种存储引擎的描述。
事务最重要的四个特性通常被称为 ACID
特性A - Atomicity 原子性
: 一个事务是一个不可分割的最小单位,事务中的所有操作要么全部成功,要么全部失败,没有中间状态。原子性主要是通过事务日志中的回滚日志(undo log)
来实现的,当事务对数据库进行修改时,InnoDB 会根据操作生成相反操作的 undo log,比如说对 insert 操作,会生成 delete 记录,如果事务执行失败或者调用了 rollback,就会根据 undo log 的内容恢复到执行之前的状态。
C - Consistency 一致性
: 事务执行之前和执行之后数据都是合法的一致性状态,即使发生了异常,也不会因为异常引而破坏数据库的完整性约束,比如唯一性约束等。
I - Isolation 隔离性
: 每个事务是彼此独立的,不会受到其他事务的执行影响,事务在提交之前对其他事务不可见。隔离性通过事务的隔离级别来定义,并用锁机制来保证写操作的隔离性,用 MVCC 来保证读操作的隔离性,将在下文详细介绍。
D - Durability 持久性
: 事务提交之后对数据的修改是持久性的,即使数据库宕机也不会丢失,通过事务日志中的重做日志(redo log)
来保证。事务修改之前,会先把变更信息预写到 redo log 中,如果数据库宕机,恢复后会读取 redo log 中的记录来恢复数据。
事务控制语法
MySQL 事务控制有几个重要节点,分别是事务的开启,提交,回滚和保存点。
开启事务代表事务开始执行,语句为 START TRANSACTION
或者 BEGIN
,提交事务代表将事务中的所有更新都写到磁盘的物理数据库,事务正常执行结束,语句为 COMMIT
,如果发生异常需要回滚,语句为 ROLLBACK
。要注意的是,一旦事务已经提交,就不能回滚了,因此,在代码执行过程中捕获到异常的时候需要直接执行 rollback 而不是 commit。
比如 A 向 B 转账 100 元的事务:
// 正常执行,提交 BEGIN; # 开启事务 UPDATE account_balance SET balance = balance - 100.00 WHERE account_name = 'A'; UPDATE account_balance SET balance = balance + 100.00 WHERE account_name = 'B'; COMMIT; # 提交事务 // 发生异常,回滚 BEGIN; # 开启事务 UPDATE account_balance SET balance = balance - 100.00 WHERE account_name = 'A'; UPDATE account_balance SET balance = balance + 100.00 WHERE account_name = 'B'; ROLLBACK; # 事务回滚
在复杂场景中,有时我们不需要全盘回滚整个操作,而是分批执行,回滚到某个节点就好了,相当于是在一个大事务下嵌套了若干个子事务,在 MySQL 中可以使用保留点 SAVEPOINT
来实现。
BEGIN; insert into user_tbl (id) values (1) ; insert into user_tbl (id) values (2) ; ROLLBACK; # 1,2 都没有写入 BEGIN; insert into user_tbl (id) values (1) ; SAVEPOINT s1; insert into user_tbl (id) values (2) ; ROLLBACK TO s1; # 回滚到保留点 s1, 因此 1 成功写入,2 被回滚, 最终结果为 1 RELEASE SAVEPOINT s1; # 释放保留点
顺便提一下,事务有隐式事务(自动提交)和显示事务(必须手动提交)两种,MySQL 默认为隐式事务,会进行自动提交,通过 autocommit
参数来控制。
# 查看变量 SHOW VARIABLES LIKE 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ # 开启自动提交(默认) SET autocommit = 1; # 关闭自动提交 SET autocommit = 0;
在自动提交状态下,如果没有显示的开启事务,那每一条语句都是一个事务,系统会自动对每一条 sql 执行 commit 操作。使用 BEGIN 或 START TRANSACTION 开启一个事务之后,自动提交将保持禁用状态,直到使用 COMMIT 或 ROLLBACK 结束事务之后,自动提交模式会恢复到之前的状态。
关于事务还有另一个参数 completion_type
,默认取值为 0 (NO_CHAIN)
# 查看变量 SHOW VARIABLES LIKE 'completion_type'; +-----------------+----------+ | Variable_name | Value | +-----------------+----------+ | completion_type | NO_CHAIN | +-----------------+----------+
completion_type = 0: 默认值,执行 commit 后不会自动开启新的事务。
completion_type = 1: 执行 commit 时,相当于执行 COMMIT AND CHAIN,自动开启一个相同隔离级别的事务。
completion_type = 2: 执行 commit 时,相当于执行 COMMIT AND RELEASE,提交事务后自动断开服务器连接。
事务并发异常
在实际产线环境下,可能会存在大规模并发请求的情况,如果没有妥善的设置事务的隔离级别,就可能导致一些异常情况的出现,最常见的几种异常为脏读(Dirty Read)
、幻读(Phantom Read)
和不可重复读(Unrepeatable Read)
。
脏读
脏读指一个事务访问到了另一个事务未提交的数据,如下过程:
假设 a 的值为 1,事务 2 把 a 改为 2,此时事务还未提交
在这个时候,事务 1 读取 a,读得 a 的值为 2,事务 1 读取完成
结果事务 2 回滚了对 a 的修改(或者是未 commit),于是 a 的值变回 1
这就导致事实上 a 的值为 1,但是事务 1 取得的结果为 2,所以事务 1 读到了脏数据,发生脏读
不可重复读
不可重复读指一个事务多次读取同一数据的过程中,数据值 内容 发生了改变,导致没有办法读到相同的值,描述的是针对同一条数据 update/delete 的现象,如下过程:
事务 1 读取 a,此时 a = 1
此时事务 2 将 a 修改为 2,并成功提交,改动生效
事务 1 又一次读取 a,此时 a = 2
事务 1 在同一个事务里面两次读取同一个值,数据值内容却发生了改变,发生不可重复读
幻读
幻读指一个事务多次读取同一数据的过程中,全局数据(如数据行数)发生了改变,仿佛产生了幻觉,描述的是针对全表 insert/delete 的现象,如下过程:
事务 1 第一次读取数量,得到 10 条数据
此时事务 2 插入了一条数据并成功提交,改动生效,数据变成 11 条
事务 1 再次读取数量,得到 11 条数据,对事务 1 而言莫名其妙的多了一条,好像产生幻觉了一样,发生幻读
或者是另一种场景,比如对于有唯一性约束的字段(如 id),发生如下过程:
事务 1 要插入 id = 5 的记录,先查询数据库,发现不存在 id = 5 的数据,可以正常插入。
这时候事务 2 插入了一条数据 id = 5。
事务 1 插入 id = 5 时,发现报错唯一性冲突,对事务 1 来讲就好像见了鬼了,我刚刚明明检查过没有,怎么这时候又有了。
事务隔离级别
串行化的事务处理方式当然是最安全的,但是串行无法满足数据库高并发访问的需求,作为妥协,有时不得不降低数据库的隔离标准来换取事务的并发能力,通过在可控的范围内牺牲正确性来换取效率的提升,这种权衡通过事务的隔离级别来实现。
数据库有 4 种事务隔离级别,由低到高依次为 读未提交 Read Uncommitted
、读已提交 Read Committed
、可重复读 Repeatable Read
、串行化 Serializable
。
读未提交 Read Uncommitted
允许读取未提交的内容,这种级别下的查询不会加锁,因此脏读、不可重复读、幻读都有可能发生。读已提交 Read Committed
只允许读取已提交的内容,这种级别下的查询不会发生脏读,因为脏数据属于未提交的数据,所以不会被读取,但是依然有可能发生不可重复读和幻读。可重复读 Repeatable Read (MySQL 的默认隔离级别)
使用行级锁来保证一个事务在相同查询条件下两次查询得到的数据结果一致,可以避免脏读和不可重复读,但是没有办法避免幻读。需要特殊注意的是,Innodb 在 Repeatable Read 下通过 MVCC 提供了稳定的视图,因此 Innodb 的 RR 隔离级别下是不会出现上述幻读异常中的第一个场景的,但第二个场景还是会出现。
串行化 Serializable
使用表级锁来保证所有事务的串行化,可以防止所有的异常情况,但是牺牲了系统的并发性。
查看隔离级别的命令为
SHOW VARIABLES LIKE 'transaction_isolation'; # 或者 SELECT @@global.tx_isolation, @@tx_isolation;
第二种方式可以查看全局和当前会话的隔离级别。
设置隔离级别的命令为
# 将当前会话的隔离级别设为读未提交 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; # 将全局的隔离级别设为读未提交 SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
以上就是《MySQL事务的示例分析》的详细内容,更多关于mysql的资料请关注golang学习网公众号!

- 上一篇
- MySQL如何实现日期格式化

- 下一篇
- 迈入2023年,为什么大家都开始关注RedCap?
-
- 数据库 · MySQL | 45分钟前 |
- MySQL主键是什么?带你深度解读主键定义与作用
- 296浏览 收藏
-
- 数据库 · MySQL | 52分钟前 |
- 新手必看!MySQL数据库常用命令全掌握
- 265浏览 收藏
-
- 数据库 · MySQL | 2小时前 |
- 手把手教你用MySQL创建数据库,超详细步骤教学
- 496浏览 收藏
-
- 数据库 · MySQL | 3小时前 |
- MySQL增删改查太复杂?超全语法速查表助你轻松掌握!
- 154浏览 收藏
-
- 数据库 · MySQL | 3小时前 |
- MySQL数据同步不会?一篇文章教你搞定同步方法
- 288浏览 收藏
-
- 数据库 · MySQL | 4小时前 |
- 电脑没装MySQL?这5种快速检测方法赶紧学起来!
- 449浏览 收藏
-
- 数据库 · MySQL | 4小时前 |
- MySQL查询优化&索引技巧,小白轻松进阶大神!
- 425浏览 收藏
-
- 数据库 · MySQL | 6小时前 |
- 手把手教学!MySQL安装配置超详细步骤(保姆级教程)
- 199浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 83次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 93次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 97次使用
-
- 稿定PPT
- 告别PPT制作难题!稿定PPT提供海量模板、AI智能生成、在线协作,助您轻松制作专业演示文稿。职场办公、教育学习、企业服务全覆盖,降本增效,释放创意!
- 91次使用
-
- Suno苏诺中文版
- 探索Suno苏诺中文版,一款颠覆传统音乐创作的AI平台。无需专业技能,轻松创作个性化音乐。智能词曲生成、风格迁移、海量音效,释放您的音乐灵感!
- 91次使用
-
- MySQL主从切换的超详细步骤
- 2023-01-01 501浏览
-
- Mysql-普通索引的 change buffer
- 2023-01-25 501浏览
-
- MySQL高级进阶sql语句总结大全
- 2022-12-31 501浏览
-
- Mysql报错:message from server: * is blocked because of many
- 2023-02-24 501浏览
-
- 腾讯云大佬亲码“redis深度笔记”,不讲一句废话,全是精华
- 2023-02-22 501浏览