事务
什么是事务?
事务有什么用?
事务怎么用?
1. 新建一个数据库 bank , 并且创建一张表 account , 用于存储用户的姓名 和 存款。
2. 打开命令行,进入 mysql 终端
3. 先使用 show variables like '%commit%'; 来查看当前数据库的事务自动提交设置。
4. 修改事务的自动提交 为 OFF , 也就是关闭自动提交,我们想手动提交,看看数据的变化。
set autocommit = OFF ; 此处 off 小写也OK ,不区分大小写, 当然也可以写 0 , OFF 对应的是 0 , ON 对应的是 1;
5. 对某个用户的存款进行修改。 接着在 命令行下查看数据,发现数据已经变化, 但是转到 GUI 下看,并没有任何变化。 这是因为我们没有提交数据。
在命令行看到的都是假象而已。
6. 在命令行下 输入 commit ; 来提交事务。 这时候,GUI 上面就显示出来最终的结果了。
事务的ACID
事务中的逻辑d要全部执行 , 不可分割.
指事务执行前和执行后,数据的完整性保持一致
指一个事物在执行的过程中不应该受其他事务的影响
事务执行结束(提交或回滚),数据都应持久化到数据库 中
事务的安全问题
张三工资5000, A事务读到的且求改成8000,
此时B事务读取张三的工资, B事务读到的是8000,
A事务发生了回滚,B事务读取到的数据就是脏数据.
张三工资5000,A事务读取张三的信息,修改成了7000,但是没提交,
B事务读取到张三的信息,修改为8000,且提交事务,
但当A事务再次读取张三信息时,张三的工资变成了8000,前后两次读到的数据不一致.
A事务读取了10数据工资为5000的数据,此时B事务插入了一条工资为5000的数据.
A事务再次读取这工资为5000的数据时,出现了11条.前后读的数据量不一致,产生幻读
''
丢失更新: 指一个事物去修改数据库, 另一个事务也修改数据库,最后的那个事务.不管是提交还是回滚,都会造成前面一个事物的数据更新丢失
''
指事务在一开始就认为丢失更新一定会发生, 这是一件很悲观的事情。 具体操作步骤如下:
select * from student for update ; 后面的for update 其实是数据库锁机制 、 一种排他锁。
所以这时候不允许修改, 要求其重新查询 。
事务的隔离级别
Read Uncommited【读未提交】
指的是 : 一个事务可以读取到另一个事务还未提交的数据。 这就会引发 “脏读” 读取到的是数据库内存中的数据,而并非真正磁盘上的数据。
例子:
1. 开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read uncommitted;
2. 另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3. 在A窗口重新执行查询, 会看到B窗口没有提交的数据。
Read Commited 【读已提交】
与前面的读未提交刚好相反,这个隔离级别是 ,只能读取到其他事务已经提交的数据,那些没有提交的数据是读不出来的。但是这会造成一个问题是: 前后读取到的结果不一样。 发生了不可重复!!!, 所谓的不可重复读,就是不能执行多次读取,否则出现结果不一 。 例子如下:
1. 开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read committed;
2. 另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3. 在A窗口重新执行查询, 是不会看到B窗口刚才执行sql 语句的结果,因为它还没有提交。
4. 在B窗口执行提交。
5. 在A窗口中执行查看, 这时候才会看到B窗口已经修改的结果。
6. 但是这会造成一个问题是: 在A窗口中, 第一次查看数据和第二次查看数据,结果不一样。
Repeatable Read 【重复读】 - MySql 默认的隔离级别就是这个。
该隔离级别, 可以让事务在自己的会话中重复读取数据,并且不会出现结果不一样的状况,即使其他事务已经提交了,也依然还是显示以前的数据。
1. 开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read committed;
2. 另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3. 在A窗口重新执行查询, 是不会看到B窗口刚才执行sql 语句的结果,因为它还没有提交。
4. 在B窗口执行提交。
5. 在A窗口中执行查看, 这时候查询结果,和以前的查询结果一致。不会发生改变。
Serializable 【可串行化】
该事务级别是最高级的事务级别了。比前面几种都要强大一点,也就是前面几种的问题【脏读、不可重复读、幻读】都能够解决。但是有一些缺点。
1. 开启一个命令行窗口A, 开始事务,然后查询表中记录。 设置当前窗口的事务隔离级别为 读未提交 命令如下:
set session transaction isolation level read serializable;
2. 另外在打开一个窗口B, 也开启事务, 然后执行 sql 语句, 但是不提交
3. 在A窗口重新执行查询, 会卡主,没有任何信息显示。
4. 在B窗口执行提交。
5. 在A窗口中执行查看, 这时候才会显示结果。
Serializable 可以防止上面的所有问题,但是都使用该隔离级别也会有些问题。 比如造成并发的性能问题。 其他的事务必须得等当前正在操作表的事务先提交,才能接着往下,否则只能一直在等着。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?