两个并发请求能够锁定 Postgres sql 中的同一行

问题描述

当对以下代码发出两个并发请求时,两个请求都能够同时获取锁,因此能够执行代码

在生产中运行的示例代码

参考示例代码

//Starting point for the request
@Override
    public void receiveTransferItems(String argumet1,String refernceId,List<Item> items,long messageId)
            throws Exception {
        ParentDTO parent = DAO.lockByReferenceid(referenceId);
        if (parent == null) {
            throw new Exception(referenceId + "does not exist");
        }

        updateData(parent);

        for (Item item : items) {
            receiveItem(td,td.getWarehouseId(),item.getItemSKU(),item.getItemStatus(),item.getQtyReceived(),messageId);
        }

    }
    
    
    private void updateData(ParentDTO td) throws DropShipException {

        //perform some logical processing and then execute update 
        DAO.update(td);
    }
    
    
    
     private void receiveItem(ParentDTO td,String warehouseId,String asin,String itemStatus,int quantity,long messageId)
            throws Exception {
    
        /**
         * perform some logical processing
         * 
         **/
        //call is being made to another class to do the rest of the processing
        service.receive(td,asin,quantity,condition,container,messageId);
    }
@Override
    public void receive(
            ParentDTO parentDTO,Condition condition,Container container,long messageId,DataAccessor accessor) throws Exception {



        List<ChildDTO> childDTOs =
            DAO.lockChildDTOItems(parentDTO.getReferenceId(),CostInfoSource.MANIFEST);

        List<ChildDTO> filterItems = DAO
            .loadChildDTOItems(parentDTO.getReferenceId(),condition.name());

        long totalExpectedQuantity = getTotalExpectedQuantity(filterItems);
        long totalReceivedQuantity = getTotalReceivedQuantity(filterItems);

        int quantitynormalReceived = 0;
        for (ChildDTO tdi : childDTOs) {
        
            int quantityReceived = 0;
            if (asinDropShipMsgAction != null) {
                quantity -= asinDropShipMsgAction.getinitialQuantity();
                quantitynormalReceived += asinDropShipMsgAction.getinitialQuantity();
            } else {
                quantityReceived = new DBOperationRunner<Integer>(accessor.getSessionManager()) {
                    @Override
                    protected Integer doWorkAndReturn() throws Exception {
                        return normalReceive(tdi,quantityLeft,MessageActionType.TS_IN,messageId);
                    }
                }.execute();
            }
          
        }

    }
    
    
    
    private int normalReceive(final ChildDTO childDTO,final Container container,final MessageActionType type,long messageId)
        throws Exception {

        /**
         * perform some business logic
         * 
         * */
         
        DAO.update(childDTO);
        return someQuantity;
    }

lockByReferenceId 函数的实现:

@Override
    public ParentDTO lockByReferenceId(String referenceId) {
        Criteria criteria = getCurrentSession().createCriteria(ParentDTO.class)
            .add(Restrictions.eq("referenceId",referenceId)).setLockMode(LockMode.UPGRADE_NowAIT);
        return (ParentDTO) criteria.uniqueResult();
    }

DBOperationRunner 类的实现:

public T execute() throws Exception {
        T t = null;
        Session originalSession = (Session) ThreadLocalContext.get(ThreadLocalContext.CURRENT_SESSION);
        try {
            ThreadLocalContext.put(ThreadLocalContext.CURRENT_SESSION,sessionManager.getCurrentSession());
            sessionManager.beginTransaction();
            t = doWorkAndReturn();
            sessionManager.commit();

        } catch (Exception e) {
            try {
                sessionManager.rollback();
            } catch (Throwable t1) {
                logger.error("Failed to rollback",t1);
            }
            throw e;
        } finally {
            ThreadLocalContext.put(ThreadLocalContext.CURRENT_SESSION,originalSession);
        }

        return t;
    }

最近我在生产代码中观察到一个问题,其中两个或多个同时请求能够同时获取对同一数据的锁定。 我使用 hibernate 和标准作为 DB 框架,c3p0 作为连接池框架,Postgres 作为 DB。 注意:此问题是间歇性的,仅在一些难以调试的随机并发请求中观察到。

我无法理解两个并发请求如何能够同时锁定相同的行。你能帮我找出这种情况下出了什么问题吗?

提前致谢!!!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...