题
我想知道,如果它通过更新的领域检查的变化和仅把改变的字段更新查询记录检索现有记录,循环时,是值得的服务器时间? (我使用MySQL&PHP。)
这样做的主要原因是为了减少用于更改日志目的更新查询的大小。通常情况下,查询可能有15场,但只有2场实际上是被改变。此查询然后也可以用于记录,因为它仅包含改变的字段,因此更容易进行解析。
我担心的是,它需要检索现有记录的时间。
或者是有没有办法从MySQL哪些字段更新它取回?
解决方案
我认为这是值得改变 - 但可能不值得插入之前做一个选择
我仅更新已更改的字段,这是我DbEntity类的下面一个ActiveRecord图案的操作的一部分。它的成本一点额外要做到这一点,因为我认为当前记录和原始记录每当记录被载入-simply复制。
原因是简洁 - 没有真正的表现。你也可以通过添加更新的字段的旧值where子句检查并发修改并引发相应的错误。
在写入/更新方法:
$s1 = "";
foreach ($this->record as $key => $value)
{
// only update fields that have been changed
if ($value != $this->orig_record[$key])
{
$s1 .= $comma."`$key`='".mysql_real_escape_string($value)."'";
$comma = ", ";
}
}
$query = "UPDATE ".$this->table." SET $s1 where {$this->id_field}='".$this->get_keyfield()."'";
$query .= $this->extra_sql_update;
mysql_query($query);
$ar = mysql_affected_rows();
//
// the number of affected rows is actually those changed by the update operation, which will
// either be zero, or 1. If the query affects more than one row then we have a problem.
if ($ar < 0 || $ar > 1)
{
cbf_error("cbf_dbentity: {$this->table} :: only one row (not $ar) must be affected by an insert operation. $query",
E_USER_ERROR);
}
else
{
$new_id = $this->get_keyfield();
GlobalEventBus::notify_all(new AuditLogSQL($this->table, "update", $query));
}
$this->orig_record = Array();
foreach ($this->record as $key => $value)
$this->orig_record[$key] = $value;
//
// sanity check - ensure that what we have just written is actually there.
$this->load($new_id);
foreach ($this->orig_record as $key => $value)
if (trim($this->record[$key]) != trim($value)
&& (!$this->record[$key] == "0" && $value=""))
cbf_error("cbf_dbentity: {$this->table} :: record differs during write after reload: field $key was \"$value\", after write it is now \"".
$this->record[$key]."\"",E_USER_ERROR);
在负载方法
$this->orig_record = Array();
foreach ($this->record as $key => $value)
$this->orig_record[$key] = $value;
其他提示
在最基本的层面上,如果我读你的问题吧,你通常不希望盲目地更新的情况下,其他用户已经更新,你还没有真正改变该记录的部分的全部记录。你会盲目和不必要的恢复及其更新。
再次我相信你目前的算法可能会导致脏写,如果你要一次读取当前的更新,允许在内存中进行的更新,然后读取记录,以便您可以找出哪些领域得到了更新。如果另一个用户更新会发生什么事,你的背后记录,导致你的算法认为的您的人来更新视野中的一个?但主要是,你不应该阅读每一条记录两次执行一个更新。
如果您的数据不经常导致冲突,您可能会受益于阅读乐观锁定,即使你不选择来实现它。
我们已经实现了一个方法,在这里,让你添加一个更新时间戳或增量更新数列的表格。然后在沙箱/内存,你可以跟踪哪些领域你已经修改(OLDVALUE / NEWVALUE),你可以自由地发出您的更新SQL该记录这些字段,“UPDATE ... WHERE UPDATENUM =的原创号码“(或WHERE UPDATETS =的原装时间戳),确保您的更新SQL还增加了UPDATENUM或UPDATETS适当。如果记录的影响由SQL更新为0,你知道别人已经修改了记录在后台,您现在有冲突。但至少你没有覆盖别人的更改,然后就可以重新读取新的数据或有你的用户解决冲突。
在应用程序中最慢的点总是会成为你的数据库访问,所以如果你能速度起来,这是一个好主意。这就是说它实际上取决于有多大你的数据库,记录,他们有多大可能增长到,至于是否值得努力以编程方式检查物品是否已经更新。 如果你的数据库是小和访问已经是相当快的,它可能不值得花时间。但是,如果速度可以提高,它给你一个额外的好处,你的日志记录,然后去了。