MySQL的事务详解_mysql事务的用法,大数据开发高级工程师每日面试题精选

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

– 若干条执行sql

– 提交/回滚事务
commit/rollback;


**注意**:


在开启事务之后, 执行sql不会立即去执行, 只有等到commit操作后才会统一执行(保证原子性).


**示例**:  
 首先创建一个账户表并初始化数据



– 创建一个账户表
create table account(
id int primary key auto_increment,
name varchar(20),
money double(10,2)
);
– 初始化账户信息
insert into account(name, money) values (‘张三’, 10000), (‘李四’, 10000);


首先看正常情况下的转账操作



– 张三账户 -2000
mysql> update account set money = money - 2000 where name = ‘张三’;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
– 李四账户 +2000
mysql> update account set money = money + 2000 where name = ‘李四’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
– 转账成功
mysql> select * from account;
±—±-------±---------+
| id | name | money |
±—±-------±---------+
| 1 | 张三 | 8000.00 |
| 2 | 李四 | 12000.00 |
±—±-------±---------+
2 rows in set (0.00 sec)


如果操作中出现异常情况, 比如sql语句中所写的注释格式错误导致sql执行中断.



– 先将张三和李四的账户余额恢复为10000元
update account set money = 10000 where name = ‘张三’;
update account set money = 10000 where name = ‘李四’;
– 张三 -2000
mysql> update account set money = money - 2000 where name = ‘张三’;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
– 李四 +2000
mysql> 没加–的注释
-> update account set money = money + 2000 where name = ‘李四’;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘没加–的注释
update account set money = money + 2000 where name = ‘李四’’ at line 1
– 出现异常
mysql> select * from account;
±—±-------±---------+
| id | name | money |
±—±-------±---------+
| 1 | 张三 | 8000.00 |
| 2 | 李四 | 10000.00 |
±—±-------±---------+
2 rows in set (0.00 sec)


观察结果发现了张三的账户少了2000元, 但李四的账户余额并没有增加, 在实际操作中这种涉及钱的操作发生这种失误可能会造成很大的损失.


为了防止这种失误的出现我们就可以使用事务来打包这些操作.



– 先将张的账户余额恢复为10000元
update account set money = 10000 where name = ‘张三’;
– 开启事务
start transaction;
– 张三 -2000
mysql> update account set money = money - 2000 where name = ‘张三’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
– 李四 -2000
mysql> 没加–的注释
-> update account set money = money + 2000 where name = ‘李四’;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘没加–的注释
update account set money = money + 2000 where name = ‘李四’’ at line 1
– 预期结果
mysql> select * from account;
±—±-------±---------+
| id | name | money |
±—±-------±---------+
| 1 | 张三 | 8000.00 |
| 2 | 李四 | 10000.00 |
±—±-------±---------+
2 rows in set (0.00 sec)


观察这里的结果发现在当前的数据库用户查询到的account表中的账户余额发生了变化,但开启了事务之后在commit之前只是临时的预操作并不会真的去修改表中的数据;


可以退出数据库再打开重新查询表中数据或者切换用户去查询去验证表中数据是否发生改变, 这里就不作演示了.


发现操作结果异常之后, 当前用户需要恢复到事务之前的状态, 即进行回滚操作.



– 回滚事务
mysql> rollback;
Query OK, 0 rows affected (0.03 sec)
– 验证回滚后的状态
mysql> select * from account;
±—±-------±---------+
| id | name | money |
±—±-------±---------+
| 1 | 张三 | 10000.00 |
| 2 | 李四 | 10000.00 |
±—±-------±---------+
2 rows in set (0.00 sec)


如果开启事务之后发现预操作的结果是预期的效果, 此时我们就可以提交事务, 当我们提交完事务之后, 数据就是真的修改了, 也就是硬盘中存储的数据真的改变了.



– 开启事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
– 张三 -2000
mysql> update account set money = money - 2000 where name = ‘张三’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
– 李四 +2000
mysql> update account set money = money + 2000 where name = ‘李四’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
– 提交事务
mysql> commit;
Query OK, 0 rows affected (0.03 sec)

mysql> select * from account;
±—±-------±---------+
| id | name | money |
±—±-------±---------+
| 1 | 张三 | 8000.00 |
| 2 | 李四 | 12000.00 |
±—±-------±---------+
2 rows in set (0.00 sec)


要注意事务也不是万能的, 不能保证你删表删库之后可以完全恢复, 只是在适量的数据和操作下使用事务可以避免一些问题.


