事务 ---- mysql

一. 引出事务

在日常开发中, 很多操作不是通过一个SQL完成的, 往往需要多个SQL配合完成

但是当多个SQL操作时, 如果中间出现了特殊的情况(程序崩溃, 系统崩溃, 网络断开, 主机掉电......), 那么可能就会出现, 前面的SQL执行成功, 后面的SQL执行失败了

考虑一个场景: 转账

如果a要给b转账500, 那么a的余额-500, b的余额+500, 那么如果在a的余额-500之后, 就出现了上述的特殊情况, 那么这个钱就消失了

这个时候就要使用到事务

二. 概念

事务, 指把多个操作, 打包成一个整体, 就能够保证, 这个整体要么都执行成功, 要么就一个都不执行, 有效避免, 部分执行, 部分未执行, 产生的一些"中间状态引起的问题"
其实, 如果中间出现问题, 并不是真的一个都没有执行, 事务中的若干个SQL必然是要一条一条执行的, 但是事务能够保证, 当执行到某一条的时候如果出现问题了, 数据库就能够自动把前面的sql造成的影响, 给恢复回去, 恢复完成, 看起来就好像一条sql都没执行的样子
像这样的"翻新"操作, 称为**"回滚"(rollback)**
为了实现回滚机制, 数据路在执行事务的时候, 记录日志
(数据库的日志是写入到硬盘的文件中)
当事务最终都执行完毕, 中间没有差错, 那么这些记录内容就可以不要了
但是如果执行事务的过程中, 出现问题了, mysql就可以根据日志中记录的内容, 来进行恢复操作
1)之前进行了新增操作, 就把数据删除掉
2)之前进行了删除操作, 就把数据新增回来
3)之前进行了修改操作, 就把数据改回去
4)之前进行了查询操作, 不需要任何恢复行为

三. 事务的基本特性

1. 原子性
上述把多个操作打包成一个整体, 有回滚机制, 能够出发还原的这种特性, 称为"原子性"
2. 一致性
执行事务之前和执行事务完毕之后, 数据是一致的, 不会出现对不上的情况, 其实和回滚是有关的, 一旦触发回滚了, 回滚回去的数据得是对的, 如果顺利执行没有触发回滚, 数据也是符合要求的
3. 持久性
但凡提到持久性, 就要想要: 把数据存储在硬盘上
此处的持久, 指的是程序重启/主机重启, 数据仍然存在
执行事务产生的修改, 会在硬盘上持久保存
4. 隔离性
隔离性主要考虑的是, 数据库并发执行事务时, 产生的情况
并发是指: 多个客户端, 同时给服务器, 发起事务,
此时就需要数据库服务区都能够给处理
如果同时处理, 又可能会出现问题:
1) 脏读问题
数据库中, 如果有事务A和事务B, 事务A针对某个表做出了一些修改, 但是在事务A提交之前(即事务完毕之前), 事务B就对这里的数据进行了读取, 最终就可能出现A后续的操作又把上述数据进行了修改, 导致最终B读到的数据和A提交的数据是不同的, 于是就出现了"脏读问题"
为了避免这样的情况出现, 我们可以针对 "写操作"加锁
本来是执行事务A的时候, B事务可以执行, 但是引入写加锁后, 执行A的过程中, B就不能执行了, 要等待
但是这样就相当于降低了"并发能力", 也就会降低数据库服务器的处理效率, 同时提高了"隔离性", 也提高了数据库的准确性
并发执行事务的过程中, 相互之间影响越小, 隔离性就越高, 影响越大, 隔离性就越低
2) 不可重复读问题
存在三个事务ABC, 事务A针对数据进行修改, 提交, 接下来事务B进行读取数据, 在B执行的过程中, 又有一个事务C, 又针对数据进行修改, 而此时事务B还在对数据进行读取, 就会出现前后读取的数据不一致
为了避免这样的情况出现, 我们可以针对" 读操作"加锁
本来是执行事务B的时候, C事务可以执行, 但是引入读加锁后, 执行B的过程中, C就不能执行了, 要等待
同样这样就相当于降低了"并发能力", 也就会降低数据库服务器的处理效率, 同时提高了"隔离性", 也提高了数据库的准确性
3) 幻读问题
事务A先修改并提交了数据, 事务B进行读数据, 此时事务C, 没有修改B读的数据, 但是给对应的表进行了新增数据/删除数据等操作, 导致事务B中, 读到的数据集不同, 就会出现"幻读问题"
解决幻读的方式, 是 "串行化", 时所有的事务都严格的按照"一个接一个"的方式进行, 完全没有并发了
此时执行的效率是最低的, 隔离性也是最高的, 数据也是最准确的
总结一下:
1)脏读 ==> 写加锁
2) 不可重复读 ==> 读加锁
3) 幻读 ==> 串行化
mysql事务的隔离性具体是怎么实现呢? mysql给程序猿提供了四个隔离级别, 可以在mysql配置文件中进行设置

  1. read uncommitted: 允许读取其他事务未提交的数据
  2. read committed: 不允许读取其他事务未提交的数据
  3. repeatable read: 针对读操作和写操作都加锁了
  4. serializable(串行化): 所有事物都是串行执行的
    在实际开发中, 我们要根据具体的应用场景来选择不同的隔离级别

四. 使用事务

  1. 开始事务:
    start transaction;
  2. 回滚或提交:
    rollback/commit;
    例:
sql 复制代码
start transaction;
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
commit;

中间的SQL语句, 就被打包成一个整体了

相关推荐
jiayou6415 小时前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
于眠牧北16 小时前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
李广坤1 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12022 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1773 天前
《从零搭建NestJS项目》
数据库·typescript
加号33 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏3 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐3 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再3 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip