Unable to execute update query

#1

Hello!

I'm trying to do an update query via the explorer to set a new field value for around 400k objects.

UPDATE Position p SET p.originalData = null

This exception raises when I try to do it:

[ObjectDB 2.6.5_04] javax.persistence.PersistenceException
Failed to read from file '/tmp/objectdb_1504640757207474899/UpdateQuery_589.mrg' (error 117)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6535)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6300)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4891)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2750)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: com.objectdb.o.UserException: Failed to read from file '/tmp/objectdb_1504640757207474899/UpdateQuery_589.mrg'
at com.objectdb.o.MSG.d(MSG.java:62)
at com.objectdb.o.FIR.o(FIR.java:117)
at com.objectdb.o.BYR.w(BYR.java:206)
at com.objectdb.o.VUT.l(VUT.java:729)
at com.objectdb.o.FCL.u(FCL.java:248)
at com.objectdb.o.FCL.h(FCL.java:93)
at com.objectdb.o.PGT.q(PGT.java:142)
at com.objectdb.o.UPT.C(UPT.java:121)
at com.objectdb.o.URT.l(URT.java:171)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.TSM.e(TSM.java:86)
at com.objectdb.o.UTT.A(UTT.java:370)
at com.objectdb.o.UTT.l(UTT.java:208)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.MST.Vr(MST.java:1337)
at com.objectdb.o.PRG.aj(PRG.java:883)
at com.objectdb.o.PRG.ag(PRG.java:659)
at com.objectdb.o.PRG.af(PRG.java:555)
at com.objectdb.o.QRM.Vm(QRM.java:286)
at com.objectdb.o.MST.Vm(MST.java:988)
at com.objectdb.o.WRA.Vm(WRA.java:311)
at com.objectdb.o.WSM.Vm(WSM.java:115)
at com.objectdb.o.QRR.g(QRR.java:247)
at com.objectdb.o.QRR.f(QRR.java:153)
at com.objectdb.jpa.JpaQuery.executeUpdate(JpaQuery.java:779)
... 39 more
[ObjectDB 2.6.5_04] javax.persistence.PersistenceException
Failed to read from file '/tmp/objectdb_2609537801813547654/UpdateQuery_4398.mrg' (error 117)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6535)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6300)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4891)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2750)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: com.objectdb.o.UserException: Failed to read from file '/tmp/objectdb_2609537801813547654/UpdateQuery_4398.mrg'
at com.objectdb.o.MSG.d(MSG.java:62)
at com.objectdb.o.FIR.o(FIR.java:117)
at com.objectdb.o.BYR.w(BYR.java:206)
at com.objectdb.o.VUT.l(VUT.java:729)
at com.objectdb.o.FCL.u(FCL.java:248)
at com.objectdb.o.FCL.h(FCL.java:93)
at com.objectdb.o.PGT.q(PGT.java:142)
at com.objectdb.o.UPT.C(UPT.java:121)
at com.objectdb.o.URT.l(URT.java:171)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.TSM.e(TSM.java:86)
at com.objectdb.o.UTT.A(UTT.java:370)
at com.objectdb.o.UTT.l(UTT.java:208)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.MST.Vr(MST.java:1337)
at com.objectdb.o.PRG.aj(PRG.java:883)
at com.objectdb.o.PRG.ag(PRG.java:659)
at com.objectdb.o.PRG.af(PRG.java:555)
at com.objectdb.o.QRM.Vm(QRM.java:286)
at com.objectdb.o.MST.Vm(MST.java:988)
at com.objectdb.o.WRA.Vm(WRA.java:311)
at com.objectdb.o.WSM.Vm(WSM.java:115)
at com.objectdb.o.STC.r(STC.java:450)
at com.objectdb.o.SHN.aj(SHN.java:489)
at com.objectdb.o.SHN.K(SHN.java:155)
at com.objectdb.o.HND.run(HND.java:133)
at java.lang.Thread.run(Thread.java:745)

Xmx is 4GB.

This is how the tmp directory looks like after the error occoured:

0 lock.lck
4,0K pages0.dat
3,8G UpdateQuery_4398.mrg
3,8G insgesamt

What could be wrong?

Best Regards

#2

The exception is thrown because of a problem in reading a temporary file that is used in an update query, but the cause is unclear, and according to your report that specific temporary file exists.

Can you reproduce the exception? Does it work with earlier ObjectDB versions?

ObjectDB Support
#3

My harddisk isn't full. The file exists. I haven't tried it with an older version.

It's reproducable in 100% of the cases. If I limit the amount of positons to update by specifying an id ranges it works.

#4

Unfortunately we cannot reproduce the error.

We tried the following test case, but it works well (also with low temp file threshold and temporary files):

import javax.persistence.*;
import javax.persistence.Query;

