事务隔离级别以及悲观锁和乐观锁

数据库的事务等级、数据库的锁

一篇事务写的相当好的博文

数据库事务并发的时候在不同的情况就会出现不同的问题,针对问题的不同,大致分为下面四类:

● 丢失更新(Update Lost): a.第一类丢失更新:这种情况的发生时因为回滚的原因,所以也可以叫回滚丢失。当两个事务同时更新一个字段,两个事务都读到Count字段为100,事务一对它进行更新提交,Count=100+1=101,事务二因为一些原因需要回滚,事务二将Count还原到最初读到的值100,这种情况下事务一的更新就丢失了。由于回滚丢失更新。 b.第二类丢失更新:这种情况是因为更新的时候被其他事务覆盖了,所以也可以叫覆盖丢失。当两个事务同时更新字段Count,都读取到了100这个初始值,事务一先更新成功并提交,Count=100+1=101,事务随后更新成功并提交,Count=100+1=101,由于事务读到的Count是100,所以导致事务一的更新丢失。由于被覆盖丢失更新。● 脏读(Dirty Read):这种异常是因为一个事务读取了另一个事务更新还未提交的值。当事务一更新了Count字段,Count = 100+1=101,但是还没有提交,事务二这时读取到Count的值是101,然后事务一回滚了,导致事务二读到了一个错误的值。

● 不可重复读(Non-Repeatable Read):这种异常是因为对同一行数据执行了多次查询,却得到了不同的结果。每次读到的数据可能相同,也可能不同(因为别的事务操作修改了数据)。

● 幻读(phantom Read):幻读的概念注重的是记录的数量,比如两个查询的返回的记录条数不一致,就比如生活中人出现了幻觉,看错了一样。和不可重复有些类似。

数据库的隔离级别:

  • 读未提交(Read Uncommitted):该隔离级别是指一个事务的更新语句没有提交,但是别人的事务仍然可以读到这个改变。这个事务基本没有起到作用,基本不会使用。

  • 读提交(Read Committed):该隔离级别指的是一个事务只能看到别的事务已经提交的更新,看不到未提交的更新,解决了第一类更新丢失和脏读的情况。

  • 可重复读(Repeatable Read):该隔离级别是一个事务进行多次对记录的查询,得到的结果是样的,但不保证记录条数一样。只要有别的事务在读写行数据,就禁止事务写。

  • 串行化(Serializable): 一个事务执行的时候不允许别的事务并发执行,完全串行化的读,这是事务隔离的最高级别,效率太低,一般不会用。

    事务隔离级别回滚覆盖脏读不可重复读提交覆盖幻读
    读未提交X会发生会发生会发生会发生
    读提交XX会发生会发生会发生
    可重复读XXXX会发生
    串行化XXXXX

数据库锁分类

主要是分为两类:1.悲观锁 2.乐观锁 。 悲观锁一般指的是数据库锁机制,乐观锁一般指的是用户自己实现的锁机制,比如Hibernate实现的乐观锁。

悲观锁: 从数据库的角度来说,它认为数据库的数据是会被修改的,所以整个数据出来过程中需要对数据加锁。数据库中的行锁、表锁无论读写锁都是悲观锁。

悲观锁按在数据库中定义划分:

  • 共享锁(S):也称读锁,事务A对对象T加S锁,其他事物也只能对T加S锁,多个事务可以同时读,但不能有写操作,直到A释放S锁。

  • 排它锁(X):也称写锁,事务A对对象T加X锁,其他事务不能对T加任何锁,只有事务A释放锁。

  • 更新所(U):也称为意向锁,用来表示事务打算对它加X锁。它允许其他事务读,但是不允许加其他锁类型。它的作用是防止死锁。防止两个事务同时对对象T尝试加X锁,发生死锁。只允许一个事务拿到U锁。乐观锁:认为数据被修改的机会不大,所以不去加锁。但是在更新的时候会判断当前的数据有没有修改,需要用户来实现相关的锁机制。乐观锁的存在主要是方便与读操作远远多于写操作的时候,大多数是读取,这时候一个写操作就会阻塞多数读操作,造成效率低下,降低吞吐量。

乐观锁的几种实现方式:

  • 版本号(Version):就是给数据添加一个版本标识,在表中添加一个Version字段,每次更新将这个字段加1,读取数据的时候可以忽略,更新的时候需要比较Version。如果读取的两次没有差别就直接更新。如果现在的Version对不上,那么就说明数据发生了改变。这时候就无法更新,由用户决定如何处理。这个还有一个点,判断Version和更新操作需要作为一个原子单元进行执行,否则当你得出可以更新,做出更新之前有别的事务修改了数据,这个时候再更新会覆盖前一个事务做的更新。因为有了Version字段,当修改时,添加where Version = ’你读到的version‘ and XXX= ’xxx‘ 进行修改记录。不会覆盖之前事务做的更新。

  • 时间戳(TimeStamp):和版本号差不多,用时间来判断。

  • 待更新字段:不需要额外字段。直接用数据字段当版本控制信息。假设有个字段Count需要修改,更新的时候会比较数据库中的Count是不是我之前读到的值。如果是我就进行更新,否则失败。

  • 所有字段:和待更新字段类似。只是使用所有字段做版本控制信息。只有所有字段没变化才进行更新,否则失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值