二、Mysql事务(必会知识点)

1.1 什么是事务?

       事务可以理解成是一种约束, 假如你要执行三条sql语句, 这三条语句全部执行成功才可以达到你的目的, 但是此时其中一条sql失败了或者因为某些其他原因导致没有执行,那么最终的执行结果就不是你原本想要的结果,所以我们就需要事务来约束捆绑这三条语句,要么三条sql都执行成功, 要么三条sql都执行失败,这就是事务。

       如果你没理解,那换个方式说。假如你去吃饭,你需要先掏钱、拿筷子、拿米饭(相当于三条sql语句)你才可以正常进行吃饭动作, 但是如果此时没有米饭了(其中一条执行失败),那么你怎么去吃饭呢? 这时是不是就和你原本想要的吃饭动作不一样了? PS(你总不能吃筷子吧...), 然后你去找店家把钱要了回来(相当于第一条sql回滚), 把米饭放回原位(相当于第二条sql回滚),所以你干脆就不吃了,要么钱,筷子,米饭都有你进行吃饭动作, 要么你不吃走人, 这就叫事务,  这样是不是可以容易帮助你理解什么是事务了?  

1.2 事务的四大特性

       上面我们明白了什么是事务也认识到了事务的作用,但是光知道什么是事务是远远不够的, 你可以想象一下, 就按我们上边举得例子来讲,你去吃饭的时候发现没有米饭了,你这时候要找店家退钱对不对, 但是!!!店家这个时候跑了,是的,你没听错,带着你的钱跑了!(相当于系统崩溃)这时候怎么办,你饭也没吃, 钱也没了。。。 

1.2.1 原子性

        一个事务必须被看作是一个整体,或者叫做工作单元,整个事务的操作要么全部成功, 要么全部失败回滚。

1.2.3 一致性

        数据库必须从一个一致性状态转换到另一个一致性状态。 这句话有点不太好理解, 我们还拿上边的例子举例, 你去吃饭了对不对, 但是注意, 你为了防止TA逃跑,你不给TA钱, 你发现筷子, 米饭,都成功的拿到了(相当于其他的sql语句执行成功),这时你才会把钱给他(相当于提交事务)。 如果店家跑了(系统崩溃了),这时你也没有损失,因为你的钱没有给他(相当于回滚事务) 

1.2.3 隔离性

        事务和事务之间是不可见的,也就是一个事务提交之前, 其他事务是看不见这个这个事务的操作的。 举个例子就是你吃饭的时候拿走了最后的一双筷子,但是你还没有付钱(没有提交事务),这时进来了另外一个顾客,他是不知道你把最后一双筷子拿走了的。PS:这里你是不是有了一些疑问了?没关系,我们后面说,现在只需要知道隔离性是什么就可以,如果这里你没有什么疑问, 那么证明你还没有理解事务。。。

1.2.4 持久性

        只要提交了事务,那么事务内的sql语句就会持久化到数据库中。 这里有个一定要知道的知识点,这里的持久化不是百分百会持久化到数据库成功的,也就是说即使你的事务提交了,也不一定会保存到数据库中,说个场景, 你的事务提交了,在持久化数据库的时候,系统崩了,这批数据依旧会丢失

