Question

Je me demande si le serveur a besoin de temps pour mettre à jour un enregistrement afin de récupérer l'enregistrement existant, de parcourir les champs pour vérifier les modifications et de ne placer que les champs modifiés dans la requête de mise à jour? (J'utilise MySQL et PHP.)

La raison principale est de réduire la taille de la requête de mise à jour aux fins du journal des modifications. Normalement, la requête peut comporter 15 champs, mais seulement 2 sont en cours de modification. Cette requête peut également être utilisée pour la journalisation car elle ne contiendra que les champs modifiés et sera donc plus facile à analyser.

Ce qui m'inquiète, c'est le temps qu'il faut pour récupérer l'enregistrement existant.

Ou existe-t-il un moyen de récupérer dans MySQL quels champs il a mis à jour?

Était-ce utile?

La solution

Je pense que cela vaut la peine d'être changé - mais probablement pas la peine de faire un choix avant l'insertion.

Je ne fais que mettre à jour les champs qui ont changé, cela fait partie du fonctionnement de ma classe DbEntity qui suit un modèle d'activation / enregistrement. Cela ne coûte que très peu, car je conserve l'enregistrement actuel et les enregistrements d'origine, que je copie simplement chaque fois qu'un enregistrement est chargé.

Les raisons sont concises - pas vraiment la performance. Vous pouvez également vérifier les modifications simultanées en ajoutant une clause where sur l'ancienne valeur des champs mis à jour et en générant l'erreur appropriée.

Dans la méthode write / update:

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

Dans la méthode de chargement

$this->orig_record = Array();
foreach ($this->record as $key => $value)
    $this->orig_record[$key] = $value;

Autres conseils

Au niveau le plus élémentaire, si je lis bien votre question, vous ne souhaitez généralement pas mettre à jour aveuglément l’enregistrement complet au cas où un autre utilisateur aurait déjà mis à jour des parties de cet enregistrement que vous n’avez pas réellement modifiées. Vous reviendriez aveuglément et inutilement sur leurs mises à jour.

Je pense que votre algorithme actuel peut conduire à des écritures sales, si vous allez lire le courant une fois pour la mise à jour, autorisez les mises à jour en mémoire, puis relisez l'enregistrement pour vous permettre de déterminer quels champs ont été remplis. mis à jour. Que se passe-t-il si un autre utilisateur met à jour cet enregistrement derrière votre dos, laissant croire à votre algorithme que vous êtes celui qui a mis à jour ce champ? Mais avant tout, vous ne devriez pas avoir à lire chaque enregistrement deux fois pour effectuer une seule mise à jour.

Si vos données n'engendrent pas souvent des conflits, vous pouvez en tirer des informations sur le verrouillage optimiste, même si vous ne choisissez pas de les implémenter.

Nous avons implémenté une méthode dans laquelle vous ajoutez une colonne update-timestamp ou incremental update-number à votre table. Ensuite, dans votre sandbox / mémoire, vous pouvez garder trace des champs que vous avez modifiés (oldvalue / newvalue), et vous pouvez librement émettre votre mise à jour SQL pour cet enregistrement pour ces champs, "UPDATE ... WHERE UPDATENUM = the-original- nombre " (ou WHERE UPDATETS = the-original-timestamp), en vous assurant que votre SQL de mise à jour incrémente également UPDATENUM ou UPDATETS, selon le cas. Si les enregistrements concernés par cette mise à jour SQL est 0, vous savez que quelqu'un d'autre a déjà modifié cet enregistrement en arrière-plan et vous êtes maintenant en conflit. Mais au moins, vous n’avez pas écrasé les modifications apportées par une autre personne. Vous pouvez ensuite relire les nouvelles données ou demander à votre utilisateur de résoudre le conflit.

Le point le plus lent de votre application sera toujours l’accès à votre base de données. Par conséquent, si vous pouvez accélérer le processus, c’est une bonne idée. Cela dit, cela dépend vraiment de la taille de votre base de données, de vos enregistrements et de leur ampleur probable pour déterminer si cela vaut la peine de vérifier par programme si les éléments ont été mis à jour. Si votre base de données est petite et que l'accès est déjà assez rapide, cela ne vaut peut-être pas la peine. Mais si la vitesse peut être améliorée et que cela vous procure un avantage supplémentaire pour votre journalisation, alors foncez.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top