1

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

如果它从缓存中提取它,为什么它只会为读取计费?似乎它会为写入而不是读取计费。应用引擎对非事务性缓存读取的收费是否与对数据存储读取的收费相同?为什么?

这是带有事务的代码:

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);
4

1 回答 1

2

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

在您的情况下,无论如何您都应该有一个事务,因为您希望在处理时拥有一致的数据库视图。没有它,mapData当您正在处理它时,可能会被另一个操作修改,而这些修改将被默默地丢失。那会很糟糕。(嗯,可能。)交易是良药。

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

于 2012-12-03T15:17:43.347 回答