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

如何解决两个并发请求能够锁定 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.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?