diff --git a/conf/core/cache.ccf b/conf/core/cache.ccf
index 672c798d126e9c759e0c7a59a81702733aa4e7b3..821e5d7862efb21e0aa13f8410886c6c14b10a7c 100644
--- a/conf/core/cache.ccf
+++ b/conf/core/cache.ccf
@@ -4,30 +4,46 @@ jcs.default.cacheattributes.MaxObjects=1000
 jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes
 
 # Caching of the backend transactions
-jcs.region.BACKEND_UserRoles.cacheattributes.MaxObjects=100
-jcs.region.BACKEND_Users.cacheattributes.MaxObjects=100
-jcs.region.BACKEND_PermissionRules.cacheattributes.MaxObjects=1000
+jcs.region.BACKEND_UserRoles
+jcs.region.BACKEND_UserRoles.cacheattributes.MaxObjects=101
 
-jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1000
-jcs.region.BACKEND_EntityProperties.cacheattributes.MaxObjects=1000
-jcs.region.BACKEND_EntityParents.cacheattributes.MaxObjects=1000
-jcs.region.BACKEND_SparseFileRecordsByPath.cacheattributes.MaxObjects=1000
+jcs.region.BACKEND_Users
+jcs.region.BACKEND_Users.cacheattributes.MaxObjects=102
 
-jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=100
+jcs.region.BACKEND_PermissionRules
+jcs.region.BACKEND_PermissionRules.cacheattributes.MaxObjects=1001
+
+jcs.region.BACKEND_EntityProperties
+jcs.region.BACKEND_EntityProperties.cacheattributes.MaxObjects=1003
+
+jcs.region.BACKEND_EntityParents
+jcs.region.BACKEND_EntityParents.cacheattributes.MaxObjects=1004
+
+jcs.region.BACKEND_SparseFileRecordsByPath
+jcs.region.BACKEND_SparseFileRecordsByPath.cacheattributes.MaxObjects=1005
+
+jcs.region.BACKEND_JobRules
+jcs.region.BACKEND_JobRules.cacheattributes.MaxObjects=103
+
+jcs.region.BACKEND_SparseEntities
+jcs.region.BACKEND_SparseEntities.cacheattributes.MaxObjects=1002
 
 
 # PAM UserSource Caching: Cached Items expire after 60 seconds if they are not requested (idle) and after 600 seconds max.
 # PAM_UnixUserGroups
+jcs.region.PAM_UnixUserGroups
 jcs.region.PAM_UnixUserGroups.elementattributes.IsEternal=false
-jcs.region.PAM_UnixUserGroups.elementattributes.MaxLife=600
-jcs.region.PAM_UnixUserGroups.elementattributes.IdleTime=60
+jcs.region.PAM_UnixUserGroups.elementattributes.MaxLife=601
+jcs.region.PAM_UnixUserGroups.elementattributes.IdleTime=61
 
 # PAM_UnixUserExists
+jcs.region.PAM_UnixUserExists
 jcs.region.PAM_UnixUserExists.elementattributes.IsEternal=false
-jcs.region.PAM_UnixUserExists.elementattributes.MaxLife=600
-jcs.region.PAM_UnixUserExists.elementattributes.IdleTime=60
+jcs.region.PAM_UnixUserExists.elementattributes.MaxLife=599
+jcs.region.PAM_UnixUserExists.elementattributes.IdleTime=59
 
 # PAM_Authentication
+jcs.region.PAM_Authentication
 jcs.region.PAM_Authentication.elementattributes.IsEternal=false
 jcs.region.PAM_Authentication.elementattributes.MaxLife=600
 jcs.region.PAM_Authentication.elementattributes.IdleTime=60
diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java
index c68ae31c1fbfe8487bce082e545222ec9647b188..19560aacd50ede38471c0fb02e31fd4560e9d8bb 100644
--- a/src/main/java/caosdb/server/CaosDBServer.java
+++ b/src/main/java/caosdb/server/CaosDBServer.java
@@ -27,7 +27,7 @@ import caosdb.server.accessControl.OneTimeTokenRealm;
 import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.SessionToken;
 import caosdb.server.accessControl.SessionTokenRealm;
-import caosdb.server.database.Database;
+import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.RetrieveDatatypes;
 import caosdb.server.database.misc.TransactionBenchmark;
@@ -58,7 +58,7 @@ import caosdb.server.resource.transaction.EntityResource;
 import caosdb.server.terminal.CaosDBTerminal;
 import caosdb.server.terminal.StatsPanel;
 import caosdb.server.terminal.SystemErrPanel;
-import caosdb.server.utils.ChecksumUpdater;
+import caosdb.server.transaction.ChecksumUpdater;
 import caosdb.server.utils.FileUtils;
 import caosdb.server.utils.Initialization;
 import caosdb.server.utils.NullPrintStream;
