多多卡起货网站建设,凡科自助建站系统,mysql 网站空间,wordpress怎么加地图吗mysql事务讲解
MySQL事务处理#xff08;TransAction#xff09; 大家好#xff0c;我是一名热爱研究技术并且喜欢自己亲手实践的博主。
工作这么多年#xff0c;一直没有深入理解MySQL的事务#xff0c;因为最近也在面试#xff0c;准备复习mysql的相关知识#xff0…mysql事务讲解
MySQL事务处理TransAction 大家好我是一名热爱研究技术并且喜欢自己亲手实践的博主。
工作这么多年一直没有深入理解MySQL的事务因为最近也在面试准备复习mysql的相关知识帮自己回顾总结一下其次就是想把这篇博客分享给大家如果你才刚刚开始学习mysql那么希望这篇博客对你有一点启发亦或者你早已是一个mysql老油条这篇博客也会使你对mysql事务有一个更深的印象。
话不多说直接开始上强度…
首先什么是事务呢
事务就是由单独单元的一个或多个sql语句组成在这个单元中每个sql语句都是相互依赖的。而整个单独单元是作为一个不可分割的整体存在类似于物理当中的原子一种不可分割的最小单位。
往通俗的讲就是事务就是一个整体里面的内容要么都执行成功要么都不成功。不可能存在部分执行成功而部分执行不成功的情况。
就是说如果单元中某条sql语句一旦执行失败或者产生错误那么整个单元将会回滚(返回最初状态)。所有受到影响的数据将返回到事务开始之前的状态但是如果单元中的所有sql语句都执行成功的话那么该事务也就被顺利执行。
大家都知道我们的数据都是通过各种不同技术的存储引擎来引导存储的不同的存储引擎都有各自的特点。在mysql中常见的存储引擎有innodb、myisammemory等。其中innodb支持事务(transaction)而myisammemory等不支持事务。
可以通过show engines;语句来查看mysql支持的存储引擎
一、事务的四个特性(ACID)【面试常考项】
原子性Atomicity指事务是一个不可分割的最小工作单位事务中的操作只有都发生和都不发生两种情况 一致性Consistency事务必须使数据库从一个一致状态变换到另外一个一致状态举一个例子李二给王五转账50元其事务就是让李二账户上减去50元王五账户上加上50元一致性是指其他事务看到的情况是要么李二还没有给王五转账的状态要么王五已经成功接收到李二的50元转账。而对于李二少了50元王五还没加上50元这个中间状态是不可见的。 隔离性Isolation一个事务的执行不能被其他事务干扰即一个事务内部的操作及使用的数据对并发的其他事务是隔离的并发执行的各个事务之间不能互相干扰。 持久性Durability一个事务一旦提交成功它对数据库中数据的改变将是永久性的接下来的其他操作或故障不应对其有任何影响。
二、事务的分类
事务分为隐式事务和显式事务两种。我们的DML语句insert、update、delete就是隐式事务。
隐式事务该事务没有明显的开启和结束标记它们都具有自动提交事务的功能不妨思考一下update语句修改数据时是不是对表中数据进行改变了它的本质其实就相当于一个事务。 举一个例子张三同学买了一个csdn定制保温杯花了99元是不是就是update语句对字段name为张三的同学的余额balance进行减99元的处理呢
显示事务该事务具有明显的开启和结束标记也是本文重点要讲的东西。使用显式事务的前提是你得先把自动提交事务的功能给禁用。禁用自动提交功能就是设置autocommit变量值为00:禁用 1:开启 先查看一下当前的autocommit变量值发现当前处于开启自动提交事务的状态 禁用自动提交事务的功能并查看当前状态
三、开启事务的步骤
假设t_account表已经存在
#步骤一开启事务可选
start transaction;
#步骤二编写事务中的sql语句insert、update、delete
#这里实现一下李二给王五转账的事务过程
update t_account set balance 50 where vname 李二;
update t_account set balance 130 where vname 王五;
#步骤三结束事务
commit; #提交事务
#rollback;#回滚事务:就是事务不执行回滚到事务执行前的状态四、事务并发时出现的问题
但是呢因为某一刻不可能总只有一个事务在运行可能出现A在操作t_account表中的数据B也同样在操作t_account表那么就会出现并发问题对于同时运行的多个事务当这些事务访问数据库中相同的数据时如果没有采用必要的隔离机制就会发生以下各种并发问题。
脏读对于两个事务T1,T2T1读取了已经被T2更新但还没有被提交的字段之后若T2回滚T1读取的内容就是临时且无效的 不可重复读 对于两个事务T1,T2T1读取了一个字段然后T2更新了该字段之后T1在读取同一个字段值就不同了 幻读对于两个事务T1,T2T1在A表中读取了一个字段然后T2又在A表中插入了一些新的数据时T1再读取该表时就会发现神不知鬼不觉的多出几行了… 所以为了避免以上出现的各种并发问题我们就必然要采取一些手段。mysql数据库系统提供了四种事务的隔离级别用来隔离并发运行各个事务使得它们相互不受影响这就是数据库事务的隔离性。
五、事务的隔离级别
mysql中的四种事务隔离级别如下
1. read uncommitted读未提交数据允许事务读取未被其他事务提交的变更。脏读、不可重复读和幻读的问题都会出现。 2. read committed读已提交数据只允许事务读取已经被其他事务提交的变更。可以避免脏读但不可重复读和幻读的问题仍然可能出现 3.repeatable read可重复读确保事务可以多次从一个字段中读取相同的值在这个事务持续期间禁止其他事务对这个字段进行更新(update)。可以避免脏读和不可重复读但幻读仍然存在 4. serializable串行化确保事务可以从一个表中读取相同的行在这个事务持续期间禁止其他事务对该表执行插入、更新和删除操作所有并发问题都可避免但性能十分低下因为你不完成就都不可以弄效率太低
了解: oracle支持两种事务隔离级别read committed、serializable。
oracle默认的事务隔离级别是read committed。
mysql的默认事务隔离级别是repeatable read。一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别不同隔离级别对应不同的干扰程度隔离级别越高数据一致性就越好但并发性就越差。 这里通过一个例子向大家简单介绍一下并发 一个人 在边开车 边打电话首先人只有一个大脑cpu,但是在同一时刻他却在执行2件事情其实内部就是靠他的大脑在不断的切换执行之所以人民警察 不允许司机开车时打电话就是怕人脑在那一瞬间切换不过来从而导致交通事故的发生并发和这个例子是差不多的意思。但在这里电脑cpu可比人脑快多了所以出错的概率也相对来说小很多。
接一下演示一下在几种不同的事务隔离级别下所发生的不同情况 。 在演示之前呢还需要知道如何查看和设置事务的隔离级别 查看当前的事务隔离级别通过 tx_isolation变量或者transaction_isolation(版本8.0以上使用) 语法select tx_isolation; 注意在mysql8.0之后就已经抛弃了tx_isolation变量了而是用 transaction_isolation变量代替了。 语法select transaction_isolation;
#设置当前mysql连接的隔离级别:
set session transaction isolation level read uncommitted;
#设置数据库系统的全局的隔离级别:
set global transaction isolation level read uncommitted;注意当前mysql连接的隔离级别和mysql全局的隔离级别的区别是什么
如果只设置当前的隔离级别即当前打开的navacat窗口也就是session那么另外一个并发的“mysqy程序”的隔离级别不会受到当前连接的影响而是保持默认的repeatable read。
但是如果是设置全局的事务隔离级别则整个mysql数据库包括所有打开的mysql程序连接的隔离级别都会随之改变除非服务器重启不然就不会恢复默认了。 两者仅仅一词之差其效果却天差地别。 好了解完如何设置事务的隔离级别之后下面将正式进入… 这里的讲解主要是为了知道在并发的环境下不同的事务隔离级别所表现出的不同特点那么自然还是要先模拟一下并发环境
这里打开两个独立的mysql数据库连接mysql程序1和mysql程序2用来模拟并发环境 事务T1 事务T2 同志们打起精神认真看啊
read uncommitted读未提交 首先我们需要先将两个会话的事务隔离级别都设置为read uncommitted语句如下
#事务T1
#设置隔离级别读未提交
set session transaction isolation level read UNCOMMITTED;
select tx_isolation;
#select transaction_isolation;8.0以后版本用这个
#禁止自动提交事务
set autocommit 0
SELECT autocommit;#事务T2
#设置隔离级别读未提交
set session transaction isolation level read UNCOMMITTED;
select tx_isolation;
#select transaction_isolation;8.0以后版本用这个
#禁止自动提交事务
set autocommit 0
SELECT autocommit;此图为t_student的表数据以下代码通过user_id为12的这条数据作验证
read uncommitted可以读到其他事务还没提交的变更这里举例事务T2对t_student表中的数据进行更改看事务1多次查询的结果是否一致。 操作步骤 1.执行事务T1中的语句 2.执行事务T2中的语句千万不要提交 3.执行事务T1中的语句
步骤1执行结果 步骤2执行完步骤3执行结果
可以看到事务T2修改了t_stundent表中的age字段但是事务T1两次执行的结果不一样后一次查询和表中数据也不一致因为事务T2未提交所以这就是读未提交的特点不管你事务是否提交只要数据发生改变我就可以察觉到。 未解决的问题 脏读回滚T2,此时第二次T1的查询就是无效的 不可重复读两次读取的结果不一致 幻读可以把T2的update换成insert语句会发现第二次事务T1读取的数据多了几行
接下来要看的是read committed读已提交
read committed读已提交
测试前一定要记住设置事务的隔离级别为read committed并且禁用自动提交事务【设置autocommit为0】后面的每个测试都是一样的
# 设置事务隔离级别为read committed
set session transaction isolation level read committed;
# 禁用自动提交事务功能
set autocommit 0;
#接下来的 repeatable read 隔离级别和 serializable 隔离级别也是同样的操作细节T2执行udate之后控制执行的返回结果是修改行数是0只有提交之后修改的结果才会大于1(当前条件下数据确实是存在的) 可以看到事务T2修改了t_stundent表中的age字段但是事务T1两次执行的结果仍然一样两次查询和表中数据一致因为事务T2未提交所以这就是读已提交的特点只有事务已经提交其他事务才可以察觉到。 未解决的问题 脏读已解决因为脏读是能读取未提交的数据但此时并未读取到T2未提交的数据 不可重复读两次读取的结果不一致即T2前后T1查询的结果不一致 幻读可以把T2的update换成insert语句会发现第二次事务T1读取的数据多了几行
repeatable read可重复读
该隔离级别为mysql的默认隔离级别它对某字段进行操作时其他事务禁止操作该字段。它总能保持你读取的数据是一致的。 细节T2执行udate之后控制执行的返回结果是修改行数是0只有提交之后修改的结果才会大于1(当前条件下数据确实是存在的)
事务T2操作t_student表时事务T1是无权对t_account表进行任何操作,如果强行操作的话就会一直等待直到T 事务T2提交或者回滚(一直等待会报错 (“ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction”翻译为“超过锁定等待超时尝试重新启动事务”))这里是因为事务T2update语句会默认添加独占锁如果其他事务对持有独占锁的记录进行修改时就会被阻塞。 脏读已解决因为脏读是能读取未提交的数据但此时并未读取到T2未提交的数据 不可重复读已解决两次读取的结果一致即T2回滚活提交前后T1查询的结果一致 幻读可以把T2的update换成insert语句会发现第二次事务T1读取的数据多了几行
serializable串行化 该隔离模式下执行的事务在对某表进行操作期间禁止其他所有事务对该表进行任何操作
如果强行操作也会报错和可重复读那个错误一致,因为serializable用的相对比较少这里就不做演示了。同学们理解了就好。
事务的保存点回滚点 回滚点表示的就是使事务回滚到指定回滚点
语法: savepoint 节点名称 ; 注意保存点只允许搭配rollback回滚来使用不能和commit一起使用
已知表t_student存在其数据如下第一次查询就是全量数据
代码举例如下 #禁用自动提交事务
set autocommit 0;#开启事务
start transaction;#删除id为2的记录
delete from t_stu where id 2;#设置保存点名为AA
savepoint AA;#删除id为3的记录
delete from t_stu where id 3;#回滚到AA保存点处
rollback to AA;运行结果如下
可以看到user_id为3的数据被删除了而user_id为4的还在就是因为事务回滚到了AA处所以user_id为3的那条记录被回滚掉了。
原文链接https://blog.csdn.net/qq_56880706/article/details/122653735本文是在作业的基础上自己进行了操作并赋上了自己的心德如有不正确支出望各位大佬评论尽快修改避免耽误其他同学