Spring Data JPA中使用事务和锁

学生选课系统小案例:https://blog.csdn.net/zc_ad/article/details/83578487

Spring Data JPA 之 for update

 

Entity Locking

In the area of concurrency control, the JPA specification supports optimistic and pessimistic locking.

public void lock(Object entity, LockModeType mode);

This method locks the given entity using the named mode. The javax.persistence.LockModeType enum defines eight modes:

  • OPTIMISTIC: Optimistic locking.

  • OPTIMISTIC_FORCE_INCREMENT: Optimistic locking. When a transaction is committed, the entity's version column will be incremented even if the entity's state did not change in the transaction.

  • PESSIMISTIC_READ: Pessimistic locking. Other transactions may concurrently read the entity, but cannot concurrently update it.

  • PESSIMISTIC_WRITE: Pessimistic locking. Other transactions cannot concurrently read or write the entity.

  • PESSIMISTIC_FORCE_INCREMENT: Pessimistic locking. Other transactions cannot concurrently read or write the entity. When a transaction is committed, the entity's version column will be incremented even if the entity's state did not change in the transaction.

  • READ: A synonym for OPTIMISTIC.

  • WRITE: A synonym for OPTIMISTIC_FORCE_INCREMENT.

  • NONE: No locking is performed.

Entities can also be locked at the time when entity state gets loaded from the datastore. This is achieved by supplying a lock mode to the respective versions of find and refresh methods. If an entity state is to be loaded by a query, a lock mode can be passed to the Query.setLockMode and TypedQuery.setLockMode methods.

public LockModeType getLockMode(Object entity);

Returns the lock mode currently held by the given entity.

Note

  • OpenJPA differentiates between PESSIMISTIC_READ and PESSIMISTIC_WRITE lock modes only with DB2 databases. While running with other databases, there is no distinction between these two modes because PESSIMISTIC_READ lock mode is upgraded to PESSIMISTIC_WRITE.

  • OpenJPA has additional APIs for controlling entity locking. See Section 3, “ Object Locking ” in the Reference Guide for details.

link: https://openjpa.apache.org/builds/2.2.2/apache-openjpa/docs/jpa_overview_em_locking.html

 

JPA使用乐观锁应对高并发

高并发系统的挑战
在部署分布式系统时,我们通常把多个微服务部署在内网集群中,再用API网关聚合起来对外提供。为了做负载均衡,通常会对每个微服务都启动多个运行实例,通过注册中心去调用。

那么问题来了,因为有多个实例运行都是同一个应用,虽然微服务网关会把每一个请求只转发给一个实例,但当面对高并发时,但它们仍然可能同时操作同一个数据库表,这会不会引发什么问题呢?

悲观锁的问题
比如电商中常见的商品秒杀系统,在用户抢购商品过程中,会有大量并发请求,很可能同时读写一个包含商品剩余数量的表,这种一般要给数据库加锁,否则很容易出现商品超卖错卖的情况。

如果使用数据库自带的锁机制,也就是悲观锁,在写入的时候锁定数据库,其他修改请求到来时就必须等待锁释放,但这就使效率降下来了,而且高并发场景下可能有的请求一直抢不到锁,就会长时间卡在那导致请求失败,然后有大量重试,系统可能会发生连接数耗尽等异常。

乐观锁是个好东西
查阅资料发现乐观锁是个好东西,它是为数据库表增加一个标识数据版本的version字段来实现的,读取数据时把version字段一同读出,写入数据库时比对version字段就知道数据是否被更改过,如果version不相等就说明持有的是过期数据,不能写入,如果相等就可以写入,并把version加一。

乐观锁在写入数据库的时候,才会检查数据是否冲突,如果发现冲突了,就放弃写入,返回写入失败的信息,相比于悲观锁,这是一种轻量级的对数据的锁定方式,能够应对高并发需求。

给数据库添加乐观锁
说乐观锁是个好东西,首先得说 JPA 是个好东西,因为Spring Data JPA已经内置了乐观锁的实现,给数据库表添加乐观锁很简单,添加一个整型字段,并加入@Version注解就可以了,每次提交数据时JPA会自动检查版本。

    @Entity  
    @Table(name = "m_order")  
    public class Order {  
    ...  
        @Version  
        private int version;  
    ...  
    }  


原文链接:https://blog.csdn.net/ta_ab/article/details/77920510

 

你可能感兴趣的:(JAVA)