public class T1803 {

    public static void main(String[] args) {
   
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb:$objectdb/db/test.tmp;drop");
        EntityManager em = emf.createEntityManager();
       
        em.getTransaction().begin();
        for (int i = 0; i < 400000; i++)
            em.persist(new MyEntity(i));
        em.getTransaction().commit();
       
        em.getTransaction().begin();
        Query query = em.createQuery("UPDATE MyEntity e SET e.x = 7");
        query.executeUpdate();
        em.getTransaction().commit();

        em.close();
        emf.close();
    }

    @Entity
    public static class MyEntity
    {
        int x;
        byte[] data = new byte[512];

        public MyEntity(int x) {
            this.x = x;
        }
    }   
}

If you can provide a test case it may help.

As a workaround you may increase the temp file threshold just for performing the operation, so no temporary files will be used.

ObjectDB Support
#5

I've modified your testcase a little bit to represent our application. We store base64 Strings with around 4k.

import javax.persistence.*;
import java.util.HashMap;
import java.util.Random;


public class T1803 {

    public static void main(String[] args) {

        HashMap<String, Object> settings = new HashMap<>();
        settings.put("javax.persistence.jdbc.user", "admin");
        settings.put("javax.persistence.jdbc.password", "admin");
        EntityManagerFactory emf =
                Persistence.createEntityManagerFactory(
                        "objectdb://localhost/test.tmp;drop", settings);

        EntityManager em = emf.createEntityManager();

        System.out.println("Adding objects");

        em.getTransaction().begin();
        for (int i = 0; i < 1000000; i++) {
            em.persist(new MyEntity(randomString(4096)));
            if (i % 5000 == 0) {
                System.out.println(i);
                em.getTransaction().commit();
                em.flush();
                em.clear();
                em.getTransaction().begin();
            }
        }
        em.getTransaction().commit();

        System.out.println("Executing update");
        em.getTransaction().begin();
        Query query = em.createQuery("UPDATE MyEntity e SET e.data = null");
        query.executeUpdate();
        em.getTransaction().commit();

        em.close();
        emf.close();
    }

    @Entity
    public static class MyEntity {
        String data;

        public MyEntity(String data) {
            this.data = data;
        }

    }


    static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static Random rnd = new Random();

    static String randomString(int len) {
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++)
            sb.append(AB.charAt(rnd.nextInt(AB.length())));
        return sb.toString();
    }
}

This testcase doesn't lead to extensive temp file generation but it crashes, during the update, with an OOM error. Xmx is set to 4096M on server and client.

com.objectdb.o.InternalException: java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap space
at com.objectdb.o.VUT.k(VUT.java:483)
at com.objectdb.o.VUT.j(VUT.java:371)
at com.objectdb.o.VUT.j(VUT.java:357)
at com.objectdb.o.SPV.U(SPV.java:148)
at com.objectdb.o.VUT.k(VUT.java:691)
at com.objectdb.o.VUT.j(VUT.java:371)
at com.objectdb.o.VUT.j(VUT.java:357)
at com.objectdb.o.UPT.H(UPT.java:288)
at com.objectdb.o.UPT.G(UPT.java:254)
at com.objectdb.o.UPT.m(UPT.java:172)
at com.objectdb.o.TSK.k(TSK.java:183)
at com.objectdb.o.TSK.i(TSK.java:156)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.UPT.s(UPT.java:157)
at com.objectdb.o.PGT.q(PGT.java:109)
at com.objectdb.o.UPT.C(UPT.java:121)
at com.objectdb.o.UPT.l(UPT.java:110)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.UPT.s(UPT.java:157)
at com.objectdb.o.PGT.q(PGT.java:109)
at com.objectdb.o.UPT.C(UPT.java:121)
at com.objectdb.o.URT.l(URT.java:171)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.TSM.e(TSM.java:86)
at com.objectdb.o.UTT.A(UTT.java:375)
at com.objectdb.o.UTT.l(UTT.java:208)
at com.objectdb.o.TSK.i(TSK.java:145)
at com.objectdb.o.TSK.f(TSK.java:95)
at com.objectdb.o.MST.Vs(MST.java:1350)
at com.objectdb.o.PRG.aj(PRG.java:883)
#6

Thank you for the test case.

The issue is related to issue #1658, a limitation of ObjectDB in handing very large transactions, since this update query requires a very large transaction to be executed, and this requires a lot of heap size.

Unfortunately the workaround suggested in that issue does not work here. We are still working on it hoping to find a solution.

ObjectDB Support
#7

The workaround of issue #1658 is now (in build 2.6.6_04) extended to update queries.

See issue #255 posts 10 and 28 regarding how to enable it.

When enabled, your test case now works with no exceptions.

ObjectDB Support

Reply