Transaction事务管理

    我们在实际业务场景中,经常会遇到数据频繁修改读取的问题。在同一时刻,不同的业务逻辑对同一个表数据进行修改,这种冲突很可能造成数据不可挽回的错乱,所以我们需要用事务来对数据进行管理。

    事务(Transaction):构成单一逻辑工作单元的操作集合
        DBMS中的用户程序,DBMS外的可执行程序,对数据库的读/写操作序列

    事务的特性-ACID:
        原子性(Atomicity):事务中的操作,要么全做成,要么都不做。事务是不可拆分的,事务必须以 Commit/Rollback 结束。
        一致性(Consistency):单独运行的事务,必须保证保持数据库的一致状态,从一个一致状态迁移到另一个一致状态,与原子性相关。
        隔离性(Isolation):多个并发事务之间不能相互干扰,并发不影响事务的执行。

        持久性(Durability):一旦事务成功完成(Commit),它对数据库的更新应该是持久的。即使在写入磁盘之前,系统发生故障,在下次启动之后,也应保障数据更新的有效。

    事务隔离原则(事务并发情境中):

       数据库事务的隔离级别有4个,由低到高依次为Read uncommitted(读未提交) 、Read committed (读提交) 、Repeatable read(重复读)  、Serializable(序列化)  ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。

        采用银行转账这一业务场景进行距离。

        Read uncommitted(读未提交): 

            一个事务可以读取另一个未提交事务的数据:又到了发工资的时间了,老板给员工A的工资卡中打入7000元(实际员工A当月工资为5000元),但此事务并未提交。此时,员工A查询工资卡工资发现7000元工资到账,很开心。这时候,老板发现工资金额转入错误,立即回滚了这个事务,将员工A工资改为5000元,并进行了提交

           事实上员工A这个月的工资还是5000元,但是员工A看到的是7000元。他看到的是老板还没提交事务时的数据。这就是脏读那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。

        Read committed (读提交) :

            一个事务要等另一个事务提交后才能读取数据:员工A兴奋地拿着刚到手的工资想去商场进行一番购物,当他购物完成要进行结账时(事务A开启),银行快捷支付系统检测到该工资卡中余额为5000元。就在这时,员工A的妻子要把员工A工资卡中的余额全部转出到她的账户中,并进行了提交。当系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。

            若有事务对数据进行更新(Update)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。如何解决不可重复读问题?Repeatable read !

        Repeatable read(重复读):

            在开始读取数据(事务开启)时,不再允许修改操作:上述例子中,员工A开始进行付款时(事务开启,不允许其他事务的Update操作)。此时,二次检测余额,即可进行付款操作。

            重复读可以解决不可重复读问题。不可重复读对应的是修改,即Update操作。但是可能还会有幻读问题。因为幻读问题对应的是插入Insert操作,而不是Update操作。

            此时,出现了新的一个场景:员工A某一天去消费,花了2000元,然后他的妻子去查看他今天的消费记录(消费记录事务开启),看到确实是花了2000元,就在这个时候,员工A花了500元买了一件衣服,即消费记录中Insert了一条消费记录,并进行了提交。当妻子打印员工A的消费记录清单时(消费记录事务提交),发现花了2500元,感觉自己似乎出现了幻觉,这就是幻读。那么,要解决幻读?Serializable!

        Serializable(序列化) :

            最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

        注:大多数数据库默认的事务隔离级别是Read committed,比如Sql Server , Oracle。但是,Mysql的默认隔离级别是Repeatable read

    总结下事务中的常见问题:

        脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

        不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)

        幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

猜你喜欢

转载自blog.csdn.net/nerver_77/article/details/79876040