数据库乐观锁和悲观锁的理解和实现。

悲观锁(Pessimistic Locking):       

       悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自 外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。

       悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能 真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系 统不会修改数据)。

       通俗理解:一段数据在被A以悲观锁的形式访问(select * from  card_record where status ="03' for update),那么在这个访问没有commit或者事务结束之前,这些 status ="03'的数据是无法被修改的。这条 sql 语句锁定了 card_record 表中所有符合检索条件( status ="03' )的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。 需要注意的是for update要放到mysql的事务中,即begin和commit中,否则不起作用。

       悲观锁有两种:读锁和写锁。上面的操作属于写锁的操作,A上了锁,那么别人就不可以再上锁了,有锁的人可以对数据进行读写操作。而读锁相当于共享锁,开启事务后,A上了共享锁,那么其他人也可以上共享锁。大家都可以读这些数据,但是都不能修改。

       悲观的理解,别人在我读写数据的时候会进行更改,那么我就上锁,在我读写数据的时候不允许别人更改我正在操作的数据。

乐观锁(Optimistic Locking):        

         由于悲观锁在频繁依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销。而乐观锁机制避免了长事务中的数据库加锁开销,大大提升了大并发量下的系统整体性能表现。

          乐观锁,大多是基于数据版本(Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

         通俗的讲,A和B都在对一个版本为1的数据进行修改,在事务提交之前,这段数据的版本一直是1,那么下次提交的人会把这段数据的版本变为2。如果A在B之前提交了,那么这段数据的版本变为2,之后B提交了数据,由于B拿到数据的时候版本是1,那么加一后,预估版本也是2,但是提交完发现,现在的版本已经是2了,所以B的修改和提交是无效的。

          需要注意的是,乐观锁机制往往基于系统中的数据存储逻辑,因此也具备一定的局限性,如在上例中,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户对数据的操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。在 系统设计阶段,我们应该充分考虑到这些情况出现的可能性,并进行相应调整(如将乐观锁策略在数据库存储过程中实现,对外只开放基于此存储过程的数据更新途 径,而不是将数据库表直接对外公开)。

          乐观的理解,在我读写数据的时候,没人对这段数据进行更改,所以可以随意更改数据,只是commit的时候可能会出现版本问题。

         悲观锁,前提是,一定会有并发抢占资源,强行独占资源,在整个数据处理过程中,将数据处于锁定状态。

         乐观锁,前提是,不会发生并发抢占资源,只有在提交操作的时候检查是否违反数据完整性。只能防止脏读后数据的提交,不能解决脏读。

猜你喜欢

转载自blog.csdn.net/lishuo1031/article/details/81510332
今日推荐