震惊!!!原来这就是事务!
一:引入
在日常开发中,很多操作并不是一个SQL就能完成的,往往需要多个SQL配合完成.当执行多个SQL的是时候,如果中间出现了特殊的情况(程序崩溃,系统崩溃,网络断开,主机断电…),可能就会出现,前面的SQL执行成功,后面的SQL 执行失败了
比如转账:假设A给B转账500元,此时首先A账户少500元,然后B账户会多500元,如果中间过程出现了差错,比如A少了500元后,网络断开了,此时B账户中并没有多500元.
显然上述情况并不允许出现.
经常会涉及到通过多个SQL配合,来完成某个操作的,这个时候就需要使用事务来确保上述的操作是可靠的,完整的.
事务:把多个操作打包成一个整体,就能够保证,这个整体要么都执行成功,要么一个都不执行,能够有效避免,部分执行,部分不执行产生的一些"中间状态引起的问题";
把多个操作打包成一个整体称为"原子性"
二:回滚机制
1:回滚的概念
事务中的若干SQL,必然是一条一条的执行的,事务能够保证,当执行到某一行的时候,如果出现了问题,数据库能够自动的把前面SQL造成的影响,给恢复回去,恢复如初,看起来好像一条 SQL都没执行的样子,
把恢复如初的过程就称为"回滚"
数据库事务的原子性,核心就是通过"回滚机制"来完成的.
2:日志:
数据库在执行事务的时候,会记录日志,也就是记录每个事务做了什么,当执行"回滚"的时候,数据库就可以根据这些日志来对数据库进行恢复操作,
比如:
(1)之前进行了新增操作,就会把数据删除掉,
(2)之前进行了删除操作,就把数据新增上来;
(3)之前进行了修改操作,就会把数据改回去
(4)之前是查询操作,不影响,不需要任何的恢复行为
如果事务最终都执行完毕,中间没有差错,日志中记录的这些内容就可以不要了.
三:事务的基本特性
1:原子性
根据回滚机制,能够触发还原
2:一致性
执行事务之前和执行事务之后,数据是一致的,不会出现对不上的情况
一致性也是和回滚有关的,一旦触发回滚了,回滚回去的数据是对的,如果顺利执行没有触发回滚,数据也是符合要求的
3:持久性
持久性:就是把数据存储在硬盘上,不是存储在内存中,当程序重启/主机重启,数据仍能存在.
执行事务对数据库产生的修改,就会在硬盘上之久保存,重启之后仍能存在.
(不仅仅是数据库,后序但凡见到"持久性"都是这个意思)
4:隔离性(重中之重)
1:概念:
描述的是,数据库并发执行事务时,产生的情况.
并发:多个客户端,同时给服务器发起事务.
那么数据库如何高效,准确的处理这些事务,就非常重要了.
2:脏读问题:
举例:老师正在备课,有同学路过的时候,偷偷瞄了一眼老师的代码,并暗暗的记下了,但后来老师又把代码改了,导致老师上课教的和同学看到的并不一样,这就是脏读问题.
**脏读问题:数据库中,如果有事务A和事务B,事务A针对某个表做出了一些修改,在事务A提交之前,事务B就对这里的数据进行了读取,最终就可能出现A后续的操作又把上述数据进行了修改,最终导致B读到的数据和A提交的数据,是不同的.
如何解决:
这个同学,发现自己脏读了,就过去找老师,于是老师就和同学们进行了约定:不要在身后偷瞄代码,如果想要提前预习课程,提前看到代码,可以在老师提交代码之后再进行阅读.
上述约定,就相当于针对"写操作"加锁,老师在写的时候,同学并不能读,写完了才可以读.
update student set math=90 where name='张三';
这里对张三同学的数学成绩进行了修改,在A事务未完成时,不能对张三同学的数学成绩进行查询操作(读操作)
加入写加锁之后,在执行A事务的过程中,B事务就不能执行了
这就降低了"并发能力",但由于不能同时处理多个事务,也就降低了数据库服务器的处理效率,提高了"隔离性",也提高了数据的准确性.
写操作,就做出来取舍,牺牲了一部分效率,换取到更高的准确性
3:不可重复读问题:
老师在备课,写代码,并且和同学们约定好了,写的时候同学不可以偷瞄老师的代码,一定是老师提交了,才可以进行阅读.
老师把代码提交了(事务A)
有同学发现,老师的码云更新了,就去读代码(事务B)
但老师突然意识到,代码可能还有点问题,还得进行修改,赶紧将代码修改,重新提交(事务C).
同学读的过程中,本来看到的是事务A中的结果,读着读着,代码就变了(老师提交了新的版本)
上述过程就是"不可重复读问题"
存在三个事务:A,B,C
事务A针对数据进行了修改,提交;接下来事务B进行读取数据(事务B这里的多个SQL都要进行读操作);在执行B的过程中,又有一个事务C,又对数据进行了修改,就会使B读到的数据和原先预想到的数据并不一样.
和同学们进一步约定,老师提交代码后,就不要改了,同学们读完之前,老师也不能修改代码
select * from student where name ='张三';
此时,B事务正在对张三的数学成绩进行读操作,事务C不能修改站张三同学的数学成绩
写操作加锁:写的时候,不能读
读操作加锁:读的时候,不能写
此时,引入读加锁,就会使"并发程度"又进一步降低,效率也随之降低,"隔离性"又进一步提高,数据的准确性又进一步提高了
这个时候,A,B,C都不能并发了.
3:幻读问题
刚刚约定了,针对读操作和写操作都加锁了.
举例:老师写了代码,并提交了,同学开始读代码,这里老师就不能修改代码的,但老师创建了一个新的类/文件,针对新的文件进行修改,并提交.
事务A先修改并提交数据,事务B进行读数据,此时事务C,没有修改B读的数据,但给相应的表进行了新增数据/删除数据,导致事务B读到的数据集不同,这就是幻读问题.
insert into student values ('李四',89,90);
事务C向学生表中新增了一行数据,但此时B正在读张三的数学成绩,虽然看似事务B,事务C没有关联,但事务C使事务B读的表发生了变化,也就造成了幻读问题.
解决幻读问题,“串行化”,使所有的事务都严格的按照"一个接一个" 的方式执行,完全没有并发了,此时执行效率最低,隔离性最高,数据也是最准确的.
标签:事务,老师,代码,回滚,SQL,原来,执行,震惊 From: https://blog.csdn.net/2302_77978695/article/details/136858454