数据库事务相关记录

数据库事务的特性    

    1.原子性 A  事务是不可分割的最小单元,事务内的操作要么全部操作,要么全部不操作,不能只做一部分。
    2.一致性 C  事务执行前数据库数据的正确状态要保持到事务执行后,和原子性的操作有异曲同工之妙。
    3.隔离性 I  所谓隔离性就是事务之间的隔离性,一个事物内部的操作是不能被其他事物影响,通过事物的隔离界别来完成,没有隔离性就一定会有下面的四种问题。
    4.持久性 D  事务一旦提交,数据就永久性被修改了。
多线程操作事务,如果不加任何限制,会出现如下的问题:
    1.丢失更新

    丢失更新更为两种情况
    1.1 第一类丢失更新
        也称作回滚丢失,Lost Update。
        可以简单的理解成:                        
        事物A和事物B同时读取数据X=100,A进行了X=X+100的操作,然后提交事务。B进行了X=X-100的操作,然后又事务回滚了,
        回滚后按照正常思维X回到原来读到的数据1000,
        这就把A的提交操作覆盖了,这种就是第一类丢失跟新,所有数据的任何隔离界别都默认解决了这种情况。
        即:即便此时B回滚,数据也还是A提交之后的200,而不会变成100.
    1.2 第二类丢失更新
        也称作覆盖更新或者两次更新的问题,Second lost update
        可接简单的理解成:
        事物A和事物B同时都获取了数据X=100,事物A对X进行+100的修改,然后提交,结果是200.但是事物B对X进行了加200操作,最后提交结果是300.
        A和B谁最后提交,那么X的结果就是谁,反而早提交的事物就丢失了此次更新。
    2.脏数据
        所谓脏数据,是指A事务正在访问数据库,并对数据进行了修改,但是还没提交,这时候事务B也访问了这个被修改的数据,
        因为A还没提交,所以B读到的就是脏数据,这个数据有可能是不正确的。
        PS:正常情况下,脏数据在Mysql/Oracle的默认级别中是不会出现的,是能是同一个事务内的操作可以互相读取这样的数据。
    3.不可重复读
        所谓不可重复读可以简单理解为:事物A和事物B同时获取数据X=100,然后事物B修改X=X+100然后提交,在事物A中如果重新读取X会发现已经变成200了,
        和第一次读取的X值不一样。区别于脏读的点在于事物B提交后事物A再读取时,无法获取第一次查询的数据,估称之为不可重复读。
    4.幻读
        所谓幻读,可以简单理解成:事物A在读取数据符合某一条件的过程中事物B又提交了符合条件的数据,事物A就会出现两次读的数据不一样,可能少可能多。
        和不可重复很类似,都是事物A读取的数据被事物B调整了,区别在于操作上不同,不可重复读是update,幻读是insert和delete,
        但是如果数据库隔离级别设置的很低,从某种意义上说幻读也是包括不可重复读的。
     
    注意点:
        以上几种情况,有一个前提,不管事务A还是事务B,出现这问题都是在一个事务内部,及事务还没提交的时候。
        例如:关于不可重复读,事务A读取的数据第一次显示100,第二次一刷新突然变成200了,这算不算不可重复读?
        这肯定不算,这是两次完整的操作,不涉及这样的问题。这些问题的操作细节比实际开发中的业务问题要细致的多。

以上四种情况是多线程操作数据库时候直观上不可避免会出现的问题,针对这些问题,我们引入数据可隔离级别、共享锁、排它锁、互斥锁、乐观锁、悲观锁等等。还要搞清楚什么情况下开启事物,例如:在SpringBoot的开发中,如果单单是查询也开启了事物有什么影响?不开启仅仅依靠数据可的默认隔离界别又有什么区别?
下面我们来一一了解和记录。


数据库隔离级别

   1.未提交读  read_uncommited
        不隔离事务,不安全,只能解决第一类丢失问题,其他问题都不能解决,一般情况下我们都是不用的,除非不涉及修改操作。对应的是一级封锁协议。
        【X锁】
    2.提交读    read_committed
        事务A只能读到事务B已经提交的数据,没提交的数据看不到,这种情况可以限制脏读和第一类丢失问题,其他问题不能解决。oracle默认情况下是提交读的隔离级别。
        也就是说事务在准备读取数据X的时候,会给他加一个共享锁,对应的是二级加锁协议。
        【X锁+临时S锁】
    3.可重复读  repeatable read
        显而易见,可重复读可以解决不可重复读的问题,但是无法解决幻读的情况。
        他指的是:保证同一个事物中先后执行的多次查询结果一致。也就是说,某个事务读取数据X后,在该事物结束事务前,任何其他事务都不能修改这个数据。
        对应的也是数据库的三级加锁协议。
        【X锁+持续S锁】
    4.序列化    serializable
        最高级别,不允许事务并发执行。

   1.乐观锁
        所谓乐观锁,可以简单理解为:所有事物都可以读写,在写的时候会判断下数据是否发生变化了,
        即:是否出现了不可重复读的情况,如果出现,就回滚事务。数据更新之前使用
        旧数据校验一下,例如:update tablea set dl='2' where dl='3'(同样的,我们也可以使用独立的时间戳字段区分不同版本来完成乐观锁)
    2.悲观锁
        共享锁(S锁)
        被加了S锁的数据,可以被其他事物读,但是不能写,对于添加S锁的事务本身,也是只能读不可写,且其他事物也不能给数据再添加X锁。
        排它锁(X锁)
        被加了X锁的数据,只能被添加锁的事物读写,其他事务不能操作,也不能再添加锁。


关于封锁协议

    1.一级封锁协议
        事务T在修改数据R之前必须先对其进行加X锁,直到事务T结束才释放。
    2.二级封锁协议
        在一级封锁协议的基础上增加事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。 临时S锁
    3.三级封锁协议
        在一级封锁协议的基础上增加事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。持久S锁
    注意点:
        乍一看,直接使用一级封锁协议完全使用X锁不就好了?
        其实有个概念要理清楚,那就是一级封锁协议添加X锁后,其事务在操作的时候,可以不加锁了,不加锁常规操作就能直接查询,
        所以不可避免的出现脏读、不可重复读这些问题。二级、三级封锁协议的前提是事务操作前要加S锁,这是关键,问题是加了X锁的数据就不能加S锁了,所以限制性比较高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值