大话mysql事务

本文介绍了事务在软件开发中的作用,特别是其原子性、一致性、持久性和隔离性的概念,以及如何通过事务解决并发执行中的脏读、不可重复读和幻读问题。作者强调了在不同场景下选择适当隔离级别的必要性,以平衡效率与正确性。
摘要由CSDN通过智能技术生成

在软件开发的过程中,经常会遇到需要"一气呵成"做完的事情,比如说,微信转账,如果你朋友给你转了5000块,而你却没收到,那可不得了,像这种程序执行的不上不下的情况,就是非常明显的bug

此时我们引入事务,就是为了防止这种事情发生,事务就可以把这些多个sql语句统统打包到一起执行,此时要么执行成功,要么就不执行(这里的不执行不是真正的不执行,是执行到错误的sql后,会发生回滚(这个下面会说),只是看起来是和没执行一样而已),另外事务把多个sql打包在一起,作为一个整体的特性,叫做原子性。所谓原子性,你想,事务整体执行sql不可分割的特性,原子也算是有不可分割的特性(当然别较真),

事务的使用

(1)开启事务:start transaction;

(2)执行多条SQL语句

(3)回滚或提交:rollback/commit;

举个例子

start transaction;

-- 阿里巴巴账户减少2000

update accout set money=money-2000 where name = '阿里巴巴';

-- 四十大盗账户增加2000

update accout set money=money+2000 where name = '四十大盗';

commit;

 另外提一嘴,rollback一般是要搭配一些条件判断逻辑来使用的

sql里面也能支持条件,循环,变量,函数(但是真正开发的时候,一般不会这么写,更多的是搭配其他是编程语言来使用)

还有回滚(rollback)是怎么进行的呢

其实我们是通过日志的方式,来记录事务中的一些关键操作,日志里的记录,就是回滚的关键依据这样即使是主机掉电,那也不影响,记录的日志已经在文件中了,这样一旦重新启动主机,mysql也重新启动,就会发现回滚日志中会有一些需要回滚的操作,于是就可以完成这日志里的回滚了。

当然这篇文章对于事务的使用我不会去过多的讲解,这里我们更关注的是事务背后一些原理性质的内容

事务的四大特性

1.原子性 :上面已经提到过,通过回滚的方式,保证这一系列操作都能正确执行或者恢复如初。

2.一致性 : 通俗的说就是事务执行之前,和事务执行之后,结果不能离谱。打个比方,张三给李四转了一千万,但李四只收到了1块钱,那张三和李四可能都会发疯的。

通常这个一致性是要靠数据库的一系列约束和检查机制来完成的

3.持久性 :事务做出的修改,在硬盘上都是永久保存的,即使是重启服务器,数据仍然存在,事务修改的数据仍然是有效的 

4.隔离性(重点):这是数据库在并发执行的时候可能会涉及的问题,我们知道mysql数据库是一个客户端服务器结构的程序,一个服务器可以给多个客户端提供服务,那就很可能或者说一定会发生,客户端1,提交的事务1刚执行了一半,客户端2,又提交了一个事务2,这时候,服务器就需要同时处理这两个事务,这就叫并发执行。比如一个餐馆只有一个锅,那么一次只能炒一个菜,其他客人要点的菜就要排队等待,此时并发程度是不高的,效率也不高。如果一个餐馆有十几个锅,那就很快,一次可以炒十几个菜,那么并发程度很高,效率当然也高。

虽然并发程度越高,效率越高,听起来效率高不是啥坏事,但是效率高真的好吗。一个厨子只炒一个菜,那么炒的菜肯定比同时炒十几个菜的质量更高,毕竟菜多了可能会一个菜没放盐,一个盐放多了,和其他这样那样的问题。中学有个文章叫,鱼我所欲也,熊掌亦我所欲也。可鱼与熊掌不可兼得。拥抱了效率,就放弃了正确性,拥抱了正确性,就失去了效率。要鱼还是熊掌,就需要看自己的实际情况来选择了。

这时候我们引入隔离级别,来在效率和正确性之间做权衡。隔离级别越高,正确度越高,效率越低,反之亦然。

那么我们在并发执行事务的时候会出现啥问题呢。

1:脏读问题

指在并发环境下,一个事务读取到了另一个事务尚未提交的数据,导致事务读取到了不一致的、未经验证的数据

比如我在写作业,而我室友在我身后看我的作业,这时候我就是一个事务,负责写数据,而我的室友是一个事务,负责读数据,如果此时我写完作业合上书睡觉,明天再去把这个作业交上去,这不会有任何问题。但是如果我写完作业,他读到一半走了,我回头又把作业给改了,那第二天室友看到我的作业和他看到的不一样,那他就要骂我说你个b诈我是吧,实际上我可没有骗他,只是因为他读的不是我的最终结果,读到了脏数据而已(数据集中包含错误、不完整或不一致的数据叫脏数据)。这就是高效率并发执行时很容易出现的问题。

那么怎么解决呢,解决脏读问题的核心思路就是针对写操作加锁,这时候我告诉室友,我写作业的时候你先别看,等我确认好了,放你桌子上你再看,这时候就是写加锁(写的时候,你别看),这时候,并发程度降低,但数据的可靠性变高了。

2:不可重复读问题

指在并发环境下,一个事务在执行过程中读取了两次相同的数据,但是得到的结果却不一致的情况

还是说写作业我作业写好了,确认了,放到室友桌子上了,室友在读的过程中,我人突然想把写好的作业再优化一下(毕竟刚刚是写加锁,我写的时候室友不能读,但可没说读的时候我不能写),这种情况下,室友读一下,数据变一下。重复:这种并发执行事务的过程中,如果事务A在内部多次读取同一个数据的时候,出现不同的情况,这种就是不可重复读问题。就像你去买菜,第一天白菜是2毛一斤,第二天是5毛一斤,那还说得过去,可是你同一天,第一次问两毛,再问就是7毛这就不能接受了

那么解决办法和上面类似,给读操作加锁(就是室友读作业的时候,我也不能改室友读的作业),这样并发程度进一步降低,隔离性进一步提高,数据的准确性就又提高了 ,当然效率也降低了

3:幻读问题

指在分布式数据库中进行并发读操作时,由于多个事务同时读取相同数据项的不同版本,导致读取的结果出现不一致的现象

我这次A,然后我写完了给室友读(写加锁),室友读的时候我也没有改写文件A(读加锁),但我想我闲着也是闲着,那我就再写个文件B吧,可一写不得了,文件B对文件A产生了影响,本来室友读着A文件,突然又蹦出来个B文件,这种一个事务A执行过程中,两次的读取操作,数据内容虽然没改变,但是结果集变了(就是本来读的是张三,李四,突然又变成了张三,李四,王五了),这种情况称为幻读。

那么我们可以引入串行化的方式,保持绝对的串行执行事务,此时完全没有并发了,隔离性最高,效率最低,数据最准确的了。

总结:事务的执行有舍有得,在效率和正确性之间,不同场景有不同需求,mysql服务器也提供了"隔离级别"来让我们针对隔离程度进行设置应付不同的需求场景。比如涉及钱财,微信转账这些,宁可牺牲效率,也一定要保证准确性,而像B站播放,点赞量这些,准确性的要求就没有这么高。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值