关于事务:事务原理了解一下
1、聊聊事务原理一句话来说,要么胜利,要么失败,不能有两头态 1.1、回顾一下ACIDAtomic:原子性,就是一堆SQL,要么一起胜利,要么都别执行,不容许某个SQL胜利了,某个SQL失败了,这就是扯淡么Consistency:一致性,这个是针对数据一致性来说的,就是一组SQL执行之前,数据必须是精确的,执行之后,数据也必须是精确的。别搞了半天,执行完了SQL,后果SQL对应的数据批改没给你执行,这不是坑爹么Isolation:隔离性,这个就是说多个事务在跑的时候不能相互烦扰,别事务A操作个数据,弄到一半儿还没弄好呢,后果事务B来改了这个数据,导致事务A的操作出错了,那不就搞笑了么Durability:持久性,事务胜利了,就必须永恒对数据的批改是无效的,别过了一会儿数据本人没了,不见了,那就好玩儿了1.2、陈词滥调的事务隔离级别读未提交(Read Uncommitted):这个很坑爹,就是说某个事务还没提交的时候,批改的数据,就让别的事务给读到了,这就恶心了,很容易导致出错的。这个也叫做脏读读已提交(Read Committed)又叫做不可反复读:这个比下面那个略微好一点,然而一样比拟难堪,就是说事务A在跑的时候, 先查问了一个数据是值1,而后过了段时间,事务B把那个数据给批改了一下还提交了,此时事务A再次查问这个数据就成了值2了,这是读了人家事务提交的数据啊,所以是读已提交。这个也叫做不可反复读,就是所谓的一个事务内对一个数据两次读,可能会读到不一样的值可反复读(Read Repeatable):这个就是比下面那个再好点儿,就是说事务A在执行过程中,对某个数据的值,无论读多少次都是值1;哪怕这个过程中事务B批改了数据的值还提交了,然而事务A读到的还是本人事务开始时这个数据的值串行化:幻读,不可反复读和可反复读都是针对两个事务同时对某条数据在批改,然而幻读针对的是插入,比方某个事务把所有行的某个字段都批改为了2,后果另外一个事务插入了一条数据,那个字段的值是1,而后就难堪了。第一个事务会忽然发现多进去一条数据,那个数据的字段是1。如果要解决幻读,就须要应用串行化级别的隔离级别,所有事务都串行起来,不容许多个事务并行操作2、MySQL的事务隔离级别分析一下2.1、InnoDB存储引擎架构设计 2.2、MySQL是怎么实现RR事务隔离的2.2.1、Redo Log日志理解一下 2.2.2、MVC Undo Log日志链条事务A,插入了一条数据接着有一个事务B跑来批改了一下这条数据接着假如事务C又来批改了一下这个值为C2.2.3、 MySQL RR readview + undo log日志链首先假如有一条数据是事务id=50的一个事务插入,之后有事务A和事务B同时在运行事务A发动一个查问,他就是第一次查问就会生成一个ReadView,此时ReadView里的creator_trx_id是60,min_trx_id是60,max_trx_id=71,m_ids=[60,70]这个时候事务A基于这个ReadView去查问这条数据,会发现这条数据的trx_id=50,是小于ReadView里的min_trx_id的,阐明他发动查问之前,早就有事务插入这条数据了还提交了所以此时能够查到这条原始数据接着事务B此时更新了这条数据的值为B,此时会批改trx_id=70,同时生成一个undo log,而且此时事务B还提交了,也就是说事务B曾经完结了这个时候有一个问题,ReadView中的m_ids此时还会是60和70吗?那是必然的,因为ReadView一旦生成就不会扭转了,这个时候尽管事务B曾经完结了,然而事务A的ReadView里,还是会有60和70两个事务id,意思就是说,你在事务A开启的时候,事务B过后是在运行的那好,接着此时事务A去查问这条数据的值,他会诧异的发现此时数据的trx_id是70了,70一方面是在ReadView的min_trx_id和max_trx_id的范畴区间的,同时还在m_ids列表中阐明起码是事务A开启查问的时候,id=70的这个事务B还是在运行的,而后由这个事务B更新了这条数据,此时事务A是不能查问到事务B的这个值的,因而这个时候只能顺着指针往历史版本链条下来找接着事务顺着指针找到上面一条数据,trx_id为50,是小于ReadView的min_trx_id的,阐明在他开启查找之前,就曾经提交这个事务了,所以事务A是能够查问到这个值的,此时事务A查到的是原始值你事务A屡次读同一个数据,每次读到的都是一样的值,除非是他本人批改了值,否则读到的都是一样的值,不论别的事务如何批改数据,事务A的ReadView始终是不变的,他基于这个ReadView始终看到的值是一样的接着此时事务A再次查问,此时发现符合条件有2条数据,一条是原始值的那个数据,一条是事务C插入的那条数据,然而事务C插入的那条数据的trx_id是80,这个80是大于本人的ReadView的max_trx_id的,阐明是本人发动查问之后,这个事务才启动的,所以此时这条数据是不能查问的,所以MySQL RR防止了幻读3、XA标准理解一下X/Open的组织定义了分布式事务的模型,这外面有几个角色,就是AP(Application,应用程序),TM(Transaction Manager,事务管理器),RM(Resource Manager,资源管理器),CRM(Communication Resource Manager,通信资源管理器)TM的话就是一个在零碎里嵌入的一个专门治理横跨多个数据库的事务的一个组件,RM的话说白了就是数据库(比方MySQL),CRM能够是消息中间件(然而也能够不必这个货色) 那么XA是啥呢?说白了,就是定义好的那个TM与RM之间的接口标准,就是治理分布式事务的那个组件跟各个数据库之间通信的一个接口 这个XA仅仅是个标准,具体的实现是数据库产商来提供的,比如说MySQL就会提供XA标准的接口函数和类库实现 JTA(Java Transaction API),是J2EE的编程接口标准,它是XA协定的JAVA实现,例如Atomikos, bitronix都提供了jar包形式的JTA实现框架。这样咱们就可能在Tomcat或者Jetty之类的服务器上运行应用JTA实现事务的利用零碎,个别是单机跨多库状况下,然而在微服务的明天,个别都是一个服务一个库,个别都不会这么干了 3.1、2PC是啥?X/Open组织定义的一套分布式事务的模型,还是比拟虚的,还没方法落地,而且XA接口标准也是一个比拟务实的一个货色,还是没法落地的2PC说白了就是基于XA标准搞的一套分布式事务的实践,也能够叫做一套标准,或者是协定 毛病:1、同步阻塞:在阶段一里执行prepare操作会占用资源,始终到整个分布式事务实现,才会开释资源,这个过程中,如果有其他人要拜访这个资源,就会被阻塞住2、单点故障:TM是个单点,一旦挂掉就完蛋了3、事务状态失落:即便把TM做成一个双机热备的,一个TM挂了主动选举其余的TM进去,然而如果TM挂掉的同时,接管到commit音讯的某个库也挂了,此时即便从新选举了其余的TM,压根儿不晓得这个分布式事务以后的状态,因为不晓得哪个库接管过commit音讯,那个接管过commit音讯的库也挂了4、脑裂问题:在阶段二中,如果产生了脑裂问题,那么就会导致某些数据库没有接管到commit音讯,那就完蛋了,有些库收到了commit音讯,后果有些库没有收到,这咋整呢,那必定完蛋了 3.1、3PC是啥?如果人家TM在DoCommit阶段发送了abort音讯给各个库,后果因为脑裂问题,某个库没接管到abort音讯,本人还执行了commit操作,不是也不对么 4、TCC是个什么原理(柔性事务)try、confirm和cancel 4.1、容许空回滚事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会呈现因为丢包而导致的网络超时,此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,而 Cancel 操作调用未呈现超时TCC 服务在未收到 Try 申请的状况下收到 Cancel 申请,这种场景被称为空回滚;空回滚在生产环境经常出现,用户在实现TCC服务时,应容许容许空回滚的执行,即收到空回滚时返回胜利 4.2、防悬挂管制事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会呈现因网络拥挤而导致的超时,此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,Cancel 调用未超时;在此之后,拥挤在网络上的一阶段 Try 数据包被 TCC 服务收到,呈现了二阶段 Cancel 申请比一阶段 Try 申请先执行的状况,此 TCC 服务在执行完到的 Try 之后,将永远不会再收到二阶段的 Confirm 或者 Cancel ,造成 TCC 服务悬挂。用户在实现 TCC 服务时,要容许空回滚,然而要拒绝执行空回滚之后 Try 申请,要避免出现悬挂 ...