回滚(rollback)操作, 实际上是我们把事务中的操作再进行逆操作, 前面是插入, 回滚就是删除…


这些操作是有很大开销的, 可以保存, 但不能够无限保存, 最多是将正再执行的事务保存下来, 额外的内容就不好再保存了; 数据库要是有几十亿条数据, 占据了几百G硬盘空间, 不可能去花费几个T甚至更多的空间用来记录这些数据是如何来的.


## 三. 事务的特性(ACID)


### 1. 原子性(Atomicity)


一个事务是一个不可分割的最小单位, 事务中的所有操作要么全部成功, 要么全部失败, 没有中间状态.


原子性主要是通过事务日志中的回滚日志(undo log)来实现的, 当事务对数据库进行修改时, InnoDB 会根据操作生成相反操作的 undo log, 比如说对 insert 操作, 会生成 delete 记录, 如果事务执行失败或者调用了 rollback,就会根据 undo log 的内容恢复到执行之前的状态.


事务的原子性, 也是事务的核心特性, 是事务的初心.


### 2. 一致性(Consistency)


事务执行之前和执行之后数据都是合法的一致性状态, 即使发生了异常, 也不会因为异常引而破坏数据库的完整性约束, 比如唯一性约束等.


事务执行前/执行后, 都得是数据合法的状态; 比如像上面的转账, 不能说转的过程出错了, 导致出现钱转丢了的情况.


### 3. 持久性(Durability)


事务提交之后对数据的修改是持久性的, 即使数据库宕机也不会丢失, 通过事务日志中的重做日志(redo log)来保证; 事务修改之前, 会先把变更信息预写到 redo log 中, 如果数据库宕机, 恢复后会读取 redo log 中的记录来恢复数据(回滚).


事务产生的修改, 都是会写入硬盘的, 程序重启/主机重启/掉电, 事务都可以正常工作, 保证修改是生效的.


### 4. 隔离性(Isolation)


这里的隔离性是指**一个数据库服务器, 同时执行多个事务的时候, 事务之间的相互影响程度**.


一个服务器, 可以同时给多个客户端提供服务, 这多个客户端是**并发执行**的关系, 多个客户端就会有多个事务, 多个事务同时去操作一个表的时候, 特别容易出现互相影响的问题.


如果隔离性越高, 就意味着事务之间的并发程度越低, 执行效率越慢, 但是数据准确性越高.


如果隔离性越低, 就意味着事务之间的并发程度越高, 执行效率越快, 但是数据准确性越低.


隔离性通过事务的隔离级别来定义, 并用锁机制来保证写操作的隔离性, 用 MVCC 来保证读操作的隔离性.


## 四. 事务并发异常


在实际生产环境下, 可能会出现大规模并发请求的情况, 如果没有妥善的设置事务的隔离级别, 就可能导致一些异常情况的出现,最常见的几种异常为`脏读(Dirty Read)`, `幻读(Phantom Read)`和`不可重复读(Unrepeatable Read)`.


### 1. 脏读


**一个事务读取到了另外一个事务没有提交的数据(读写的是同一份数据)**.


说详细点就是当一个事务正在访问数据并且对数据进行了修改, 而这种修改还没有提交到数据库中,与此同时时另外一个事务也访问这个数据, 然后使用了这个数据; 因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据就是脏数据, 依据脏数据所做的操作可能是不正确的.


用一个场景例子来理解, 张三正在写代码, 李四趴在屏幕前看张三写代码, 等张三走掉之后, 李四就把他刚刚写的这段代码删掉了, 此时李四看到的这段代码就可能是一个错误的代码.


在这个场景下, 张三和李四就可以理解为两个事务, 这两个事务是完全并发没有任何限制的, 此时就会出现脏读问题.


**解决脏读问题的办法, 就是降低并发性, 提高隔离性, 具体来说就是给这里的 “写操作” 加锁**, 张三在写代码的时候, 李四不能看, 张三和李四约定张三代码写完后会提交到githup上, 李四去githup上去看.


当进行了写加锁的时候, 张三写的时候, 李四就不能同时去读了; 相当于降低了并发程度, 提高了隔离性. 降低了一定的效率, 但是提高了准确性.


### 2. 不可重复读



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
![img](https://img-blog.csdnimg.cn/img_convert/921837f0fba545c3fca6f2f920ab6006.png)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

但是提高了准确性.


### 2. 不可重复读



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-p1LjjFAA-1713312465396)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值