1.2.5 四大特性总结

        这四大特性,专业名词叫ACID,分别代表四个特性,A(原子性atomicity), C(一致性consistency),I(隔离性isllation),D(持久性durability)。

        四大特性就像锁粒度(不知道锁粒度的看我第一章文章http://t.csdn.cn/C77sZ)一样,会额外的增加系统消耗,一个实现了ACID的数据库系统,要给TA更高更优的cpu,更大的内存空间和磁盘容量,而在我们的应用业务系统中要实现这一套ACID也很困难, 所幸我们Mysql的存储引擎会自带一些特性(每个不同的存储引擎自身所携带的特性是不同的),我们日常开发中可以根据实际的业务场景来选择合适的存储引擎来获取更好的系统性能,即使选用的存储引擎不持支事务,我们也可以自己来使用一些其他方式实现

1.3 隔离级别

        隔离级别就是规定在一个事务中所做的修改,那些在事务内和事务间是可见的,那些是不可见的。较低级别的隔离性可以支持更高的并发,系统开销也会相应更低。

        隔离级别同样也有四个

1.3.1 未提交读(READ UNCOMMITTED)

        在这个级别中,即使一个事务没有提交,其他事务也是可以看见这个事务做出的修改的。事务可以读取到其他事务没有提交的数据,被称为脏读。看到这里相比你也意识到TA的问题了,会导致数据混乱,而且性能也没有比其他隔离级别好太多。在日常开发中,这个级别一般不会用到

1.3.2 提交读(READ COMMITTEN)

        大多数数据库采用的默认隔离级别都是提交读,注意哈,我们的Mysql不是(那些数据库默认是这个级别大家可以自己查资料),这个隔离级别满足我们前面说的隔离性,一个事务只能看到其他事务提交后的数据,事务间的数据不会共享,被称为不可重复读。因为如果你执行两次相同的操作, 读取到数据可能是不一样的(因为在你执行两次的时候有可能其他事务提交了修改呀,所以你第二次读取到的数据有可能是其他事务提交后的数据)

1.3.3 可重复读(REPEATABLE READ)

        这个隔离级别解决了脏读的问题,保证在同一个事务中,多次读取数据时一致的,但是理论中,无法解决另一个问题, 就是幻读。 什么是幻读, 幻读就是假如有一个事务A正在查询数据,但是这个时候另一个事务B在这个数据范围内插入了一条新的数据,当A进行第二次数据查询时就会查到这条新的数据,总结来讲就是同一个事务中后一次查询会查到前一次查询没有查到的数据,在InnonDB和XtraDb存储引擎中通过多版本并发控制解决了幻读的问题(后面说)。 注意,Mysql默认隔离级别就是可重复读       

1.3.4 可串行化(SERIALIZABLE)

        可串行话时隔离级别最高的,TA强制事务串行化执行,避免了幻读问题。简单说就是TA会在读取的每一行数据上强制加锁,但是同时也会导致大量的超时和抢锁的情况,所以我们日常开发很少会用到这个隔离级别,除非时那种必须确保数据一致性而且可以接受没有并发的情况下。

 1.4 死锁

        死锁就是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,导致循环请求的情况。多个事务以不同的顺序锁定资源或者同时锁定同一个资源时就会发生死锁。举个例子, 现在有两个人A和B(事务A和事务B),同时去食堂打饭,A拿到了勺子,B拿到了筷子,这时A用完了勺子需要用筷子, B用完了筷子要用勺子, 但是A要用完筷子才可以归还勺子,B要用完勺子才可以归还筷子, 这时A和B两个都在等待对方归还各自需要的东西,就会发生一直等待下去的情况,这就叫死锁。

         为了解决这个问题,数据库系统实现了各种死锁检测和死锁超时机制,越复杂的系统越能检测到死锁的循环依赖,并返回一个错误信息提示。还有一个解决办法就是设定锁等待时间,当等待锁时间超过设定的时间就放弃锁请求,这种方式一般不太会用到,因为如果你放弃了意味着你本次操作就失败了,对于用户来讲不太友好。InnonDB(存储引擎)的解决方法是将持有最少行级排他锁(不清楚排他锁概念的看第一章文章http://t.csdn.cn/C77sZ))的事务进行回滚。这种处理方式也叫做死锁回滚算法。

        锁的行为和顺序是和存储引擎有关系的,已同样的顺序执行语句,有些存储引擎会死锁, 有些则不会。死锁产生的原因有些是因为真正的数据冲突, 就像前边举得例子一样, 有些则是因为存储引擎的实现方式引起的。

        死锁产生后,只有部分或者是整个事务回滚才可以打破死锁,对于业务性系统而言,这种情况是无法避免的,所以我们可以在程序中进行处理,大部分情况下回滚重新执行即可。

1.5 事务日志 

        什么是事务日志? 事务日志可以理解为一种记录事务操作的机制, 也就是说你的事务提交或者是回滚,都会记录下来存储在磁盘中。

        事务日志有啥好处? 为啥要用事务日志? 前面我们说过,在我们执行sql语句时,是会有事务产生的,在事务提交或者回滚的时候, 是会占用IO来进行磁盘操作的,如果有多个事务意味着同时会有多个零零散散的磁盘IO操作。这个时候就体现出事务日志的好处了,存储引擎修改数据的时候修改内存拷贝数据, 事务日志是占用磁盘上一块固定区域的顺序IO,这样每个事务提交或回滚都会按照顺序记录在事务日志中, 之后在由服务器来执行事务日志中的记录更新数据。 

1.6 Mysql中的事务

        Mysql提供了两种事务性存储引擎,InnonDB和NDB Cluster (先知道有这两个, 后边我们说到存储引擎的时候细聊)

 自动提交(AUTOCOMMIT)

        Mysql默认采用自动提交模式,也就是说你的sql语句在不需要手写commit或者rollback命令的情况下,mysql也会当作一个事务来进行提交或者回滚。你也可以手动设置是否开启该模式(命令自己查资料哈)。

注意: 尽量不要同时使用不同的存储引擎,例如你同时使用了InnonDB和MyISAM, 当InnonDB需要回滚时, 你会发现MyISAM里的数据依旧发生了改变,这是因为MyISAM不是一个事务型存储引擎,所以对他来讲数据依旧会提交

1.7 多版本并发控制

        多版本并发控制又叫做MVCC, 简单理解TA就是行级锁的一个升级,但是TA又在很多情况下避免了加锁操作来提升并发能力。Mysql, Oracle等其他数据库也都实现了MVCC,不过每个数据库都有自己的实现方式,业界内还没有一种统一规范的实现标准。

        MVCC是通过保存数据在某个时间点的快照实现的。也就是说相同的时间,每个事务看到的数据都是一样的,不同的时间,多个时间看到的数据有可能不同。

        我们MVCC不同的存储引擎有不同的实现方式,典型的就是乐观并发控制和悲观并发控制,下面我们用我们比较常用的InnonDB举例

        

 

        有了这两个版本号,大多数读操作都不需要加锁了,提升了系统性能,但是同时要多维护两个字段数据也会相信增加服务器资源

        注意: MVCC只在重复读和提交读生效, 因为未提交读总是读取最新的数据,而串行化会对所有数据加锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值