在日常生活中,我们会遇到一个场景,那就是在转账的时候,A有1000块钱,要给B转账500,那么最后的结果是A有500,B有500,但是也有可能出现A没有钱了,B有1000块,或者在转账过程中卡顿,这是不符合逻辑的,那么这个时候就要使用事务来解决问题
事务就是把一堆sql语句打包成一个整体,要么全都执行,要么就不执行,那么是真的没有执行吗,其实这是一个假象,其实执行了,只是没有显现出来,执行了,执行到一半发现卡顿了,那么就还原到没执行 的样子.这个过程叫做回滚" roll back"
在回滚的过程中,我们要怎样知道回滚到哪一个地步了呢,需要额外的部分记录具体的操作,数据库中有专门的的事务记录日志,因此使用事务执行sql是非常耗费空间的
下面来看一看的事务执行的相关代码
start transaction//开启事务 update account set money=money-200 where name='李四'; update account set money=money+200 where name='张三' commit //提交事务 相等于事务已经执行完了
从start到commit之间的这段就是事务具体执行的操作
下面,来讨论一次啊数据库事务的特性
面试爱考的点
1.原子性
2.一致性 执行完前后数据对得上
3.持久性 事务修改的内容在硬盘上,可以持久保存
4.隔离性 这个是最难理解的,这个特性是为了解决并发执行事务,引起的问题
举个例子,去餐馆吃饭
如果一次性来了很多人,大家点不一样的餐,那么大厨如果只有一口锅,那么可以一个一个做,如果很多锅,可以一起炒
此时餐馆作为服务器,要处理顾客也就是客户端的请求,一次性来很多条请求,就需要一起处理,
数据库本质是服务器,那么处理大量请求,就是并发执行事务的过程
并发执行任务产生的问题以及数据库利用隔离性的解决办法
1.脏读问题
事务A在修改数据时,事务B读取了数据,而事务A在改完数据以后提交了,那么事务B原来读取的数据就是无效的,事务B读取的过程叫做脏读,读取到的数据叫做脏数据
解决办法
给写加锁,也就是在事务A写的时候或者改的时候,事务B不可以读,这样写操作和读操作不能同时并发执行了不能一起干
这样做降低了并发程度(降低了效率),提高了隔离性(提高了数据的准确性)
2.不可重复读
具体是这样的,事务A已经提交了数据,事务B开始读,而在事务B读的过程中,事务A又修改了数据提交,事务B在读的时候发现数据改变了,也就是在读的一次过程中,出现了不同的结果,就叫做"不可重复读"
解决办法
给读加锁,就是只能读,不能修改,在事务B读的过程中事务A不可以进行修改
进一步降低了并发程度(降低了效率),提高了事务的隔离性(进一步提高了数据的准确性)
3.幻读问题
事务A在写的时候事务B不可以读,事务B在读的时候事务A不可以写,这样在读加锁和写加锁的前提下,这样不会出现上述的两种情况,但是在事务B读1文件数据时,事务A可能又创建了一个文件,并且提交了
这个时候读到的结果集不一样了,就是读着读着多出现了一个文件,这就叫做幻读
解决办法
数据库使用"串行化"方式解决幻读的问题,放弃并发处理事务,一个一个串行处理事务
脏读 给写加锁
不可重复读 给读加锁
幻读 串行化处理
是并发处理事务产生的问题
面对上述三种问题
mysql提供了四种隔离级别
1. read uncommitted 没有任何锁限制,并发程度最高(效率最低),隔离性最低(数据准确性最低)
2.read committed 给写加锁,并发程度降低(效率提高),隔离性提高(数据准确性提高)
3.repeatable read 给读和写都加锁,并发程度进一步降低(效率进一步提高),隔离性进一步提高(数据准确性进一步提高)
4.serializable 串行化处理事务 并发程度最低,隔离性最高
加锁本质上是cpu 指令,后期在详细讲解
今天就讲解到这里,下期再见,886!!!