Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当下面的代码被包装在一个事务中时,为什么应用程序引擎会给我更少的账单?_Java_Google App Engine_Jdo_Datanucleus_Appstats - Fatal编程技术网

Java 当下面的代码被包装在一个事务中时,为什么应用程序引擎会给我更少的账单?

Java 当下面的代码被包装在一个事务中时,为什么应用程序引擎会给我更少的账单?,java,google-app-engine,jdo,datanucleus,appstats,Java,Google App Engine,Jdo,Datanucleus,Appstats,我已经使用appstats多次验证了这一点。当下面的代码未包装在事务中时,JDO将执行两次数据存储读取和一次写入(3个RPC),代价为240。不只是第一次,每次,即使它每次都在访问同一条记录,因此应该从缓存中提取它。但是,当我像上面那样将代码包装到事务中时,代码会生成4个RPC:开始事务、获取、放置和提交——其中,只有获取作为数据存储读取计费,因此总成本为70 如果它是从缓存中提取的,为什么它只会为读取付费?这似乎是一个写的账单,而不是读的账单。app engine是否可以为非事务性缓存读取向我

我已经使用appstats多次验证了这一点。当下面的代码未包装在事务中时,JDO将执行两次数据存储读取和一次写入(3个RPC),代价为240。不只是第一次,每次,即使它每次都在访问同一条记录,因此应该从缓存中提取它。但是,当我像上面那样将代码包装到事务中时,代码会生成4个RPC:开始事务、获取、放置和提交——其中,只有获取作为数据存储读取计费,因此总成本为70

如果它是从缓存中提取的,为什么它只会为读取付费?这似乎是一个写的账单,而不是读的账单。app engine是否可以为非事务性缓存读取向我支付与数据存储读取相同的金额?为什么?

这是带有事务的代码:

PersistenceManager pm = PMF.getManager();
Transaction tx = pm.currentTransaction();
String responsetext = "";
try {
  tx.begin();
  Key userkey = obtainUserKeyFromCookie();
  User u = pm.getObjectById(User.class, userkey);
  Key mapkey = obtainMapKeyFromQueryString();
  // this is NOT a java.util.Map, just FYI
  Map currentmap = pm.getObjectById(Map.class, mapkey);
  Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
  Text newMapData = parseModifyAndReturn(mapData); // transform the map
  currentmap.setMapData(newMapData); // mutate the Map object
  tx.commit();
  responsetext = "OK";
} catch (JDOCanRetryException jdoe) {
  // log jdoe
  responsetext = "RETRY";
} catch (Exception e) {
  // log e
  responsetext = "ERROR";
} finally {
  if (tx.isActive()) {
    tx.rollback();
  }
  pm.close();
}
resp.getWriter().println(responsetext);
PersistenceManager pm = PMF.getManager();
String responsetext = "";
try {
  Key userkey = obtainUserKeyFromCookie();
  User u = pm.getObjectById(User.class, userkey);
  Key mapkey = obtainMapKeyFromQueryString();
  // this is NOT a java.util.Map, just FYI
  Map currentmap = pm.getObjectById(Map.class, mapkey);
  Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
  Text newMapData = parseModifyAndReturn(mapData); // transform the map
  currentmap.setMapData(newMapData); // mutate the Map object
  responsetext = "OK";
} catch (Exception e) {
  // log e
  responsetext = "ERROR";
} finally {
  pm.close();
}
resp.getWriter().println(responsetext);
这是没有事务的代码:

PersistenceManager pm = PMF.getManager();
Transaction tx = pm.currentTransaction();
String responsetext = "";
try {
  tx.begin();
  Key userkey = obtainUserKeyFromCookie();
  User u = pm.getObjectById(User.class, userkey);
  Key mapkey = obtainMapKeyFromQueryString();
  // this is NOT a java.util.Map, just FYI
  Map currentmap = pm.getObjectById(Map.class, mapkey);
  Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
  Text newMapData = parseModifyAndReturn(mapData); // transform the map
  currentmap.setMapData(newMapData); // mutate the Map object
  tx.commit();
  responsetext = "OK";
} catch (JDOCanRetryException jdoe) {
  // log jdoe
  responsetext = "RETRY";
} catch (Exception e) {
  // log e
  responsetext = "ERROR";
} finally {
  if (tx.isActive()) {
    tx.rollback();
  }
  pm.close();
}
resp.getWriter().println(responsetext);
PersistenceManager pm = PMF.getManager();
String responsetext = "";
try {
  Key userkey = obtainUserKeyFromCookie();
  User u = pm.getObjectById(User.class, userkey);
  Key mapkey = obtainMapKeyFromQueryString();
  // this is NOT a java.util.Map, just FYI
  Map currentmap = pm.getObjectById(Map.class, mapkey);
  Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
  Text newMapData = parseModifyAndReturn(mapData); // transform the map
  currentmap.setMapData(newMapData); // mutate the Map object
  responsetext = "OK";
} catch (Exception e) {
  // log e
  responsetext = "ERROR";
} finally {
  pm.close();
}
resp.getWriter().println(responsetext);

对于事务,
PersistenceManager
可以知道缓存在该代码的整个处理过程中都是有效的。如果没有事务,它就不能(它不知道是否有其他操作在它背后出现并更改了内容),因此必须根据DB表验证缓存的内容。每次检查时,它都需要创建一个事务来进行检查;这是DB接口本身的一个特性,其中任何不在事务中的操作(有一些特定于DB的异常)都会自动添加一个事务

在您的情况下,无论如何都应该有一个事务,因为您希望在处理过程中有一个一致的数据库视图。如果没有这样的话, MaDATAs/COD>可以在您正在进行操作的同时被另一个操作修改,这些修改将被悄然丢失。那太糟糕了。(好吧,也许吧。)交易才是解决之道


(您还应该考虑使用AOP来管理事务包装;这比每次自己编写所有事务管理代码要简单得多。哦,在您把事情做好之前,它会给部署增加很多复杂性,所以我理解不遵循这条建议……)

正如您在另一期文章中所述,查看日志可以告诉您哪些内容来自缓存,哪些不来自缓存。DataNucleus还有一个持久性属性“DataNucleus.findObject.validateWhenCached”,详细说明了该属性扩展了JDO规范之外的内容。@datanucleusging在日志中没有看到缓存的任何内容,即使我在app engine logging.properties文件中将所有日志级别设置为fine。一些关于状态更改和前滚未应用的作业的内容,但没有关于缓存的内容。当然,我知道XAActions很好,但我只是想了解其行为。有趣的是,当我设置datanucleus.findObject.validateWhenCached=false(如上面用户datanucleus所述)时,它归结为一次读取(而不是2次)和一次写入。无论如何,PM检查数据存储以确保对象存在是一个合理的解释,它解释了当我不在事务中时为什么会有更多的读取——但它没有解释为什么,当我在事务中包装代码时,当它似乎应该为一个DS写入向我收费时,它为一个DS读取向我收费。我再次思考了你的答案,它没有意义。如果我在请求中多次访问同一对象,这是有意义的,但我没有。在请求中,我访问两个不同的项——user对象和map对象。除非您说当我访问JDO对象的字段时,它会检查数据存储。