@@ -279,8 +279,10 @@ public class CaosDBServer extends Application {
     try {
       // init backend
       if (START_BACKEND) {
+        BackendTransaction.init();
+
         // init benchmark
-        TransactionBenchmark.getInstance();
+        TransactionBenchmark.getRootInstance();
 
         // Role
         Role.init(init.getAccess());
@@ -316,7 +318,7 @@ public class CaosDBServer extends Application {
         Thread.sleep(1000);
 
         // add Benchmark
-        StatsPanel.addStat("TransactionBenchmark", TransactionBenchmark.getInstance());
+        StatsPanel.addStat("TransactionBenchmark", TransactionBenchmark.getRootInstance());
       } else {
         logger.info("NO GUI");
         System.setOut(new NullPrintStream());
@@ -357,7 +359,9 @@ public class CaosDBServer extends Application {
 
   private static void initDatatypes(final Access access) throws Exception {
     final RetrieveDatatypes t = new RetrieveDatatypes();
-    final Container<? extends EntityInterface> dts = Database.execute(t, access).getDatatypes();
+    t.setAccess(access);
+    t.executeTransaction();
+    final Container<? extends EntityInterface> dts = t.getDatatypes();
     AbstractDatatype.initializeDatatypes(dts);
   }
 
diff --git a/src/main/java/caosdb/server/FileSystem.java b/src/main/java/caosdb/server/FileSystem.java
index 44b663e958841ac92a24f44244096034eb9154c3..c46f0f644442a5df6c2363dedfacb38025cacde4 100644
--- a/src/main/java/caosdb/server/FileSystem.java
+++ b/src/main/java/caosdb/server/FileSystem.java
@@ -24,9 +24,9 @@
 
 package caosdb.server;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.GetFileRecordByPath;
+import caosdb.server.database.misc.TransactionBenchmark;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.FileProperties;
 import caosdb.server.entity.Message;
@@ -300,8 +300,8 @@ public class FileSystem {
    * @return
    * @throws Message
    */
-  public static boolean checkTarget(final EntityInterface entity, final Access access)
-      throws Message {
+  public static boolean checkTarget(
+      final EntityInterface entity, final Access access, TransactionBenchmark b) throws Message {
 
     final FileProperties file = entity.getFileProperties();
     // target file name = where the file is to be stored.
@@ -321,8 +321,10 @@ public class FileSystem {
       if (file.getFile() != null && file.getFile().equals(target)) {
         return true;
       } else {
-        final GetFileRecordByPath t =
-            Database.execute(new GetFileRecordByPath(file.getPath()), access);
+        final GetFileRecordByPath t = new GetFileRecordByPath(file.getPath());
+        t.setAccess(access);
+        t.setTransactionBenchmark(b);
+        t.executeTransaction();
         if (t.getEntity() != null) {
           final Integer foreign = t.getId();
           if (foreign != null && foreign.equals(entity.getId())) {
diff --git a/src/main/java/caosdb/server/accessControl/Pam.java b/src/main/java/caosdb/server/accessControl/Pam.java
index 99f68faadc15c15d9404a504d15669f0c2604ea3..d640a66f4fffdb6254c7d11d696a1f2a1bf5ebf6 100644
--- a/src/main/java/caosdb/server/accessControl/Pam.java
+++ b/src/main/java/caosdb/server/accessControl/Pam.java
@@ -108,6 +108,10 @@ public class Pam implements UserSource {
   public static final String KEY_EMAIL = "email";
   public static final String REGEX_SPLIT_CSV = "\\s*,\\s*";
 
+  public static final String CACHE_REGION_GROUPS = "PAM_UnixUserGroups";
+  public static final String CACHE_REGION_USER_EXIST = "PAM_UnixUserExists";
+  public static final String CACHE_REGION_AUTH = "PAM_Authentication";
+
   private String[] EXCLUDE_USERS = null;
   private String[] INCLUDE_USERS = null;
   private String[] EXCLUDE_GROUPS = null;
@@ -117,9 +121,9 @@ public class Pam implements UserSource {
 
   /* Caches for groups, user-existence and password validation */
 
-  private ICacheAccess<String, HashSet<String>> groupsCache = Cache.getCache("PAM_UnixUserGroups");
-  private ICacheAccess<String, Boolean> userExistsCache = Cache.getCache("PAM_UnixUserExists");
-  private ICacheAccess<String, Boolean> passwordValidCache = Cache.getCache("PAM_Authentication");
+  private ICacheAccess<String, HashSet<String>> groupsCache = Cache.getCache(CACHE_REGION_GROUPS);
+  private ICacheAccess<String, Boolean> userExistsCache = Cache.getCache(CACHE_REGION_USER_EXIST);
+  private ICacheAccess<String, Boolean> passwordValidCache = Cache.getCache(CACHE_REGION_AUTH);
 
   @Override
   public void setMap(final Map<String, String> map) {
diff --git a/src/main/java/caosdb/server/caching/JCSCacheHelper.java b/src/main/java/caosdb/server/caching/JCSCacheHelper.java
index dab2b77ceaab3d0caaf49d798a4819ca890b5e82..55efaa191bcb777bd63881dfbd72cd292808064c 100644
--- a/src/main/java/caosdb/server/caching/JCSCacheHelper.java
+++ b/src/main/java/caosdb/server/caching/JCSCacheHelper.java
@@ -58,11 +58,18 @@ public class JCSCacheHelper implements CacheHelper {
 
   // configure JCS
   static {
+    init();
+  }
+
+  public static void init() {
+    init(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_CONF_LOC));
+  }
+
+  public static void init(String configFileLocation) {
     Properties config = null;
     try {
       Properties p = new Properties();
-      final InputStream is =
-          new FileInputStream(CaosDBServer.getServerProperty(ServerProperties.KEY_CACHE_CONF_LOC));
+      final InputStream is = new FileInputStream(configFileLocation);
       p.load(is);
       is.close();
       config = p;
diff --git a/src/main/java/caosdb/server/database/BackendTransaction.java b/src/main/java/caosdb/server/database/BackendTransaction.java
index 4899996e6c4df2b18837259112ac7e90c534b793..42cce21af9f7e851d27c960b9704aae46b96350f 100644
--- a/src/main/java/caosdb/server/database/BackendTransaction.java
+++ b/src/main/java/caosdb/server/database/BackendTransaction.java
@@ -130,21 +130,21 @@ public abstract class BackendTransaction implements Undoable {
 
   private final UndoHandler undoHandler = new UndoHandler();
   private Access access;
-  BackendTransaction parent = null;
+  private TransactionBenchmark benchmark;
   private static HashMap<
           Class<? extends BackendTransactionImpl>, Class<? extends BackendTransactionImpl>>
       impl = new HashMap<>();
 
   protected abstract void execute();
 
-  final void executeTransaction() {
+  public final void executeTransaction() {
     final long t1 = System.currentTimeMillis();
     execute();
     final long t2 = System.currentTimeMillis();
-    TransactionBenchmark.getInstance().addBenchmark(this, t2 - t1);
+    this.addMeasurement(this, t2 - t1);
   }
 
-  private static void init() {
+  public static void init() {
     if (impl.isEmpty()) {
       setImpl(DeleteEntityPropertiesImpl.class, MySQLDeleteEntityProperties.class);
       setImpl(DeleteSparseEntityImpl.class, MySQLDeleteSparseEntity.class);
@@ -202,11 +202,13 @@ public abstract class BackendTransaction implements Undoable {
     assert t != this;
     this.undoHandler.append(t);
     t.setAccess(this.access);
-    t.parent = this;
+    if (benchmark != null) {
+      t.setTransactionBenchmark(benchmark.getBenchmark(t.getClass()));
+    }
     final long t1 = System.currentTimeMillis();
     t.execute();
     final long t2 = System.currentTimeMillis();
-    TransactionBenchmark.getInstance().addBenchmark(t, t2 - t1);
+    this.addMeasurement(t, t2 - t1);
     return t;
   }
 
@@ -215,7 +217,7 @@ public abstract class BackendTransaction implements Undoable {
     impl.put(k, l);
   }
 
-  void setAccess(final Access access) {
+  public void setAccess(final Access access) {
     this.access = access;
   }
 
@@ -223,10 +225,14 @@ public abstract class BackendTransaction implements Undoable {
   protected <T extends BackendTransactionImpl> T getImplementation(final Class<T> clz) {
     init();
     try {
-      final T ret = (T) impl.get(clz).getConstructor(Access.class).newInstance(this.access);
+      Class<?> implclz = impl.get(clz);
+      final T ret = (T) implclz.getConstructor(Access.class).newInstance(this.access);
       if (ret instanceof Undoable) {
         this.undoHandler.append((Undoable) ret);
       }
+      if (benchmark != null) {
+        ret.setTransactionBenchmark(benchmark.getBenchmark(ret.getClass()));
+      }
       return ret;
     } catch (final Exception e) {
       throw new TransactionException(e);
@@ -253,7 +259,16 @@ public abstract class BackendTransaction implements Undoable {
 
   @Override
   public String toString() {
-    return (this.parent != null ? this.parent.toString() + " -> " : "")
-        + this.getClass().getSimpleName();
+    return this.getClass().getSimpleName();
+  }
+
+  public void setTransactionBenchmark(TransactionBenchmark b) {
+    this.benchmark = b;
+  }
+
+  public void addMeasurement(Object o, long time) {
+    if (this.benchmark != null) {
+      this.benchmark.addMeasurement(o, time);
+    }
   }
 }
diff --git a/src/main/java/caosdb/server/database/Database.java b/src/main/java/caosdb/server/database/Database.java
index c30b68c7c16cecf4d59f3d6adda10e066a42763f..d67acdff9d8fbacdbdefdfdeb5013c3838156461 100644
--- a/src/main/java/caosdb/server/database/Database.java
+++ b/src/main/java/caosdb/server/database/Database.java
@@ -22,18 +22,17 @@
  */
 package caosdb.server.database;
 
-import caosdb.server.database.access.Access;
-import caosdb.server.database.misc.RollBackHandler;
-
 public class Database {
 
-  public static <K extends BackendTransaction> K execute(final K t, final Access access) {
-
-    final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack");
-    handler.append(t);
-    t.setAccess(access);
-
-    t.executeTransaction();
-    return t;
-  }
+  //  public static <K extends BackendTransaction> K execute(
+  //      final K t, final Access access, TransactionBenchmark b) {
+  //
+  //    final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack");
+  //    handler.append(t);
+  //    t.setAccess(access);
+  //
+  //    t.setTransactionBenchmark(b);
+  //    t.executeTransaction();
+  //    return t;
+  //  }
 }
diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java
index 329a4e81b211815ac3ab5059e4b789eed9dce1b9..8b9a547bac69cf221dbf7c204a93e95326bb484c 100644
--- a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java
+++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java
@@ -49,6 +49,7 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev
       final PreparedStatement prepareStatement = prepareStatement(stmtStr);
 
       final List<FlatProperty> props = retrieveFlatPropertiesStage1(0, entity, prepareStatement);
+
       final ArrayList<ProtoProperty> protos = new ArrayList<ProtoProperty>();
       for (final FlatProperty p : props) {
         final ProtoProperty proto = new ProtoProperty();
@@ -56,6 +57,7 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev
 
         final List<FlatProperty> subProps =
             retrieveFlatPropertiesStage1(entity, p.id, prepareStatement);
+
         proto.subProperties = subProps;
 
         protos.add(proto);
@@ -80,7 +82,10 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev
       }
 
       stmt.setInt(2, entity);
+      long t1 = System.currentTimeMillis();
       rs = stmt.executeQuery();
+      long t2 = System.currentTimeMillis();
+      addMeasurement(this.getClass().getSimpleName() + ".retrieveFlatPropertiesStage1", t2 - t1);
 
       final List<FlatProperty> props = DatabaseUtils.parsePropertyResultset(rs);
 
@@ -107,7 +112,10 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev
     try {
       stmt2.setInt(1, domain);
       stmt2.setInt(2, entity);
+      long t1 = System.currentTimeMillis();
       rs = stmt2.executeQuery();
+      long t2 = System.currentTimeMillis();
+      addMeasurement(this.getClass().getSimpleName() + ".retrieveOverrides", t2 - t1);
       DatabaseUtils.parseOverrides(props, rs);
     } finally {
       if (rs != null && !rs.isClosed()) {
diff --git a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java
index 1eb398634a665672bfbd266c51d819565fbea04d..f116a136c1b3e1942ddc2400139db3c82210fac8 100644
--- a/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java
+++ b/src/main/java/caosdb/server/database/backend/implementation/MySQL/MySQLTransaction.java
@@ -23,13 +23,16 @@
 package caosdb.server.database.backend.implementation.MySQL;
 
 import caosdb.server.database.access.Access;
+import caosdb.server.database.backend.interfaces.BackendTransactionImpl;
 import caosdb.server.database.misc.DBHelper;
+import caosdb.server.database.misc.TransactionBenchmark;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 
-public class MySQLTransaction {
+public class MySQLTransaction implements BackendTransactionImpl {
 
   protected final Access access;
+  private TransactionBenchmark benchmark;
 
   public MySQLTransaction(final Access access) {
     this.access = access;
@@ -54,4 +57,20 @@ public class MySQLTransaction {
   public final void undo() {}
 
   public final void cleanUp() {}
+
+  @Override
+  public TransactionBenchmark getBenchmark() {
+    return benchmark;
+  }
+
+  @Override
+  public void setTransactionBenchmark(TransactionBenchmark b) {
+    this.benchmark = b;
+  }
+
+  protected void addMeasurement(String string, long l) {
+    if (benchmark != null) {
+      benchmark.addMeasurement(string, l);
+    }
+  }
 }
diff --git a/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java b/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java
index 851e0b0d6bfdbe0b29f9ce8ec51d26f1b26954e8..63e87d6a4f968d3d4833111f9ca9875daf18d9cc 100644
--- a/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java
+++ b/src/main/java/caosdb/server/database/backend/implementation/UnixFileSystem/UnixFileSystemTransaction.java
@@ -24,19 +24,27 @@ package caosdb.server.database.backend.implementation.UnixFileSystem;
 
 import caosdb.server.FileSystem;
 import caosdb.server.database.access.Access;
+import caosdb.server.database.backend.interfaces.BackendTransactionImpl;
 import caosdb.server.database.misc.DBHelper;
+import caosdb.server.database.misc.TransactionBenchmark;
 import caosdb.server.entity.Message;
 import java.io.File;
 import java.io.IOException;
 
-public abstract class UnixFileSystemTransaction {
+public abstract class UnixFileSystemTransaction implements BackendTransactionImpl {
 
   private final Access access;
+  private TransactionBenchmark benchmark;
 
   public UnixFileSystemTransaction(final Access access) {
     this.access = access;
   }
 
+  @Override
+  public void setTransactionBenchmark(TransactionBenchmark b) {
+    this.benchmark = b;
+  }
+
   protected File getFile(final String path) throws IOException, Message {
     return new File(getHelper().getBasePath() + path);
   }
@@ -56,4 +64,9 @@ public abstract class UnixFileSystemTransaction {
       return (UnixFileSystemHelper) dbHelper;
     }
   }
+
+  @Override
+  public TransactionBenchmark getBenchmark() {
+    return benchmark;
+  }
 }
diff --git a/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java b/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java
index cc2af6e2d8a421eab23b466986413bf2819b10b5..d4751f94cda0b0bdea703d5f207527ea756681f3 100644
--- a/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java
+++ b/src/main/java/caosdb/server/database/backend/interfaces/BackendTransactionImpl.java
@@ -22,4 +22,11 @@
  */
 package caosdb.server.database.backend.interfaces;
 
-public interface BackendTransactionImpl {}
+import caosdb.server.database.misc.TransactionBenchmark;
+
+public interface BackendTransactionImpl {
+
+  public void setTransactionBenchmark(TransactionBenchmark b);
+
+  public TransactionBenchmark getBenchmark();
+}
diff --git a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
index 650cae3676ed2b6b50f86c76a5ce92b195290fc3..487feb56cf848e948fcacb8f33f49e4a0bc2267d 100644
--- a/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
+++ b/src/main/java/caosdb/server/database/backend/transaction/RetrieveProperties.java
@@ -40,8 +40,9 @@ public class RetrieveProperties
     extends CacheableBackendTransaction<Integer, ArrayList<ProtoProperty>> {
 
   private final EntityInterface entity;
+  public static final String CACHE_REGION = "BACKEND_EntityProperties";
   private static final ICacheAccess<Integer, ArrayList<ProtoProperty>> cache =
-      Cache.getCache("BACKEND_EntityProperties");
+      Cache.getCache(CACHE_REGION);
 
   /**
    * To be called by DeleteEntityProperties on execution.
diff --git a/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java b/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java
index 80b60e80893e8b512abededb345e286438ec22bb..f7c9e80f811418392b6567fcda5bfb8a9948bbff 100644
--- a/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java
+++ b/src/main/java/caosdb/server/database/misc/TransactionBenchmark.java
@@ -27,49 +27,122 @@ import caosdb.server.ServerProperties;
 import caosdb.server.utils.CronJob;
 import caosdb.server.utils.Info;
 import caosdb.server.utils.ServerStat;
+import java.io.Serializable;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Map.Entry;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.jdom2.Element;
 
-public class TransactionBenchmark implements ServerStat {
+class Counter implements Serializable {
+  private static final long serialVersionUID = 8679355597595634790L;
+  private int c;
 
-  private static final long serialVersionUID = -8916163825450491067L;
-  private long since = System.currentTimeMillis();
-  private final HashMap<String, Integer> counts = new HashMap<String, Integer>();
-  private final HashMap<String, Long> acc = new HashMap<String, Long>();
-  private transient boolean synced = false;
-  private static final TransactionBenchmark instance = new TransactionBenchmark();
-  private static final boolean isActive =
-      Boolean.valueOf(
-          CaosDBServer.getServerProperty(ServerProperties.KEY_TRANSACTION_BENCHMARK_ENABLED)
-              .toLowerCase());
+  public Counter(int initial) {
+    this.c = initial;
+  }
 
-  static {
-    if (isActive) {
-      instance.init();
-    }
+  public void add(int inc) {
+    this.c += inc;
+  }
+
+  public int toInteger() {
+    return c;
+  }
+}
+
+class Timer implements Serializable {
+  private static final long serialVersionUID = 7895352555775799409L;
+  private long c;
+
+  public Timer(long initial) {
+    this.c = initial;
+  }
+
+  public void add(long inc) {
+    this.c += inc;
+  }
+
+  public long toLong() {
+    return c;
+  }
+}
+
+class Measurement implements Serializable {
+  private static final long serialVersionUID = -2429348657382168470L;
+  private final Timer timer;
+  private final Counter counter;
+  private final String name;
+
+  public Measurement(String name, long time, int count) {
+    this.name = name;
+    this.timer = new Timer(time);
+    this.counter = new Counter(count);
+  }
+
+  public void add(long time, int count) {
+    this.timer.add(time);
+    this.counter.add(count);
+  }
+
+  public double getAvg() {
+    return (double) this.getAccTime() / this.getCount();
   }
 
+  public StringBuilder toStringBuilder() {
+    StringBuilder sb = new StringBuilder();
+    sb.append('#');
+    sb.append(name);
+    sb.append(": ");
+    sb.append('(');
+    sb.append(this.getCount());
+    sb.append(", ");
+    sb.append(this.getAccTime());
+    sb.append(", ");
+    sb.append(String.format(Locale.US, "%3.2f", this.getAvg()));
+    sb.append(')');
+    return sb;
+  }
+
+  public int getCount() {
+    return counter.toInteger();
+  }
+
+  public long getAccTime() {
+    return timer.toLong();
+  }
+
+  public String getName() {
+    return this.name;
+  }
+}
+
+class RootBenchmark extends TransactionBenchmark implements ServerStat {
+
+  private static final long serialVersionUID = 8070554107783826602L;
+  private transient boolean synced = false;
   /**
    * Fetch old data (from before last shutdown) and fill it into this instance.
    *
    * @return
    */
-  private TransactionBenchmark init() {
-    synchronized (this.counts) {
+  protected TransactionBenchmark init() {
+    final RootBenchmark b = this;
+    synchronized (this.measurements) {
       final Runnable updater =
           new Runnable() {
 
             @Override
             public void run() {
               try {
-                synchronized (TransactionBenchmark.this.counts) {
-                  Info.syncDatabase(TransactionBenchmark.this);
+                synchronized (b.measurements) {
+                  Info.getInstance().syncDatabase(b);
                 }
               } catch (final Exception e) {
-                e.printStackTrace();
+                logger.error(e);
               }
             }
           };
@@ -81,38 +154,166 @@ public class TransactionBenchmark implements ServerStat {
     return this;
   }
 
+  @Override
+  public final String getName() {
+    return "TransactionBenchmark";
+  }
+
   /**
-   * Add a benchmark for a certain object. The object will be toString()'ed. The string serves as a
-   * key.
+   * Add data from s to this instance.
    *
-   * @param object
-   * @param time
+   * @param s another TransactionBenchmark instance
    */
-  public void addBenchmark(final Object object, final long time) {
+  @Override
+  public final void update(final ServerStat s) {
+    if (!this.synced && isActive) {
+      final RootBenchmark t = (RootBenchmark) s;
+      this.synced = true;
+      merge(this, t);
+    }
+  }
+
+  public void merge(TransactionBenchmark target, TransactionBenchmark src) {
     if (isActive) {
-      addBenchmark(instance, object.toString(), time, 1);
+      target.since = Long.min(target.since, src.since);
+      synchronized (target.measurements) {
+        for (final Measurement m : src.measurements.values()) {
+          // add all measurements from src
+          target.addMeasurement(m);
+        }
+      }
+
+      // merge subBenchmarks
+      synchronized (src.subBenchmarks) {
+        for (final SubBenchmark srcsb : src.getSubBenchmarks()) {
+          synchronized (target.subBenchmarks) {
+            if (target.subBenchmarks.containsKey(srcsb.getName())) {
+              merge(target.subBenchmarks.get(srcsb.getName()), srcsb);
+            } else {
+              target.subBenchmarks.put(srcsb.getName(), srcsb);
+            }
+          }
+        }
+      }
     }
   }
+}
 
-  private static void addBenchmark(
-      final TransactionBenchmark b, final String name, final long time, final int count) {
-    synchronized (b.counts) {
-      if (b.counts.containsKey(name)) {
-        int c = b.counts.get(name);
-        c += count;
-        b.counts.put(name, c);
-        long a = b.acc.get(name);
-        a += time;
-        b.acc.put(name, a);
-      } else {
-        b.counts.put(name, count);
-        b.acc.put(name, time);
+class SubBenchmark extends TransactionBenchmark {
+
+  private static final long serialVersionUID = 323147917189195973L;
+  private final String name;
+
+  public SubBenchmark(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+}
+
+class JdomConverter {
+  public Element convert(Measurement m) {
+    Element ret = new Element("Measurement");
+    ret.setAttribute("name", m.getName());
+    ret.setAttribute("acc_time", Long.toString(m.getAccTime()));
+    ret.setAttribute("avg_time", String.format(Locale.US, "%3.2f", m.getAvg()));
+    ret.setAttribute("count", Integer.toString(m.getCount()));
+    return ret;
+  }
+
+  public Element convert(TransactionBenchmark b) {
+    Element ret = new Element(b.getName());
+    ret.setAttribute("since", new Date(b.since).toString());
+    Iterable<Measurement> measurements = b.getMeasurements();
+
+    synchronized (measurements) {
+      for (Measurement m : measurements) {
+        ret.addContent(this.convert(m));
       }
     }
+
+    // tree view of subBenchmarks
+    Iterable<SubBenchmark> subBenchmarks = b.getSubBenchmarks();
+    synchronized (subBenchmarks) {
+      for (SubBenchmark s : subBenchmarks) {
+        ret.addContent(this.convert(s));
+      }
+    }
+    return ret;
+  }
+}
+
+public abstract class TransactionBenchmark implements Serializable {
+
+  private static final long serialVersionUID = -8916163825450491067L;
+  private static final TransactionBenchmark rootService = new RootBenchmark().init();
+  public final transient Logger logger = LogManager.getLogger(getClass());
+  protected static final transient boolean isActive =
+      Boolean.valueOf(
+          CaosDBServer.getServerProperty(ServerProperties.KEY_TRANSACTION_BENCHMARK_ENABLED)
+              .toLowerCase());
+
+  long since = System.currentTimeMillis();
+
+  protected final Map<String, Measurement> measurements = new HashMap<>();
+  protected final Map<String, SubBenchmark> subBenchmarks = new HashMap<>();
+
+  protected TransactionBenchmark() {};
+
+  public Iterable<SubBenchmark> getSubBenchmarks() {
+    return this.subBenchmarks.values();
   }
 
-  public static TransactionBenchmark getInstance() {
-    return instance;
+  public Iterable<Measurement> getMeasurements() {
+    return this.measurements.values();
+  }
+
+  /**
+   * Add a measurement. The object will be toString()'ed. The string serves as a key.
+   *
+   * @param object
+   * @param time
+   */
+  public void addMeasurement(final Object object, final long time) {
+    this.addMeasurement(object, time, 1);
+  }
+
+  /**
+   * Add a measurement. The object will be toString()'ed. The string serves as a key.
+   *
+   * @param object
+   * @param time
+   * @param count
+   */
+  public void addMeasurement(final Object object, final long time, int count) {
+    if (isActive) {
+      String name = object.toString();
+
+      synchronized (this.measurements) {
+        Measurement existing = this.measurements.get(name);
+        if (existing == null) {
+          this.measurements.put(name, new Measurement(name, time, count));
+        } else {
+          existing.add(time, count);
+        }
+      }
+    }
+  }
+
+  /**
+   * Add a measurement.
+   *
+   * @param measurement
+   */
+  public void addMeasurement(Measurement measurement) {
+    this.addMeasurement(measurement.getName(), measurement.getAccTime(), measurement.getCount());
+  }
+
+  public static TransactionBenchmark getRootInstance() {
+    return rootService;
   }
 
   @Override
@@ -121,23 +322,11 @@ public class TransactionBenchmark implements ServerStat {
       final StringBuilder sb = new StringBuilder();
       sb.append(
           "\nNAME: (execution count, accumulated execution time [ms], avg time per execution [ms])\n");
-      synchronized (this.counts) {
-        for (final Entry<String, Integer> e : this.counts.entrySet()) {
-          final int c = e.getValue();
-          final long acc = this.acc.get(e.getKey());
-          final String name = e.getKey();
-          final double avg = (double) acc / c;
+      synchronized (this.measurements) {
+        for (final Entry<String, Measurement> e : this.measurements.entrySet()) {
+          final Measurement m = e.getValue();
           sb.append('\n');
-          sb.append('#');
-          sb.append(name);
-          sb.append(": ");
-          sb.append('(');
-          sb.append(c);
-          sb.append(", ");
-          sb.append(acc);
-          sb.append(", ");
-          sb.append(String.format(Locale.US, "%3.2f", avg));
-          sb.append(')');
+          sb.append(m.toStringBuilder());
         }
       }
       return sb.toString();
@@ -147,73 +336,54 @@ public class TransactionBenchmark implements ServerStat {
   }
 
   public Element toElememt() {
-    final Element ret = new Element("TransactionBenchmark");
     if (isActive) {
-      ret.setAttribute("since", new Date(this.since).toString());
-      synchronized (this.counts) {
-        for (final Entry<String, Integer> e : this.counts.entrySet()) {
-          final int c = e.getValue();
-          final long acc = TransactionBenchmark.this.acc.get(e.getKey());
-          final String name = e.getKey();
-          final double avg = (double) acc / c;
-
-          final Element b = new Element("Benchmark");
-          b.setAttribute("name", name);
-          b.setAttribute("execution_count", Integer.toString(c));
-          b.setAttribute("accumulated_execution_time", Long.toString(acc) + "ms");
-          b.setAttribute("avg_execution_time", String.format(Locale.US, "%3.2f", avg) + "ms");
-
-          ret.addContent(b);
-        }
-      }
+      return new JdomConverter().convert(this).setName("TransactionBenchmark");
     } else {
+      final Element ret = new Element("TransactionBenchmark");
       ret.setAttribute("info", "TransactionBenchmark is disabled.");
+      return ret;
     }
-    return ret;
   }
 
-  @Override
-  public String getName() {
-    return this.getClass().getSimpleName();
-  }
+  public abstract String getName();
 
   /**
-   * Add data from s to this instance
+   * Create a new independent {@link TransactionBenchmark}.
    *
-   * @param s another TransactionBenchmark instance
+   * <p>This is for starting a series of measurements from a clean slate.
+   *
+   * <p>However, the Measurements and Benchmarks are still recorded in the {@link RootBenchmark}
+   * too.
+   *
+   * @param name the name of the new {@link TransactionBenchmark}.
+   * @return a new {@link TransactionBenchmark}
    */
-  @Override
-  public void update(final ServerStat s) {
-    final TransactionBenchmark t = (TransactionBenchmark) s;
-    if (!this.synced) {
-      this.synced = true;
-      this.since = t.since;
-      for (final String key : t.counts.keySet()) {
-        addBenchmark(this, key, t.acc.get(key), t.counts.get(key));
-      }
+  public TransactionBenchmark createBenchmark(String name) {
+    synchronized (subBenchmarks) {
+      SubBenchmark b = new SubBenchmark(name);
+      subBenchmarks.put(name, b);
+      return b;
     }
   }
 
-  /**
-   * Get a SubBenchmark which can be used to produce a separate benchmark (e.g. for single
-   * transactions). The SubBenchmark's data will also available to the main benchmark.
-   *
-   * @return A SubBenchmark
-   */
-  public static TransactionBenchmark getSubBenchmark() {
-    return new SubBenchmark();
+  public TransactionBenchmark getBenchmark(String name) {
+    synchronized (subBenchmarks) {
+      SubBenchmark existing = subBenchmarks.get(name);
+      if (existing != null) {
+        return existing;
+      } else {
+        SubBenchmark b = new SubBenchmark(name);
+        subBenchmarks.put(name, b);
+        return b;
+      }
+    }
   }
 
-  private static class SubBenchmark extends TransactionBenchmark {
-
-    private static final long serialVersionUID = 1L;
+  public TransactionBenchmark getBenchmark(Class<?> class1) {
+    return this.getBenchmark(class1.getSimpleName());
+  }
 
-    @Override
-    public void addBenchmark(final Object object, final long time) {
-      if (isActive) {
-        super.addBenchmark(object, time);
-        TransactionBenchmark.addBenchmark(this, object.toString(), time, 1);
-      }
-    }
+  public TransactionBenchmark createBenchmark(Class<?> class1) {
+    return this.createBenchmark(class1.getSimpleName());
   }
 }
diff --git a/src/main/java/caosdb/server/entity/Role.java b/src/main/java/caosdb/server/entity/Role.java
index 58cd7ba4f19ff89dad10a0a1c18fc3a417274255..79b6548f82f41568ec44c574c4ad35502379e58b 100644
--- a/src/main/java/caosdb/server/entity/Role.java
+++ b/src/main/java/caosdb/server/entity/Role.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.entity;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.GetIDByName;
 import caosdb.server.entity.xml.EntityToElementStrategy;
@@ -44,10 +43,16 @@ public enum Role {
     ids = new HashMap<Role, Integer>();
 
     for (final Role r : Role.values()) {
-      ids.put(r, Database.execute(new GetIDByName(r.name(), "ROLE"), access).getId());
+      ids.put(r, execute(new GetIDByName(r.name(), "ROLE"), access).getId());
     }
   }
 
+  private static GetIDByName execute(GetIDByName getIDByName, Access access) {
+    getIDByName.setAccess(access);
+    getIDByName.executeTransaction();
+    return getIDByName;
+  }
+
   public static Role parse(final String str) {
     for (final Role r : Role.values()) {
       if (r.toString().equalsIgnoreCase(str)) {
diff --git a/src/main/java/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/caosdb/server/entity/container/TransactionContainer.java
index ff799a4df5eb74a0d15e48a990e735af609925ec..ea4cc02e7d16bda586ff3c700e3f2fb237b15426 100644
--- a/src/main/java/caosdb/server/entity/container/TransactionContainer.java
+++ b/src/main/java/caosdb/server/entity/container/TransactionContainer.java
@@ -103,15 +103,15 @@ public class TransactionContainer extends Container<Entity> implements ToElement
   @Override
   public void addToElement(final Element element) {
     element.setAttribute("count", Integer.toString(size()));
+    if (this.benchmark != null && CaosDBServer.isDebugMode()) {
+      element.addContent(this.benchmark.toElememt());
+    }
     for (final ToElementable m : this.messages) {
       m.addToElement(element);
     }
     for (final EntityInterface entity : this) {
       entity.addToElement(element);
     }
-    if (this.benchmark != null && CaosDBServer.isDebugMode()) {
-      element.addContent(this.benchmark.toElememt());
-    }
   }
 
   public void print() {
@@ -180,7 +180,7 @@ public class TransactionContainer extends Container<Entity> implements ToElement
 
   public TransactionBenchmark getTransactionBenchmark() {
     if (this.benchmark == null) {
-      this.benchmark = TransactionBenchmark.getSubBenchmark();
+      this.benchmark = TransactionBenchmark.getRootInstance().createBenchmark(getClass());
     }
     return this.benchmark;
   }
diff --git a/src/main/java/caosdb/server/jobs/Job.java b/src/main/java/caosdb/server/jobs/Job.java
index 681098b76a9deb90bc05dbea6f13ad2acd937ea6..b3551b4dd92084e6296a57be4166b341efa68262 100644
--- a/src/main/java/caosdb/server/jobs/Job.java
+++ b/src/main/java/caosdb/server/jobs/Job.java
@@ -23,7 +23,7 @@
 package caosdb.server.jobs;
 
 import caosdb.server.CaosDBException;
-import caosdb.server.database.Database;
+import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.backend.transaction.GetIDByName;
 import caosdb.server.database.backend.transaction.IsSubType;
 import caosdb.server.database.backend.transaction.RetrieveFullEntity;
@@ -78,6 +78,10 @@ public abstract class Job extends AbstractObservable implements Observer {
     return getTransaction().getTransactor();
   }
 
+  public <K extends BackendTransaction> K execute(final K t) {
+    return getTransaction().execute(t, getTransaction().getAccess());
+  }
+
   protected ScheduledJob appendJob(final EntityInterface entity, final Class<? extends Job> clazz) {
     try {
       final Job job = clazz.newInstance();
@@ -156,8 +160,7 @@ public abstract class Job extends AbstractObservable implements Observer {
   }
 
   protected final boolean isValidSubTypeNoCache(final int child, final int parent) {
-    return child == parent
-        || Database.execute(new IsSubType(child, parent), getTransaction().getAccess()).isSubType();
+    return child == parent || execute(new IsSubType(child, parent)).isSubType();
   }
 
   protected final EntityInterface retrieveValidSparseEntityByName(final String name)
@@ -166,8 +169,7 @@ public abstract class Job extends AbstractObservable implements Observer {
   }
 
   protected final EntityInterface retrieveValidSparseEntityById(final Integer id) throws Message {
-    final EntityInterface ret =
-        Database.execute(new RetrieveSparseEntity(id), getTransaction().getAccess()).getEntity();
+    final EntityInterface ret = execute(new RetrieveSparseEntity(id)).getEntity();
     if (ret.getEntityStatus() == EntityStatus.NONEXISTENT) {
       throw ServerMessages.ENTITY_DOES_NOT_EXIST;
     }
@@ -175,17 +177,15 @@ public abstract class Job extends AbstractObservable implements Observer {
   }
 
   protected final EntityInterface retrieveValidEntity(Integer id) {
-    return Database.execute(new RetrieveFullEntity(id), getTransaction().getAccess())
-        .getContainer()
-        .get(0);
+    return execute(new RetrieveFullEntity(id)).getContainer().get(0);
   }
 
   protected final Integer retrieveValidIDByName(final String name) {
-    return Database.execute(new GetIDByName(name), getTransaction().getAccess()).getId();
+    return execute(new GetIDByName(name)).getId();
   }
 
   protected EntityInterface retrieveParentsOfValidEntity(final EntityInterface entity) {
-    Database.execute(new RetrieveParents(entity), getTransaction().getAccess());
+    execute(new RetrieveParents(entity));
     return entity;
   }
 
@@ -257,16 +257,16 @@ public abstract class Job extends AbstractObservable implements Observer {
   }
 
   protected List<Job> loadDataTypeSpecificJobs() {
-    return Job.loadDataTypeSpecificJobs(getEntity(), getTransaction());
+    return loadDataTypeSpecificJobs(getEntity(), getTransaction());
   }
 
-  public static List<Job> loadDataTypeSpecificJobs(
+  public List<Job> loadDataTypeSpecificJobs(
       final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) {
 
     return loadDataTypeSpecificJobs(entity.getDatatype(), entity, transaction);
   }
 
-  private static List<Job> loadDataTypeSpecificJobs(
+  private List<Job> loadDataTypeSpecificJobs(
       final AbstractDatatype dt,
       final EntityInterface entity,
       final Transaction<? extends TransactionContainer> transaction) {
@@ -275,19 +275,19 @@ public abstract class Job extends AbstractObservable implements Observer {
     }
     if (dt instanceof ReferenceDatatype2) {
       final RuleLoader t = new RuleLoader(0, 17, entity, transaction);
-      return Database.execute(t, transaction.getAccess()).getJobs();
+      return execute(t).getJobs();
     } else if (dt instanceof AbstractCollectionDatatype) {
       final AbstractDatatype datatype = ((AbstractCollectionDatatype) dt).getDatatype();
       return loadDataTypeSpecificJobs(datatype, entity, transaction);
     } else if (dt.getId() != null) {
       final RuleLoader t = new RuleLoader(0, dt.getId(), entity, transaction);
-      return Database.execute(t, transaction.getAccess()).getJobs();
+      return execute(t).getJobs();
     } else {
       return null;
     }
   }
 
-  public static List<Job> loadStandardJobs(
+  public List<Job> loadStandardJobs(
       final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) {
 
     final ArrayList<Job> jobs = new ArrayList<>();
@@ -302,13 +302,13 @@ public abstract class Job extends AbstractObservable implements Observer {
     // load general rules
     {
       final RuleLoader t = new RuleLoader(0, 0, entity, transaction);
-      jobs.addAll(Database.execute(t, transaction.getAccess()).getJobs());
+      jobs.addAll(execute(t).getJobs());
     }
 
     // load Role specific rules
     if (entity.hasRole()) {
       final RuleLoader t = new RuleLoader(0, entity.getRole().getId(), entity, transaction);
-      jobs.addAll(Database.execute(t, transaction.getAccess()).getJobs());
+      jobs.addAll(execute(t).getJobs());
     }
 
     // load data type specific rules
@@ -336,7 +336,7 @@ public abstract class Job extends AbstractObservable implements Observer {
     }
   }
 
-  public static List<Job> loadJobs(
+  public List<Job> loadJobs(
       final EntityInterface entity, final Transaction<? extends TransactionContainer> transaction) {
     final LinkedList<Job> jobs = new LinkedList<>();
 
diff --git a/src/main/java/caosdb/server/jobs/Schedule.java b/src/main/java/caosdb/server/jobs/Schedule.java
index 367fdcbd13c5830f46205ef05d386f98bb14492d..4e7f005f3d2f790008a991a0138d62013f6a545a 100644
--- a/src/main/java/caosdb/server/jobs/Schedule.java
+++ b/src/main/java/caosdb/server/jobs/Schedule.java
@@ -55,7 +55,7 @@ class ScheduledJob {
     this.job
         .getContainer()
         .getTransactionBenchmark()
-        .addBenchmark(this.job.getClass().getSimpleName(), this.runtime);
+        .addMeasurement(this.job.getClass().getSimpleName(), this.runtime);
   }
 
   void pause() {
diff --git a/src/main/java/caosdb/server/jobs/core/AccessControl.java b/src/main/java/caosdb/server/jobs/core/AccessControl.java
index 8b51cd582933d9c993c2427be7c399e7dc553df2..0dd2ef4740d1a17d6e6ed8b0cc04c8d66a56c918 100644
--- a/src/main/java/caosdb/server/jobs/core/AccessControl.java
+++ b/src/main/java/caosdb/server/jobs/core/AccessControl.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveSparseEntity;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.wrapper.Parent;
@@ -66,7 +65,7 @@ public class AccessControl extends ContainerJob {
       if (e.hasParents() && e.getParents().size() == 1) {
         final Parent par1 = e.getParents().get(0);
         if (par1.hasId() && par1.getId() > 0) {
-          Database.execute(new RetrieveSparseEntity(par1), getTransaction().getAccess());
+          execute(new RetrieveSparseEntity(par1));
         }
         if (par1.hasName()
             && par1.getName().equals("CommentAnnotation")
diff --git a/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java b/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java
index 407c6e549bdcb8968a7ca91093534574ec6e5e2e..a3d9f4e493b189e7fb49de69347c5b6149f9f885 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckChildDependencyExistent.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.GetChildren;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.jobs.EntityJob;
@@ -42,9 +41,7 @@ public class CheckChildDependencyExistent extends EntityJob {
   public final void run() {
     if (getEntity().getDomain() == null || getEntity().getDomain() == 0) {
 
-      final List<Integer> children =
-          Database.execute(new GetChildren(getEntity().getId()), getTransaction().getAccess())
-              .getList();
+      final List<Integer> children = execute(new GetChildren(getEntity().getId())).getList();
 
       // loop:
       for (final Integer id : children) {
diff --git a/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java b/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java
index b74a0319c981753a52d5fb962f9bf3add3347ba1..5af12ad71b4b3c5b12ac8321131b4d9cb29013d5 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckFileStorageConsistency.java
@@ -28,9 +28,9 @@ import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.Message;
 import caosdb.server.jobs.FlagJob;
 import caosdb.server.jobs.JobAnnotation;
+import caosdb.server.transaction.FileStorageConsistencyCheck;
 import caosdb.server.transaction.Retrieve;
 import caosdb.server.transaction.Transaction;
-import caosdb.server.utils.FileStorageConsistencyCheck;
 import caosdb.server.utils.FileUtils;
 import caosdb.server.utils.Observable;
 import caosdb.server.utils.Observer;
diff --git a/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java b/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java
index ead4248f63fe5af4bf6e35778ecc34c7e3459da4..bee056c5763593ce6ef6a71f713019fae30a8bb5 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckParOblPropPresent.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveFullEntity;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.StatementStatus;
@@ -49,8 +48,7 @@ public class CheckParOblPropPresent extends EntityJob {
     runJobFromSchedule(getEntity(), CheckParValid.class);
 
     if (getEntity().hasParents()) {
-      Database.execute(
-          new RetrieveFullEntity(getEntity().getParents()), getTransaction().getAccess());
+      execute(new RetrieveFullEntity(getEntity().getParents()));
     }
 
     // inherit properties
diff --git a/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java b/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java
index eec99f5ed00384d4be447a7ef3cd51b19178dccf..fd5eaab0f0d302e9b5586693ef502c32d607d773 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckReferenceDependencyExistent.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.GetDependentEntities;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.jobs.EntityJob;
@@ -45,9 +44,7 @@ public class CheckReferenceDependencyExistent extends EntityJob {
 
       // retrieve dependent entities
       final List<Integer> depends =
-          Database.execute(
-                  new GetDependentEntities(getEntity().getId()), getTransaction().getAccess())
-              .getList();
+          execute(new GetDependentEntities(getEntity().getId())).getList();
 
       // loop:
       for (final Integer id : depends) {
diff --git a/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java b/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java
index 3dc0c4bba460dfa7f6eb2eec338e5dea738da9e2..404e6b3a0d82950061ba4168a7a6f32e5f847400 100644
--- a/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java
+++ b/src/main/java/caosdb/server/jobs/core/CheckTargetPathValid.java
@@ -55,7 +55,8 @@ public class CheckTargetPathValid extends EntityJob {
       }
 
       try {
-        FileSystem.checkTarget(getEntity(), getTransaction().getAccess());
+        FileSystem.checkTarget(
+            getEntity(), getTransaction().getAccess(), getTransaction().getTransactionBenchmark());
       } catch (final Message m) {
         getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
         getEntity().addError(m);
diff --git a/src/main/java/caosdb/server/jobs/core/History.java b/src/main/java/caosdb/server/jobs/core/History.java
index 7e7643040196333b923536b13d8b84ae6b962311..ee72413a46e65f8b8a020315e3c2e93c7b8ccd97 100644
--- a/src/main/java/caosdb/server/jobs/core/History.java
+++ b/src/main/java/caosdb/server/jobs/core/History.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveTransactionHistory;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.jobs.FlagJob;
@@ -44,7 +43,7 @@ public class History extends FlagJob {
           try {
             entity.checkPermission(EntityPermission.RETRIEVE_HISTORY);
             final RetrieveTransactionHistory t = new RetrieveTransactionHistory(entity);
-            Database.execute(t, getTransaction().getAccess());
+            execute(t);
           } catch (final AuthorizationException e) {
             entity.setEntityStatus(EntityStatus.UNQUALIFIED);
             entity.addError(ServerMessages.AUTHORIZATION_ERROR);
diff --git a/src/main/java/caosdb/server/jobs/core/Inheritance.java b/src/main/java/caosdb/server/jobs/core/Inheritance.java
index ed25c64cbf02d16566addc79961e36e0fdffad81..f7149eb3c74270012db011385e17bbf01fdd01a2 100644
--- a/src/main/java/caosdb/server/jobs/core/Inheritance.java
+++ b/src/main/java/caosdb/server/jobs/core/Inheritance.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveFullEntity;
 import caosdb.server.entity.Entity;
 import caosdb.server.entity.EntityInterface;
@@ -74,7 +73,7 @@ public class Inheritance extends EntityJob {
 
             runJobFromSchedule(getEntity(), CheckParValid.class);
 
-            Database.execute(new RetrieveFullEntity(parent), getTransaction().getAccess());
+            execute(new RetrieveFullEntity(parent));
 
             if (parent.hasProperties()) {
               // loop over all properties of the parent and
@@ -163,7 +162,7 @@ public class Inheritance extends EntityJob {
                 }
               }
             } else {
-              Database.execute(new RetrieveFullEntity(validProperty), getTransaction().getAccess());
+              execute(new RetrieveFullEntity(validProperty));
             }
 
             if (validProperty.getEntityStatus() == EntityStatus.VALID
diff --git a/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java b/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java
index 9dbc2a68b684b7a5757a00c816f81f3716e55dc9..7db04f124aa45b81d3484db3a9d0ea33ca74a5ba 100644
--- a/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java
+++ b/src/main/java/caosdb/server/jobs/core/InsertFilesInDir.java
@@ -224,7 +224,10 @@ public class InsertFilesInDir extends FlagJob {
             // add create symlink and file record to this
             // container if the target
             // path is allowed
-            if (FileSystem.checkTarget(newFileEntity, getTransaction().getAccess())
+            if (FileSystem.checkTarget(
+                    newFileEntity,
+                    getTransaction().getAccess(),
+                    getTransaction().getTransactionBenchmark())
                 && newFileEntity.getEntityStatus() != EntityStatus.UNQUALIFIED) {
 
               final File link =
@@ -301,7 +304,7 @@ public class InsertFilesInDir extends FlagJob {
   }
 
   private void loadJobs(final Entity e) {
-    final List<Job> loadJobs = Job.loadJobs(e, getTransaction());
+    final List<Job> loadJobs = loadJobs(e, getTransaction());
     getTransaction().getSchedule().addAll(loadJobs);
   }
 
diff --git a/src/main/java/caosdb/server/jobs/core/ResolveNames.java b/src/main/java/caosdb/server/jobs/core/ResolveNames.java
index fd5498f468e44801279655ba21a1702da12c168e..f5e1695f34c30a78f136950f7aae3ae00be170e4 100644
--- a/src/main/java/caosdb/server/jobs/core/ResolveNames.java
+++ b/src/main/java/caosdb/server/jobs/core/ResolveNames.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.GetIDByName;
 import caosdb.server.database.exceptions.EntityDoesNotExistException;
 import caosdb.server.entity.Entity;
@@ -45,9 +44,7 @@ public class ResolveNames extends ContainerJob {
     for (final Entity e : container) {
       if (e.hasName() && !e.hasId()) {
         try {
-          final List<Integer> c =
-              Database.execute(new GetIDByName(e.getName(), false), getTransaction().getAccess())
-                  .getList();
+          final List<Integer> c = execute(new GetIDByName(e.getName(), false)).getList();
 
           e.setId(c.get(0));
           e.setEntityStatus(EntityStatus.QUALIFIED);
diff --git a/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java b/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java
index f522986c6b40ed73fdbb752226a7dd66de4d040e..0fba1223a3bd0e984c5c2b6ff43dd58070b5bbc5 100644
--- a/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java
+++ b/src/main/java/caosdb/server/jobs/core/RetrieveAllJob.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveAll;
 import caosdb.server.jobs.FlagJob;
 import caosdb.server.jobs.JobAnnotation;
@@ -37,7 +36,7 @@ public class RetrieveAllJob extends FlagJob {
       if (value == null) {
         value = "ENTITY";
       }
-      Database.execute(new RetrieveAll(getContainer(), value), getTransaction().getAccess());
+      execute(new RetrieveAll(getContainer(), value));
     }
   }
 }
diff --git a/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java b/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java
index 86f5b2d23721e97cef6e1b9ebd356cbf140b0cc6..8d0118b80582e3a65b613caae2200719af428819 100644
--- a/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java
+++ b/src/main/java/caosdb/server/jobs/core/UpdateUnitConverters.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.jobs.core;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.InsertLinCon;
 import caosdb.server.jobs.EntityJob;
 import caosdb.server.jobs.JobAnnotation;
@@ -66,7 +65,7 @@ public class UpdateUnitConverters extends EntityJob {
     if (signature_from != signature_to) {
       final InsertLinCon t =
           new InsertLinCon(signature_from, signature_to, a, b_dividend, b_divisor, c);
-      Database.execute(t, getTransaction().getAccess());
+      execute(t);
     }
   }
 }
diff --git a/src/main/java/caosdb/server/query/Backreference.java b/src/main/java/caosdb/server/query/Backreference.java
index f8d4f86f5d04d6b724a3fdec66c1a24d739726af..c39ce43923372811caf8607550a9852d1a518c63 100644
--- a/src/main/java/caosdb/server/query/Backreference.java
+++ b/src/main/java/caosdb/server/query/Backreference.java
@@ -192,7 +192,7 @@ public class Backreference implements EntityFilterInterface, QueryInterface {
     addBenchmark("initBackreference()", t2 - t1);
 
     if (this.entitiesTable != null) {
-      Query.applyQueryTemplates(query, this.entitiesTable);
+      getQuery().applyQueryTemplates(query, this.entitiesTable);
       addBenchmark("applyQueryTemplates()", System.currentTimeMillis() - t2);
     }
   }
diff --git a/src/main/java/caosdb/server/query/POV.java b/src/main/java/caosdb/server/query/POV.java
index 01d2cb1b9bb2bd51e18ccacc438ff8ac75788762..6a57caa780d76c5279a37eaba09d44c021215d7c 100644
--- a/src/main/java/caosdb/server/query/POV.java
+++ b/src/main/java/caosdb/server/query/POV.java
@@ -412,7 +412,7 @@ public class POV implements EntityFilterInterface {
     query.addBenchmark(getClass().getSimpleName() + ".initPOVPropertiesTable()", t3 - t2);
 
     if (this.refIdsTable != null) {
-      Query.applyQueryTemplates(query, this.refIdsTable);
+      query.getQuery().applyQueryTemplates(query, this.refIdsTable);
       query.addBenchmark(
           getClass().getSimpleName() + ".applyQueryTemplates()", System.currentTimeMillis() - t3);
     }
diff --git a/src/main/java/caosdb/server/query/Query.java b/src/main/java/caosdb/server/query/Query.java
index d3e0e927d14d0b2021f056ad52f10df548c5734c..a62a6acae9bcc413e7ab06c812312f8e8b8fe323 100644
--- a/src/main/java/caosdb/server/query/Query.java
+++ b/src/main/java/caosdb/server/query/Query.java
@@ -26,7 +26,6 @@ import static caosdb.server.database.DatabaseUtils.bytes2UTF8;
 
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.implementation.MySQL.ConnectionException;
 import caosdb.server.database.backend.implementation.MySQL.MySQLHelper;
@@ -284,7 +283,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
    * @throws SQLException
    * @throws QueryException
    */
-  public static void applyQueryTemplates(final QueryInterface query, final String resultSet)
+  public void applyQueryTemplates(final QueryInterface query, final String resultSet)
       throws QueryException {
     try {
       final Map<Integer, String> queryTemplates = getQueryTemplates(query, resultSet);
@@ -300,7 +299,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
 
         // ... check for RETRIEVE:ENTITY permission...
         final EntityInterface e =
-            Database.execute(new RetrieveSparseEntity(q.getKey()), query.getAccess()).getEntity();
+            execute(new RetrieveSparseEntity(q.getKey()), query.getAccess()).getEntity();
         final EntityACL entityACL = e.getEntityACL();
         if (!entityACL.isPermitted(query.getUser(), EntityPermission.RETRIEVE_ENTITY)) {
           // ... and ignore if not.
@@ -436,7 +435,9 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     this.filter = cq.filter;
     this.selections = cq.s;
     final long t2 = System.currentTimeMillis();
-    addBenchmark("parse (" + this.query + ")", t2 - t1);
+    if (t2 - t1 > 1000) {
+      addBenchmark("LONG_PARSING: " + this.query, t2 - t1);
+    }
   }
 
   private String executeStrategy() throws QueryException {
@@ -531,8 +532,6 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     this.access = access;
   }
 
-  private final TransactionBenchmark benchmark = TransactionBenchmark.getSubBenchmark();
-
   /**
    * Filter out all entities which may not be retrieved by this user due to a missing RETRIEVE
    * permission. This one is also designed for filtering of intermediate results.
@@ -542,7 +541,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
    * @throws SQLException
    * @throws TransactionException
    */
-  public static void filterEntitiesWithoutRetrievePermission(
+  public void filterEntitiesWithoutRetrievePermission(
       final QueryInterface query, final String resultSet)
       throws SQLException, TransactionException {
     if (!filterEntitiesWithoutRetrievePermisions) {
@@ -554,7 +553,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
       while (rs.next()) {
         final long t1 = System.currentTimeMillis();
         final Integer id = rs.getInt("id");
-        if (!Database.execute(new RetrieveSparseEntity(id), query.getAccess())
+        if (!execute(new RetrieveSparseEntity(id), query.getAccess())
             .getEntity()
             .getEntityACL()
             .isPermitted(query.getUser(), EntityPermission.RETRIEVE_ENTITY)) {
@@ -587,7 +586,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
     while (iterator.hasNext()) {
       final long t1 = System.currentTimeMillis();
       final Integer id = iterator.next();
-      if (!Database.execute(new RetrieveSparseEntity(id), getAccess())
+      if (!execute(new RetrieveSparseEntity(id), getAccess())
           .getEntity()
           .getEntityACL()
           .isPermitted(getUser(), EntityPermission.RETRIEVE_ENTITY)) {
@@ -641,6 +640,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
 
   private int targetSetCount = -1;
 
+  private TransactionBenchmark benchmark;
+
   @Override
   public void addToElement(final Element parent) {
     final Element ret = new Element("Query");
@@ -695,8 +696,6 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
       ret.addContent(selection);
     }
 
-    ret.addContent(this.benchmark.toElememt());
-
     parent.addContent(ret);
   }
 
@@ -726,6 +725,19 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
 
   @Override
   public void addBenchmark(final String str, final long time) {
-    this.benchmark.addBenchmark(this.getClass().getSimpleName().toString() + "." + str, time);
+    getTransactionBenchmark()
+        .addMeasurement(this.getClass().getSimpleName().toString() + "." + str, time);
+  }
+
+  @Override
+  public TransactionBenchmark getTransactionBenchmark() {
+    if (benchmark == null) {
+      if (container != null) {
+        benchmark = container.getTransactionBenchmark().getBenchmark(getClass());
+      } else {
+        benchmark = TransactionBenchmark.getRootInstance().getBenchmark(getClass());
+      }
+    }
+    return benchmark;
   }
 }
diff --git a/src/main/java/caosdb/server/query/SubProperty.java b/src/main/java/caosdb/server/query/SubProperty.java
index a5abe0b7b6cd3940f16cfe29461c13a019416d41..12629640ec4e7780c1b1d5933e7d6e1711f635f7 100644
--- a/src/main/java/caosdb/server/query/SubProperty.java
+++ b/src/main/java/caosdb/server/query/SubProperty.java
@@ -87,7 +87,7 @@ public class SubProperty implements QueryInterface, EntityFilterInterface {
 
         this.filter.apply(this);
 
-        Query.filterEntitiesWithoutRetrievePermission(this, this.sourceSet);
+        getQuery().filterEntitiesWithoutRetrievePermission(this, this.sourceSet);
 
         final CallableStatement callFinishSubProperty =
             getConnection().prepareCall("call finishSubProperty(?,?,?)");
diff --git a/src/main/java/caosdb/server/resource/FileSystemResource.java b/src/main/java/caosdb/server/resource/FileSystemResource.java
index 0e8d59a107d3f8dbb83d966a9e251641ac9bdd8a..290a88801b4f14401981f9d91a6ba00cf27c12a4 100644
--- a/src/main/java/caosdb/server/resource/FileSystemResource.java
+++ b/src/main/java/caosdb/server/resource/FileSystemResource.java
@@ -117,7 +117,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
       rootElem.addContent(folder);
       final long t2 = System.currentTimeMillis();
 
-      getBenchmark().addBenchmark(this.getClass().getSimpleName(), t2 - t1);
+      getBenchmark().addMeasurement(this.getClass().getSimpleName(), t2 - t1);
       rootElem.addContent(getBenchmark().toElememt());
       final Document doc = new Document(rootElem);
       return ok(doc);
@@ -132,6 +132,10 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
     }
   }
 
+  TransactionBenchmark getBenchmark() {
+    return TransactionBenchmark.getRootInstance().getBenchmark(getClass());
+  }
+
   protected Attribute getThumbnailAttribute(
       final File file, final File child, final String referenceString) {
     final String thpath =
@@ -145,15 +149,6 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
     return null;
   }
 
-  private TransactionBenchmark benchmark;
-
-  private TransactionBenchmark getBenchmark() {
-    if (this.benchmark == null) {
-      this.benchmark = TransactionBenchmark.getSubBenchmark();
-    }
-    return this.benchmark;
-  }
-
   Element getFileElement(final String directory, final File file) throws Exception {
     final Element celem = new Element("file");
     celem.setAttribute(
@@ -177,7 +172,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
     final Transaction<?> t = new RetrieveSparseEntityByPath(c);
     t.execute();
     final long t2 = System.currentTimeMillis();
-    getBenchmark().addBenchmark(this.getClass().getSimpleName() + ".getEntity", t2 - t1);
+    getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".getEntity", t2 - t1);
     return e;
   }
 
@@ -193,7 +188,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
     final long t1 = System.currentTimeMillis();
     getEntity(path).checkPermission(EntityPermission.RETRIEVE_FILE);
     final long t2 = System.currentTimeMillis();
-    getBenchmark().addBenchmark(this.getClass().getSimpleName() + ".checkPermissions", t2 - t1);
+    getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".checkPermissions", t2 - t1);
   }
 
   @Override
diff --git a/src/main/java/caosdb/server/resource/InfoResource.java b/src/main/java/caosdb/server/resource/InfoResource.java
index c2342cc46f7e62fd6a398218b39e804ab9f1767d..924d66980e5da27ec998fd361b95a8f0769e4229 100644
--- a/src/main/java/caosdb/server/resource/InfoResource.java
+++ b/src/main/java/caosdb/server/resource/InfoResource.java
@@ -45,7 +45,7 @@ public class InfoResource extends AbstractCaosDBServerResource {
     final Element root = generateRootElement();
     root.addContent(Info.toElement());
     root.addContent(FlagInfo.toElement());
-    root.addContent(TransactionBenchmark.getInstance().toElememt());
+    root.addContent(TransactionBenchmark.getRootInstance().toElememt());
     doc.setRootElement(root);
     return ok(doc);
   }
diff --git a/src/main/java/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/caosdb/server/resource/transaction/EntityResource.java
index 54882bcab6211bdbbd6921871ef4709413738543..0c853096c1af71dcacf2ef775c46f4dceecb1673 100644
--- a/src/main/java/caosdb/server/resource/transaction/EntityResource.java
+++ b/src/main/java/caosdb/server/resource/transaction/EntityResource.java
@@ -115,7 +115,7 @@ public class EntityResource extends AbstractCaosDBServerResource {
     final long t2 = System.currentTimeMillis();
     entityContainer
         .getTransactionBenchmark()
-        .addBenchmark(getClass().getSimpleName() + ".httpGetInChildClass", t2 - t1);
+        .addMeasurement(getClass().getSimpleName() + ".httpGetInChildClass", t2 - t1);
     final Element rootElem = generateRootElement();
     entityContainer.addToElement(rootElem);
     doc.setRootElement(rootElem);
diff --git a/src/main/java/caosdb/server/utils/ChecksumUpdater.java b/src/main/java/caosdb/server/transaction/ChecksumUpdater.java
similarity index 92%
rename from src/main/java/caosdb/server/utils/ChecksumUpdater.java
rename to src/main/java/caosdb/server/transaction/ChecksumUpdater.java
index 6a1e0e927002eff7669d3a6dc7bcae39e761d859..30313478c263a131658005daa39da3b495c85eb2 100644
--- a/src/main/java/caosdb/server/utils/ChecksumUpdater.java
+++ b/src/main/java/caosdb/server/transaction/ChecksumUpdater.java
@@ -20,10 +20,9 @@
  *
  * ** end header
  */
-package caosdb.server.utils;
+package caosdb.server.transaction;
 
 import caosdb.server.CaosDBException;
-import caosdb.server.database.Database;
 import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.GetUpdateableChecksums;
@@ -34,7 +33,7 @@ import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.FileProperties;
 import caosdb.server.entity.Message;
 import caosdb.server.entity.container.TransactionContainer;
-import caosdb.server.transaction.WriteTransaction;
+import caosdb.server.utils.FileUtils;
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 
@@ -86,7 +85,7 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl
           DatabaseMonitor.getInstance().acquireStrongAccess(this);
 
           // update
-          Database.execute(new UpdateSparseEntity(fileEntity), strongAccess);
+          execute(new UpdateSparseEntity(fileEntity), strongAccess);
           strongAccess.commit();
 
         } catch (final InterruptedException e) {
@@ -108,7 +107,7 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl
       final EntityInterface fileEntity, final Access access, final long lastModified)
       throws NoSuchAlgorithmException, IOException, CaosDBException, Message {
     final EntityInterface checkEntity =
-        Database.execute(new RetrieveSparseEntity(fileEntity), access).getEntity();
+        execute(new RetrieveSparseEntity(fileEntity), access).getEntity();
     final FileProperties thatFP = checkEntity.getFileProperties();
     final FileProperties thisFP = fileEntity.getFileProperties();
 
@@ -136,13 +135,13 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl
       synchronized (instance.running) {
 
         // test for updatable checksums
-        final Integer id = Database.execute(new GetUpdateableChecksums(), weakAccess).getID();
+        final Integer id = execute(new GetUpdateableChecksums(), weakAccess).getID();
         if (id == null) {
           // nothing to be updated...
           instance.running = false;
           return null;
         }
-        return Database.execute(new RetrieveSparseEntity(id), weakAccess).getEntity();
+        return execute(new RetrieveSparseEntity(id), weakAccess).getEntity();
       }
     } catch (final Exception e) {
       e.printStackTrace();
diff --git a/src/main/java/caosdb/server/transaction/Delete.java b/src/main/java/caosdb/server/transaction/Delete.java
index f371f0d64e32ddc5a6f4812943b2c9be08b5bcbc..1d3aacbc78043fef6982b2b7663dc5d033e50e50 100644
--- a/src/main/java/caosdb/server/transaction/Delete.java
+++ b/src/main/java/caosdb/server/transaction/Delete.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.transaction;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.DeleteEntity;
 import caosdb.server.database.backend.transaction.RetrieveFullEntity;
@@ -53,7 +52,7 @@ public class Delete extends WriteTransaction<DeleteContainer> {
     setAccess(getMonitor().allocateStrongAccess(this));
 
     // retrieve all entities which are to be deleted.
-    Database.execute(new RetrieveFullEntity(getContainer()), getAccess());
+    execute(new RetrieveFullEntity(getContainer()), getAccess());
 
     for (final EntityInterface e : getContainer()) {
       if (e.getEntityStatus() == EntityStatus.NONEXISTENT) {
@@ -104,10 +103,9 @@ public class Delete extends WriteTransaction<DeleteContainer> {
     delete(getContainer(), getAccess());
   }
 
-  private static void delete(final TransactionContainer container, final Access access)
-      throws Exception {
+  private void delete(final TransactionContainer container, final Access access) throws Exception {
     if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) {
-      Database.execute(new DeleteEntity(container), access);
+      execute(new DeleteEntity(container), access);
     }
   }
 
diff --git a/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java b/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java
index 3f3758823a2b554edbfb1e400c2a8f2f14916ba1..e1ba3bec80663cb3b30d2dbdc48d9f9024c8f2d7 100644
--- a/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java
+++ b/src/main/java/caosdb/server/transaction/DeleteRoleTransaction.java
@@ -23,7 +23,6 @@
 package caosdb.server.transaction;
 
 import caosdb.server.accessControl.ACMPermissions;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.DeleteRole;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.database.backend.transaction.SetPermissionRules;
@@ -42,10 +41,10 @@ public class DeleteRoleTransaction extends AccessControlTransaction {
   protected void transaction() throws Exception {
     SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_DELETE_ROLE(this.name));
 
-    if (Database.execute(new RetrieveRole(this.name), getAccess()).getRole() == null) {
+    if (execute(new RetrieveRole(this.name), getAccess()).getRole() == null) {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
-    Database.execute(new SetPermissionRules(this.name, null), getAccess());
-    Database.execute(new DeleteRole(this.name), getAccess());
+    execute(new SetPermissionRules(this.name, null), getAccess());
+    execute(new DeleteRole(this.name), getAccess());
   }
 }
diff --git a/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java b/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java
index 729512a2a6dfae734b152e2ddd4c1e71362681d5..cdedce31b34153494ceb0be28e4c3a9da360bb6e 100644
--- a/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java
+++ b/src/main/java/caosdb/server/transaction/DeleteUserTransaction.java
@@ -25,7 +25,6 @@ package caosdb.server.transaction;
 import caosdb.server.accessControl.ACMPermissions;
 import caosdb.server.accessControl.CredentialsValidator;
 import caosdb.server.accessControl.UserSources;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.DeletePassword;
 import caosdb.server.database.backend.transaction.DeleteUser;
 import caosdb.server.database.backend.transaction.RetrievePasswordValidator;
@@ -51,14 +50,14 @@ public class DeleteUserTransaction extends AccessControlTransaction {
         .checkPermission(ACMPermissions.PERMISSION_DELETE_USER(this.realm, this.user));
 
     final CredentialsValidator<String> validator =
-        Database.execute(new RetrievePasswordValidator(this.user), getAccess()).getValidator();
+        execute(new RetrievePasswordValidator(this.user), getAccess()).getValidator();
 
     if (validator == null) {
       throw ServerMessages.ACCOUNT_DOES_NOT_EXIST;
     }
 
-    Database.execute(new DeletePassword(this.user), getAccess());
-    Database.execute(new DeleteUser(this.realm, this.user), getAccess());
+    execute(new DeletePassword(this.user), getAccess());
+    execute(new DeleteUser(this.realm, this.user), getAccess());
   }
 
   public Element getUserElement() {
diff --git a/src/main/java/caosdb/server/utils/FileStorageConsistencyCheck.java b/src/main/java/caosdb/server/transaction/FileStorageConsistencyCheck.java
similarity index 91%
rename from src/main/java/caosdb/server/utils/FileStorageConsistencyCheck.java
rename to src/main/java/caosdb/server/transaction/FileStorageConsistencyCheck.java
index c750bb4e6f4de884cf39289d82df79138206f057..d1055b5e4c4a3bf0676883cc221e60d47442f304 100644
--- a/src/main/java/caosdb/server/utils/FileStorageConsistencyCheck.java
+++ b/src/main/java/caosdb/server/transaction/FileStorageConsistencyCheck.java
@@ -20,10 +20,9 @@
  *
  * ** end header
  */
-package caosdb.server.utils;
+package caosdb.server.transaction;
 
 import caosdb.datetime.UTCDateTime;
-import caosdb.server.database.Database;
 import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.FileConsistencyCheck;
@@ -34,7 +33,7 @@ import caosdb.server.database.backend.transaction.SetFileCheckedTimestamp;
 import caosdb.server.database.proto.SparseEntity;
 import caosdb.server.entity.Message;
 import caosdb.server.entity.xml.ToElementable;
-import caosdb.server.transaction.TransactionInterface;
+import caosdb.server.utils.SHA512;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -69,7 +68,7 @@ public class FileStorageConsistencyCheck extends Thread
 
       // test all files in file system.
       final Iterator<String> iterator =
-          Database.execute(new GetFileIterator(this.location), this.access).getIterator();
+          execute(new GetFileIterator(this.location), this.access).getIterator();
 
       this.ts = System.currentTimeMillis();
       while (iterator != null && iterator.hasNext()) {
@@ -87,14 +86,14 @@ public class FileStorageConsistencyCheck extends Thread
           continue;
         }
 
-        final GetFileRecordByPath t = Database.execute(new GetFileRecordByPath(path), this.access);
+        final GetFileRecordByPath t = execute(new GetFileRecordByPath(path), this.access);
 
         if (t.getEntity() == null) {
           this.results.put(path, FileConsistencyCheck.UNKNOWN_FILE);
           continue;
         }
         final int result =
-            Database.execute(
+            execute(
                     new FileConsistencyCheck(
                         path, t.getSize(), t.getHash(), t.getLastConsistencyCheck(), new SHA512()),
                     this.access)
@@ -104,18 +103,17 @@ public class FileStorageConsistencyCheck extends Thread
           this.results.put(path, result);
         }
 
-        Database.execute(new SetFileCheckedTimestamp(t.getId(), this.ts), this.access);
+        execute(new SetFileCheckedTimestamp(t.getId(), this.ts), this.access);
       }
 
       // test all remaining file records
       final Iterator<SparseEntity> iterator2 =
-          Database.execute(new RetrieveAllUncheckedFiles(this.ts, this.location), this.access)
-              .getIterator();
+          execute(new RetrieveAllUncheckedFiles(this.ts, this.location), this.access).getIterator();
       while (iterator2 != null && iterator2.hasNext()) {
 
         final SparseEntity entity = iterator2.next();
         final int result =
-            Database.execute(
+            execute(
                     new FileConsistencyCheck(
                         entity.filePath,
                         entity.fileSize,
@@ -129,7 +127,7 @@ public class FileStorageConsistencyCheck extends Thread
           this.results.put(entity.filePath, result);
         }
 
-        Database.execute(new SetFileCheckedTimestamp(entity.id, this.ts), this.access);
+        execute(new SetFileCheckedTimestamp(entity.id, this.ts), this.access);
       }
 
     } catch (final Exception e) {
diff --git a/src/main/java/caosdb/server/transaction/Insert.java b/src/main/java/caosdb/server/transaction/Insert.java
index 0dbda080ce33ea1fbcfdd4f43f36860f44e55db1..627ada52655c5e7802e98172d1c32f8280a95fb4 100644
--- a/src/main/java/caosdb/server/transaction/Insert.java
+++ b/src/main/java/caosdb/server/transaction/Insert.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.transaction;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.InsertEntity;
 import caosdb.server.entity.EntityInterface;
@@ -101,10 +100,9 @@ public class Insert extends WriteTransaction<InsertContainer> {
     insert(getContainer(), getAccess());
   }
 
-  public static void insert(final TransactionContainer container, final Access access)
-      throws Exception {
+  public void insert(final TransactionContainer container, final Access access) throws Exception {
     if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) {
-      Database.execute(new InsertEntity(container), access);
+      execute(new InsertEntity(container), access);
     }
   }
 
diff --git a/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java b/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java
index 89b48418843f326ac42bf49f96b0e6dfa8d0f17a..3762b0bed3f726dd521f754043d0e99a5d2a3913 100644
--- a/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java
+++ b/src/main/java/caosdb/server/transaction/InsertLogRecordTransaction.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.transaction;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.InsertLogRecord;
@@ -41,7 +40,7 @@ public class InsertLogRecordTransaction implements TransactionInterface {
   public void execute() throws Exception {
     final Access access = DatabaseMonitor.getInstance().acquiredWeakAccess(this);
     try {
-      Database.execute(new InsertLogRecord(this.toBeFlushed), access);
+      execute(new InsertLogRecord(this.toBeFlushed), access);
     } finally {
       access.release();
     }
diff --git a/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java b/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java
index 250ca37bba0eedaba25d105072617b20fbf94cd5..8377210690692c8819e5197e35a8e549d27f2a30 100644
--- a/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java
+++ b/src/main/java/caosdb/server/transaction/InsertRoleTransaction.java
@@ -24,7 +24,6 @@ package caosdb.server.transaction;
 
 import caosdb.server.accessControl.ACMPermissions;
 import caosdb.server.accessControl.Role;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.InsertRole;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.utils.ServerMessages;
@@ -42,10 +41,10 @@ public class InsertRoleTransaction extends AccessControlTransaction {
   protected void transaction() throws Exception {
     SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_INSERT_ROLE());
 
-    if (Database.execute(new RetrieveRole(this.role.name), getAccess()).getRole() != null) {
+    if (execute(new RetrieveRole(this.role.name), getAccess()).getRole() != null) {
       throw ServerMessages.ROLE_NAME_IS_NOT_UNIQUE;
     }
 
-    Database.execute(new InsertRole(this.role), getAccess());
+    execute(new InsertRole(this.role), getAccess());
   }
 }
diff --git a/src/main/java/caosdb/server/transaction/InsertUserTransaction.java b/src/main/java/caosdb/server/transaction/InsertUserTransaction.java
index d6cc2f46b397cf194a32f6ab5d7ec7e7fdc7407c..75b876b8bc291ea246746b4a8e85ccd26055c173 100644
--- a/src/main/java/caosdb/server/transaction/InsertUserTransaction.java
+++ b/src/main/java/caosdb/server/transaction/InsertUserTransaction.java
@@ -25,7 +25,6 @@ package caosdb.server.transaction;
 import caosdb.server.accessControl.ACMPermissions;
 import caosdb.server.accessControl.UserSources;
 import caosdb.server.accessControl.UserStatus;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrievePasswordValidator;
 import caosdb.server.database.backend.transaction.SetPassword;
 import caosdb.server.database.backend.transaction.UpdateUser;
@@ -67,14 +66,14 @@ public class InsertUserTransaction extends AccessControlTransaction {
       UpdateUserTransaction.checkEntityExists(this.user.entity);
     }
 
-    if (Database.execute(new RetrievePasswordValidator(this.user.name), getAccess()).getValidator()
+    if (execute(new RetrievePasswordValidator(this.user.name), getAccess()).getValidator()
         == null) {
       if (this.password != null) {
         Utils.checkPasswordStrength(this.password);
       }
 
-      Database.execute(new SetPassword(this.user.name, this.password), getAccess());
-      Database.execute(new UpdateUser(this.user), getAccess());
+      execute(new SetPassword(this.user.name, this.password), getAccess());
+      execute(new UpdateUser(this.user), getAccess());
     } else {
       throw ServerMessages.ACCOUNT_NAME_NOT_UNIQUE;
     }
diff --git a/src/main/java/caosdb/server/transaction/Retrieve.java b/src/main/java/caosdb/server/transaction/Retrieve.java
index 3110ee97e68e38a955ad0ae146228a27eb7677d6..0de1b8e06b66a4293668fb499fb28f33fa398187 100644
--- a/src/main/java/caosdb/server/transaction/Retrieve.java
+++ b/src/main/java/caosdb/server/transaction/Retrieve.java
@@ -22,11 +22,9 @@
  */
 package caosdb.server.transaction;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.RetrieveFullEntity;
 import caosdb.server.entity.EntityInterface;
-import caosdb.server.entity.container.Container;
 import caosdb.server.entity.container.RetrieveContainer;
 import caosdb.server.entity.xml.SetFieldStrategy;
 import caosdb.server.entity.xml.ToElementStrategy;
@@ -137,9 +135,9 @@ public class Retrieve extends Transaction<RetrieveContainer> {
     retrieveFullEntities(getContainer(), getAccess());
   }
 
-  private static void retrieveFullEntities(
-      final Container<? extends EntityInterface> container, final Access access) throws Exception {
-    Database.execute(new RetrieveFullEntity(container), access);
+  private void retrieveFullEntities(final RetrieveContainer container, final Access access)
+      throws Exception {
+    execute(new RetrieveFullEntity(container), access);
   }
 
   @Override
diff --git a/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java
index 14b5ea3140b685db77be79ff680180fea6e379b3..bbe2e1f11a7bd4c7705a790dec78903fb0e7c20a 100644
--- a/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java
+++ b/src/main/java/caosdb/server/transaction/RetrieveLogRecordTransaction.java
@@ -23,7 +23,6 @@
 package caosdb.server.transaction;
 
 import caosdb.server.accessControl.ACMPermissions;
-import caosdb.server.database.Database;
 import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.RetrieveLogRecord;
@@ -64,7 +63,7 @@ public class RetrieveLogRecordTransaction implements TransactionInterface {
     final Access access = DatabaseMonitor.getInstance().acquiredWeakAccess(this);
     try {
       this.logRecords =
-          Database.execute(new RetrieveLogRecord(this.logger, this.level, this.message), access)
+          execute(new RetrieveLogRecord(this.logger, this.level, this.message), access)
               .getLogRecords();
     } finally {
       access.release();
diff --git a/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java b/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java
index 15817a5b405d18f80b23e26ac8b16d3a545483dd..d18b5c306373d6b89aa924bd154db444fbdb8f9a 100644
--- a/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java
+++ b/src/main/java/caosdb/server/transaction/RetrievePasswordValidatorTransaction.java
@@ -23,7 +23,6 @@
 package caosdb.server.transaction;
 
 import caosdb.server.accessControl.CredentialsValidator;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrievePasswordValidator;
 import caosdb.server.utils.ServerMessages;
 
@@ -38,8 +37,7 @@ public class RetrievePasswordValidatorTransaction extends AccessControlTransacti
 
   @Override
   protected void transaction() throws Exception {
-    this.validator =
-        Database.execute(new RetrievePasswordValidator(this.name), getAccess()).getValidator();
+    this.validator = execute(new RetrievePasswordValidator(this.name), getAccess()).getValidator();
     if (this.validator == null) {
       throw ServerMessages.ACCOUNT_DOES_NOT_EXIST;
     }
diff --git a/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java b/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java
index 187a277bf8724eb343e52b84364b7b10fc781641..d02722fd9e89e70c26e8782252c65fb9e199158c 100644
--- a/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java
+++ b/src/main/java/caosdb/server/transaction/RetrievePermissionRulesTransaction.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.transaction;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrievePermissionRules;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.permissions.PermissionRule;
@@ -40,10 +39,10 @@ public class RetrievePermissionRulesTransaction extends AccessControlTransaction
 
   @Override
   protected void transaction() throws Exception {
-    if (Database.execute(new RetrieveRole(this.role), getAccess()).getRole() == null) {
+    if (execute(new RetrieveRole(this.role), getAccess()).getRole() == null) {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
-    this.rules = Database.execute(new RetrievePermissionRules(this.role), getAccess()).getRules();
+    this.rules = execute(new RetrievePermissionRules(this.role), getAccess()).getRules();
   }
 
   public HashSet<PermissionRule> getRules() {
diff --git a/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java
index bcadbac85942a4b1e66e7676c1675647427251ff..4d019f87fb572ce8e75393302764e8146034ee22 100644
--- a/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java
+++ b/src/main/java/caosdb/server/transaction/RetrieveRoleTransaction.java
@@ -23,7 +23,6 @@
 package caosdb.server.transaction;
 
 import caosdb.server.accessControl.Role;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.utils.ServerMessages;
 
@@ -38,7 +37,7 @@ public class RetrieveRoleTransaction extends AccessControlTransaction {
 
   @Override
   protected void transaction() throws Exception {
-    this.role = Database.execute(new RetrieveRole(this.name), getAccess()).getRole();
+    this.role = execute(new RetrieveRole(this.name), getAccess()).getRole();
     if (this.role == null) {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
diff --git a/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java b/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java
index 3530d6dad9ec5a134a9613a0a7ece61f53a20edb..2b936247bba9ece2d4bb9ab5cb1a5a1b2cbada74 100644
--- a/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java
+++ b/src/main/java/caosdb/server/transaction/RetrieveSparseEntityByPath.java
@@ -22,7 +22,6 @@
  */
 package caosdb.server.transaction;
 
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.GetFileRecordByPath;
 import caosdb.server.database.backend.transaction.RetrieveSparseEntity;
 import caosdb.server.entity.EntityInterface;
@@ -58,9 +57,9 @@ public class RetrieveSparseEntityByPath extends Transaction<TransactionContainer
   protected void transaction() throws Exception {
     for (final EntityInterface e : getContainer()) {
       final GetFileRecordByPath r =
-          Database.execute(new GetFileRecordByPath(e.getFileProperties().getPath()), getAccess());
+          execute(new GetFileRecordByPath(e.getFileProperties().getPath()), getAccess());
       e.setId(r.getId());
-      Database.execute(new RetrieveSparseEntity(e), getAccess());
+      execute(new RetrieveSparseEntity(e), getAccess());
     }
   }
 
diff --git a/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java
index 93c5eb5c638ff8d4ee36d0c1416bd7f980c10378..f2728a64664ad72f113e55a91ef87496810ad7c6 100644
--- a/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java
+++ b/src/main/java/caosdb/server/transaction/RetrieveUserTransaction.java
@@ -25,7 +25,6 @@ package caosdb.server.transaction;
 import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.UserSources;
 import caosdb.server.accessControl.UserStatus;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveUser;
 import caosdb.server.database.proto.ProtoUser;
 import caosdb.server.utils.ServerMessages;
@@ -46,7 +45,7 @@ public class RetrieveUserTransaction extends AccessControlTransaction {
     if (!UserSources.isUserExisting(this.principal)) {
       throw ServerMessages.ACCOUNT_DOES_NOT_EXIST;
     }
-    this.user = Database.execute(new RetrieveUser(this.principal), getAccess()).getUser();
+    this.user = execute(new RetrieveUser(this.principal), getAccess()).getUser();
 
     if (this.user == null) {
       this.user = new ProtoUser();
diff --git a/src/main/java/caosdb/server/transaction/Transaction.java b/src/main/java/caosdb/server/transaction/Transaction.java
index 3e511257b239627c61064acc5d011d79516bbb08..28b8276e2b93699f2315fb754303194208bb37e5 100644
--- a/src/main/java/caosdb/server/transaction/Transaction.java
+++ b/src/main/java/caosdb/server/transaction/Transaction.java
@@ -25,11 +25,11 @@ package caosdb.server.transaction;
 import caosdb.datetime.UTCDateTime;
 import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.Principal;
-import caosdb.server.database.Database;
 import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.InsertTransactionHistory;
 import caosdb.server.database.exceptions.TransactionException;
+import caosdb.server.database.misc.TransactionBenchmark;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.Message;
 import caosdb.server.entity.Message.MessageType;
@@ -55,6 +55,11 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
   public static final Message ERROR_INTEGRITY_VIOLATION =
       new Message(MessageType.Error, 0, "This entity caused an unexpected integrity violation.");
 
+  @Override
+  public TransactionBenchmark getTransactionBenchmark() {
+    return getContainer().getTransactionBenchmark();
+  }
+
   private static final DatabaseMonitor monitor = DatabaseMonitor.getInstance();
 
   public static final String CLEAN_UP = "TransactionCleanUp";
@@ -93,7 +98,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
     this.schedule.addAll(Job.loadPermanentContainerJobs(this));
 
     for (final EntityInterface e : getContainer()) {
-      final List<Job> loadJobs = Job.loadJobs(e, this);
+      final List<Job> loadJobs = loadContainerFlags.loadJobs(e, this);
       this.schedule.addAll(loadJobs);
 
       // additionally load datatype job
@@ -126,21 +131,22 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       this.schedule.runJobs(JobExecutionTime.INIT);
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(this.getClass().getSimpleName() + ".init", System.currentTimeMillis() - t1);
+          .addMeasurement(
+              this.getClass().getSimpleName() + ".init", System.currentTimeMillis() - t1);
 
       t1 = System.currentTimeMillis();
       preCheck();
       this.schedule.runJobs(JobExecutionTime.PRE_CHECK);
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".pre_check", System.currentTimeMillis() - t1);
 
       t1 = System.currentTimeMillis();
       check();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".check", System.currentTimeMillis() - t1);
 
       t1 = System.currentTimeMillis();
@@ -148,7 +154,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       postCheck();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".post_check", System.currentTimeMillis() - t1);
 
       t1 = System.currentTimeMillis();
@@ -156,7 +162,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       this.schedule.runJobs(JobExecutionTime.PRE_TRANSACTION);
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".pre_transaction",
               System.currentTimeMillis() - t1);
 
@@ -164,7 +170,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       transaction();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".transaction", System.currentTimeMillis() - t1);
 
       t1 = System.currentTimeMillis();
@@ -172,7 +178,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       postTransaction();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".post_transaction",
               System.currentTimeMillis() - t1);
 
@@ -180,14 +186,14 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       writeHistory();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".history", System.currentTimeMillis() - t1);
 
       t1 = System.currentTimeMillis();
       commit();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".commit", System.currentTimeMillis() - t1);
 
     } catch (final Exception e) {
@@ -198,7 +204,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
       cleanUp();
       getContainer()
           .getTransactionBenchmark()
-          .addBenchmark(
+          .addMeasurement(
               this.getClass().getSimpleName() + ".cleanup", System.currentTimeMillis() - t1);
       notifyObservers(CLEAN_UP);
     }
@@ -229,7 +235,7 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra
           getTransactor().getPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal()
               ? "anonymous"
               : ((Principal) getTransactor().getPrincipal()).getUsername();
-      Database.execute(
+      execute(
           new InsertTransactionHistory(
               getContainer(), this.getClass().getSimpleName(), realm, username, getTimestamp()),
           getAccess());
diff --git a/src/main/java/caosdb/server/transaction/TransactionInterface.java b/src/main/java/caosdb/server/transaction/TransactionInterface.java
index 2dfb3d4201a864795ca76bcdbe6872fa76ab8e9d..1aaf2786cc613709c59c92b7102474cead00ca1c 100644
--- a/src/main/java/caosdb/server/transaction/TransactionInterface.java
+++ b/src/main/java/caosdb/server/transaction/TransactionInterface.java
@@ -22,7 +22,26 @@
  */
 package caosdb.server.transaction;
 
+import caosdb.server.database.BackendTransaction;
+import caosdb.server.database.access.Access;
+import caosdb.server.database.misc.RollBackHandler;
+import caosdb.server.database.misc.TransactionBenchmark;
+
 public interface TransactionInterface {
 
   public void execute() throws Exception;
+
+  public default TransactionBenchmark getTransactionBenchmark() {
+    return TransactionBenchmark.getRootInstance().getBenchmark(getClass());
+  }
+
+  public default <K extends BackendTransaction> K execute(K t, Access access) {
+    final RollBackHandler handler = (RollBackHandler) access.getHelper("RollBack");
+    handler.append(t);
+    t.setAccess(access);
+
+    t.setTransactionBenchmark(getTransactionBenchmark().getBenchmark(t.getClass()));
+    t.executeTransaction();
+    return t;
+  }
 }
diff --git a/src/main/java/caosdb/server/transaction/Update.java b/src/main/java/caosdb/server/transaction/Update.java
index 8cb14a66716c711656acf6af2dd037110b0f5025..8edd27d0aa0250ffebadc8d9a9639490daf1e2c7 100644
--- a/src/main/java/caosdb/server/transaction/Update.java
+++ b/src/main/java/caosdb/server/transaction/Update.java
@@ -23,7 +23,6 @@
 package caosdb.server.transaction;
 
 import caosdb.server.CaosDBException;
-import caosdb.server.database.Database;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.RetrieveFullEntity;
 import caosdb.server.database.backend.transaction.UpdateEntity;
@@ -82,7 +81,7 @@ public class Update extends WriteTransaction<UpdateContainer> {
 
     // retrieve a container which contains all id of those entities
     // which are to be updated.
-    Database.execute(new RetrieveFullEntity(oldContainer), getAccess());
+    execute(new RetrieveFullEntity(oldContainer), getAccess());
 
     // Check if any updates are to be processed.
     for (final EntityInterface newEntity : getContainer()) {
@@ -169,10 +168,9 @@ public class Update extends WriteTransaction<UpdateContainer> {
     update(getContainer(), getAccess());
   }
 
-  public static void update(final TransactionContainer container, final Access access)
-      throws Exception {
+  private void update(final TransactionContainer container, final Access access) throws Exception {
     if (container.getStatus().ordinal() >= EntityStatus.QUALIFIED.ordinal()) {
-      Database.execute(new UpdateEntity(container), access);
+      execute(new UpdateEntity(container), access);
     }
   }
 
diff --git a/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java b/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java
index 450e89e0d900a34964976d668ff5cb0a3e500cf4..e537b001f2af65e35c65e8c8ad88d37a2fd2bc01 100644
--- a/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java
+++ b/src/main/java/caosdb/server/transaction/UpdatePermissionRulesTransaction.java
@@ -23,7 +23,6 @@
 package caosdb.server.transaction;
 
 import caosdb.server.accessControl.ACMPermissions;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.database.backend.transaction.SetPermissionRules;
 import caosdb.server.permissions.PermissionRule;
@@ -46,10 +45,10 @@ public class UpdatePermissionRulesTransaction extends AccessControlTransaction {
     SecurityUtils.getSubject()
         .checkPermission(ACMPermissions.PERMISSION_UPDATE_ROLE_PERMISSIONS(this.role));
 
-    if (Database.execute(new RetrieveRole(this.role), getAccess()).getRole() == null) {
+    if (execute(new RetrieveRole(this.role), getAccess()).getRole() == null) {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
 
-    Database.execute(new SetPermissionRules(this.role, this.rules), getAccess());
+    execute(new SetPermissionRules(this.role, this.rules), getAccess());
   }
 }
diff --git a/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java b/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java
index e4ca75051e757dfb227585b11153b2ae5c802a82..dfec776005800469654f144a0c5ae6f0213a04ad 100644
--- a/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java
+++ b/src/main/java/caosdb/server/transaction/UpdateRoleTransaction.java
@@ -25,7 +25,6 @@ package caosdb.server.transaction;
 import caosdb.server.accessControl.ACMPermissions;
 import caosdb.server.accessControl.Role;
 import caosdb.server.accessControl.UserSources;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.InsertRole;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.utils.ServerMessages;
@@ -48,7 +47,7 @@ public class UpdateRoleTransaction extends AccessControlTransaction {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
 
-    Database.execute(new InsertRole(this.role), getAccess());
+    execute(new InsertRole(this.role), getAccess());
     RetrieveRole.removeCached(this.role.name);
   }
 }
diff --git a/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java b/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java
index 6b8a93b0c3da1674e1ab9b1589c85b9b0116f1ec..257e8c06cc9d9c9f24774e541cea611663f5ff0d 100644
--- a/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java
+++ b/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java
@@ -25,7 +25,6 @@ package caosdb.server.transaction;
 import caosdb.server.accessControl.ACMPermissions;
 import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.UserSources;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveRole;
 import caosdb.server.database.backend.transaction.UpdateUserRoles;
 import caosdb.server.utils.ServerMessages;
@@ -56,7 +55,7 @@ public class UpdateUserRolesTransaction extends AccessControlTransaction {
       SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_ASSIGN_ROLE(role));
 
       // test if role is existent
-      if (Database.execute(new RetrieveRole(role), getAccess()).getRole() == null) {
+      if (execute(new RetrieveRole(role), getAccess()).getRole() == null) {
         throw ServerMessages.ROLE_DOES_NOT_EXIST;
       }
     }
@@ -65,7 +64,7 @@ public class UpdateUserRolesTransaction extends AccessControlTransaction {
       throw ServerMessages.ACCOUNT_DOES_NOT_EXIST;
     }
 
-    Database.execute(new UpdateUserRoles(this.realm, this.user, this.roles), getAccess());
+    execute(new UpdateUserRoles(this.realm, this.user, this.roles), getAccess());
   }
 
   public Element getUserRolesElement() {
diff --git a/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java b/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java
index 663367c21a34c14392bcd0b60113d1e82e1e0539..ca29bb7977da8fc677c774b30a1f3fa78879c5a7 100644
--- a/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java
+++ b/src/main/java/caosdb/server/transaction/UpdateUserTransaction.java
@@ -26,7 +26,6 @@ import caosdb.server.accessControl.ACMPermissions;
 import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.UserSources;
 import caosdb.server.accessControl.UserStatus;
-import caosdb.server.database.Database;
 import caosdb.server.database.backend.transaction.RetrieveUser;
 import caosdb.server.database.backend.transaction.SetPassword;
 import caosdb.server.database.backend.transaction.UpdateUser;
@@ -88,23 +87,22 @@ public class UpdateUserTransaction extends AccessControlTransaction {
 
       if (this.password.isEmpty()) {
         // reset password
-        Database.execute(new SetPassword(this.user.name, null), getAccess());
+        execute(new SetPassword(this.user.name, null), getAccess());
       } else {
         Utils.checkPasswordStrength(this.password);
-        Database.execute(new SetPassword(this.user.name, this.password), getAccess());
+        execute(new SetPassword(this.user.name, this.password), getAccess());
       }
     }
 
     if (isToBeUpdated()) {
-      Database.execute(new UpdateUser(this.user), getAccess());
+      execute(new UpdateUser(this.user), getAccess());
     }
   }
 
   private boolean isToBeUpdated() throws Exception {
     boolean isToBeUpdated = false;
     final ProtoUser validUser =
-        Database.execute(
-                new RetrieveUser(new Principal(this.user.realm, this.user.name)), getAccess())
+        execute(new RetrieveUser(new Principal(this.user.realm, this.user.name)), getAccess())
             .getUser();
     if (this.user.status != null && (validUser == null || this.user.status != validUser.status)) {
       SecurityUtils.getSubject()
diff --git a/src/main/java/caosdb/server/transaction/WriteTransaction.java b/src/main/java/caosdb/server/transaction/WriteTransaction.java
index a666e9737a50af039d124178ddf507905e38d7ef..e67ae0600bc573efbdf67b9b341299fe1fe3ca00 100644
--- a/src/main/java/caosdb/server/transaction/WriteTransaction.java
+++ b/src/main/java/caosdb/server/transaction/WriteTransaction.java
@@ -25,7 +25,6 @@ package caosdb.server.transaction;
 import caosdb.server.database.misc.RollBackHandler;
 import caosdb.server.entity.FileProperties;
 import caosdb.server.entity.container.TransactionContainer;
-import caosdb.server.utils.ChecksumUpdater;
 
 public abstract class WriteTransaction<C extends TransactionContainer> extends Transaction<C> {
 
diff --git a/src/main/java/caosdb/server/utils/Info.java b/src/main/java/caosdb/server/utils/Info.java
index 445374a105fbe8fbff1bc95a90fcceba197b09f4..e35b77bfbd18e12b3fd5c82112bffc4d337eac3a 100644
--- a/src/main/java/caosdb/server/utils/Info.java
+++ b/src/main/java/caosdb/server/utils/Info.java
@@ -24,7 +24,6 @@ package caosdb.server.utils;
 
 import caosdb.server.CaosDBServer;
 import caosdb.server.FileSystem;
-import caosdb.server.database.Database;
 import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.GetInfo;
@@ -37,6 +36,8 @@ import java.io.File;
 import java.io.IOException;
 import java.sql.SQLException;
 import java.util.LinkedList;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.jdom2.Element;
 
 public class Info extends AbstractObservable implements Observer, TransactionInterface {
@@ -44,33 +45,32 @@ public class Info extends AbstractObservable implements Observer, TransactionInt
   private static Info instance = new Info();
   public static final String SYNC_DATABASE_EVENT = "SyncDatabaseEvent";
   private final Access access;
+  public Logger logger = LogManager.getLogger(getClass());
 
   @Override
   public boolean notifyObserver(final String e, final Observable o) {
     try {
       syncDatabase();
     } catch (final Exception exc) {
-      exc.printStackTrace();
+      logger.error(exc);
     }
     return true;
   }
 
-  static {
+  private Info() {
+    this.access = DatabaseMonitor.getInfoAccess(this);
     try {
       syncDatabase();
-    } catch (final Exception e) {
-      e.printStackTrace();
+    } catch (final Exception exc) {
+      logger.error(exc);
     }
   }
 
-  private Info() {
-    this.access = DatabaseMonitor.getInfoAccess(this);
-  }
-
   public static Info getInstance() {
     return instance;
   }
 
+  private Long lastSync = 0L;
   private static File dropOffBox = null;
   private static int filesCount = -1;
   private static int propertiesCount = -1;
@@ -145,12 +145,22 @@ public class Info extends AbstractObservable implements Observer, TransactionInt
     return ret;
   }
 
-  public static void syncDatabase() throws Exception {
-    final Access access = getInstance().access;
+  public long timeSinceSync() {
+    long time = System.currentTimeMillis();
+    return time - lastSync;
+  }
+
+  public void syncDatabase() throws Exception {
+    synchronized (lastSync) {
+      if (timeSinceSync() < 10000) {
+        return;
+      }
+      lastSync = System.currentTimeMillis();
+    }
 
     final ProtoInfo i = new ProtoInfo();
     final GetInfo t = new GetInfo(i);
-    Database.execute(t, access);
+    execute(t, access);
     filesCount = i.filesCount;
     recordsCount = i.recordsCount;
     recordTypesCount = i.recordTypesCount;
@@ -158,7 +168,7 @@ public class Info extends AbstractObservable implements Observer, TransactionInt
     fssize = Utils.getReadableByteSize(i.fssize);
     tmpFilesCount = countTmpFiles();
 
-    getInstance().notifyObservers(SYNC_DATABASE_EVENT);
+    notifyObservers(SYNC_DATABASE_EVENT);
   }
 
   private static int countTmpFiles() throws IOException {
@@ -221,12 +231,12 @@ public class Info extends AbstractObservable implements Observer, TransactionInt
     return info;
   }
 
-  public static void syncDatabase(final ServerStat stat) throws TransactionException, Message {
+  public void syncDatabase(final ServerStat stat) throws TransactionException, Message {
 
     final Access access = getInstance().access;
 
     final SyncStats t = new SyncStats(stat);
-    Database.execute(t, access);
+    execute(t, access);
   }
 
   @Override
diff --git a/src/test/java/caosdb/server/Misc.java b/src/test/java/caosdb/server/Misc.java
index 92e8b198bf8cd60b8407dac4e7fcd4e9ed671a25..bcdc1729f008dbb1393fe238a3eb763c67d69e0f 100644
--- a/src/test/java/caosdb/server/Misc.java
+++ b/src/test/java/caosdb/server/Misc.java
@@ -25,7 +25,6 @@ package caosdb.server;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import caosdb.server.database.misc.TransactionBenchmark;
@@ -37,11 +36,8 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.util.Properties;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import org.apache.commons.jcs.JCS;
-import org.apache.commons.jcs.access.CacheAccess;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.config.Ini;
 import org.apache.shiro.config.IniSecurityManagerFactory;
@@ -205,26 +201,6 @@ public class Misc {
     assertEquals(null, m.group(2));
   }
 
-  @Test
-  public void testCache() throws IOException {
-    final Properties p = new Properties();
-    p.load(
-        new FileInputStream(
-            System.getProperty("user.dir") + "/src/test/java/caosdb/server/cache.ccf"));
-    JCS.setConfigProperties(p);
-
-    final CacheAccess<Object, Object> cache = JCS.getInstance("default");
-    JCS.getInstance("default");
-
-    final String key = "KEY";
-    final String value = "VALUE";
-
-    cache.put(key, value);
-
-    assertEquals(value, cache.get(key));
-    assertSame(value, cache.get(key));
-  }
-
   @Test
   public void testCrobJob() throws InterruptedException {
     new CronJob(
@@ -295,11 +271,11 @@ public class Misc {
 
   @Test
   public void benchmarkSerialization() throws IOException, ClassNotFoundException {
-    TransactionBenchmark.getInstance().addBenchmark("bla", 1000);
+    TransactionBenchmark.getRootInstance().addMeasurement("bla", 1000);
 
     final FileOutputStream fileOut = new FileOutputStream("/tmp/benchmark.java.ser");
     final ObjectOutputStream out = new ObjectOutputStream(fileOut);
-    out.writeObject(TransactionBenchmark.getInstance());
+    out.writeObject(TransactionBenchmark.getRootInstance());
     out.close();
     fileOut.close();
     System.out.printf("Serialized data is saved in /tmp/benchmark.java.ser");
diff --git a/src/test/java/caosdb/server/cache.ccf b/src/test/java/caosdb/server/cache.ccf
deleted file mode 100644
index d57b1c9f63d44f6436532e686b3609dd33df00d3..0000000000000000000000000000000000000000
--- a/src/test/java/caosdb/server/cache.ccf
+++ /dev/null
@@ -1,4 +0,0 @@
-jcs.default=DC
-jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes
-jcs.default.cacheattributes.MaxObjects=1000
-jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.lru.LRUMemoryCache
\ No newline at end of file
diff --git a/src/test/java/caosdb/server/caching/TestCaching.java b/src/test/java/caosdb/server/caching/TestCaching.java
new file mode 100644
index 0000000000000000000000000000000000000000..56d8e750ab75663e29808a0f97962df88006d080
--- /dev/null
+++ b/src/test/java/caosdb/server/caching/TestCaching.java
@@ -0,0 +1,52 @@
+package caosdb.server.caching;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import caosdb.server.CaosDBServer;
+import caosdb.server.accessControl.Pam;
+import caosdb.server.database.backend.transaction.RetrieveProperties;
+import java.io.IOException;
+import org.apache.commons.jcs.JCS;
+import org.apache.commons.jcs.access.CacheAccess;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestCaching {
+
+  @BeforeClass
+  public static void init() throws IOException {
+    CaosDBServer.initServerProperties();
+    JCSCacheHelper.init();
+  }
+
+  @Test
+  public void testCacheConfig() {
+    CacheAccess<String, String> retrieve_properties_cache =
+        JCS.getInstance(RetrieveProperties.CACHE_REGION);
+    assertEquals(1003, retrieve_properties_cache.getCacheAttributes().getMaxObjects());
+
+    CacheAccess<String, String> retrieve_entities_cache = JCS.getInstance("BACKEND_SparseEntities");
+    assertEquals(1002, retrieve_entities_cache.getCacheAttributes().getMaxObjects());
+
+    CacheAccess<String, String> pam_groups_cache = JCS.getInstance(Pam.CACHE_REGION_GROUPS);
+    assertEquals(1000, pam_groups_cache.getCacheAttributes().getMaxObjects());
+    assertEquals(false, pam_groups_cache.getCacheAttributes().isUseMemoryShrinker());
+    assertEquals(false, pam_groups_cache.getDefaultElementAttributes().getIsEternal());
+    assertEquals(61, pam_groups_cache.getDefaultElementAttributes().getIdleTime());
+    assertEquals(601, pam_groups_cache.getDefaultElementAttributes().getMaxLife());
+  }
+
+  @Test
+  public void testCacheElements() throws IOException {
+    final CacheAccess<Object, Object> cache = JCS.getInstance("default");
+
+    final String key = "KEY";
+    final String value = "VALUE";
+
+    cache.put(key, value);
+
+    assertEquals(value, cache.get(key));
+    assertSame(value, cache.get(key));
+  }
+}
diff --git a/src/test/java/caosdb/server/resource/TestScriptingResource.java b/src/test/java/caosdb/server/resource/TestScriptingResource.java
index 353a2ea220984705b2612e01fe8460d5c2d7b457..2edfb82b53b56324996293a469fadf807264d86c 100644
--- a/src/test/java/caosdb/server/resource/TestScriptingResource.java
+++ b/src/test/java/caosdb/server/resource/TestScriptingResource.java
@@ -38,6 +38,7 @@ import caosdb.server.database.backend.interfaces.RetrievePermissionRulesImpl;
 import caosdb.server.database.backend.interfaces.RetrieveRoleImpl;
 import caosdb.server.database.backend.interfaces.RetrieveUserImpl;
 import caosdb.server.database.exceptions.TransactionException;
+import caosdb.server.database.misc.TransactionBenchmark;
 import caosdb.server.database.proto.ProtoUser;
 import caosdb.server.entity.Message;
 import caosdb.server.permissions.PermissionRule;
@@ -76,6 +77,14 @@ public class TestScriptingResource {
       ret.description = "bla";
       return ret;
     }
+
+    @Override
+    public TransactionBenchmark getBenchmark() {
+      return null;
+    }
+
+    @Override
+    public void setTransactionBenchmark(TransactionBenchmark b) {}
   }
 
   public static class RetrievePermissionRules implements RetrievePermissionRulesImpl {
@@ -86,6 +95,14 @@ public class TestScriptingResource {
     public HashSet<PermissionRule> retrievePermissionRule(String role) throws TransactionException {
       return new HashSet<>();
     }
+
+    @Override
+    public TransactionBenchmark getBenchmark() {
+      return null;
+    }
+
+    @Override
+    public void setTransactionBenchmark(TransactionBenchmark b) {}
   }
 
   public static class RetrieveUser implements RetrieveUserImpl {
@@ -96,6 +113,14 @@ public class TestScriptingResource {
     public ProtoUser execute(Principal principal) throws TransactionException {
       return new ProtoUser();
     }
+
+    @Override
+    public TransactionBenchmark getBenchmark() {
+      return null;
+    }
+
+    @Override
+    public void setTransactionBenchmark(TransactionBenchmark b) {}
   }
 
   public static class RetrievePasswordValidator implements RetrievePasswordValidatorImpl {
@@ -112,6 +137,14 @@ public class TestScriptingResource {
         }
       };
     }
+
+    @Override
+    public void setTransactionBenchmark(TransactionBenchmark b) {}
+
+    @Override
+    public TransactionBenchmark getBenchmark() {
+      return null;
+    }
   }
 
   @BeforeClass
diff --git a/src/test/java/caosdb/server/utils/FileUtilsTest.java b/src/test/java/caosdb/server/utils/FileUtilsTest.java
index c80f8ebb8b71785dcf8b6f5c8adaaec5e61b0332..e4b2411dc0e77ce0225c0637422c84bbab2cc4aa 100644
--- a/src/test/java/caosdb/server/utils/FileUtilsTest.java
+++ b/src/test/java/caosdb/server/utils/FileUtilsTest.java
@@ -31,7 +31,7 @@ import caosdb.server.CaosDBException;
 import caosdb.server.CaosDBServer;
 import caosdb.server.FileSystem;
 import caosdb.server.ServerProperties;
-import caosdb.server.database.Database;
+import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.implementation.UnixFileSystem.UnixFileSystemGetFileIterator.FileNameIterator;
 import caosdb.server.database.backend.implementation.UnixFileSystem.UnixFileSystemHelper;
@@ -557,7 +557,7 @@ public class FileUtilsTest {
     access.setHelper("UnixFileSystemHelper", h);
 
     FileConsistencyCheck check =
-        Database.execute(new FileConsistencyCheck("test1.dat", 0, null, 0L, null), access);
+        execute(new FileConsistencyCheck("test1.dat", 0, null, 0L, null), access);
     assertEquals(FileConsistencyCheck.FILE_DOES_NOT_EXIST, check.getResult());
 
     final File f = new File(rootPath + "test1.dat");
@@ -573,9 +573,7 @@ public class FileUtilsTest {
     final long size = f.length();
     final long timestamp = f.lastModified();
 
-    check =
-        Database.execute(
-            new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access);
+    check = execute(new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access);
     assertEquals(FileConsistencyCheck.OK, check.getResult());
 
     // timestamp has 1 second accuracy
@@ -592,9 +590,7 @@ public class FileUtilsTest {
     assertTrue(timestamp2 > timestamp);
 
     assertTrue(f.exists());
-    check =
-        Database.execute(
-            new FileConsistencyCheck("test1.dat", size2, hash, timestamp, hasher), access);
+    check = execute(new FileConsistencyCheck("test1.dat", size2, hash, timestamp, hasher), access);
     assertEquals(FileConsistencyCheck.OK, check.getResult());
 
     out = new PrintStream(f);
@@ -602,12 +598,16 @@ public class FileUtilsTest {
     out.flush();
     out.close();
 
-    check =
-        Database.execute(
-            new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access);
+    check = execute(new FileConsistencyCheck("test1.dat", size, hash, timestamp, hasher), access);
     assertEquals(FileConsistencyCheck.FILE_MODIFIED, check.getResult());
   }
 
+  private <K extends BackendTransaction> K execute(K t, Access access2) {
+    t.setAccess(access2);
+    t.executeTransaction();
+    return t;
+  }
+
   @Test
   public void testFileIterator() throws IOException {
     final String rootPath = "./testFileIterator/";
@@ -674,8 +674,7 @@ public class FileUtilsTest {
     dat3.deleteOnExit();
     dat3.createNewFile();
 
-    final Iterator<String> iterator =
-        Database.execute(new GetFileIterator(rootPath), access).getIterator();
+    final Iterator<String> iterator = execute(new GetFileIterator(rootPath), access).getIterator();
 
     assertEquals(rootPath + "dat1", iterator.next());
     assertEquals(rootPath + "dat2", iterator.next());