web-dev-qa-db-fra.com

La taille de la table Cache Form est énorme

La taille de la table de cache était passée à 10+ Go le mois dernier, et je l'avais corrigée temporairement en la tronquant. La dernière fois que j'ai vérifié, c'était environ 1 Go. Donc, dans quelques mois, il atteindra à nouveau 10 Go. Comment cela devrait-il être traité?

Notez que j'ai désactivé toutes les tâches cron sur ce site. Si c'est la raison, quel cron doit être activé?

13
GoodSp33d

La table _{cache_form}_ est un peu drôle et se comporte d'une manière légèrement différente de celle des autres tables de cache.

Si vous jetez un œil à drupal_flush_all_caches() , vous verrez que _{cache_form}_ n'est pas effacé. Il s'agit de protéger les formulaires en cours contre les armes nucléaires.

La fonction system_cron() s'occupe de l'élagage des anciennes données de _{cache_form}_ avec les autres tables de cache.

Vous devriez vraiment exécuter cron sur tous les sites Drupal. Si votre table _{cache_form}_ est ginourmous, alors je parie que votre _{watchdog}_ et _{session}_ les tables le sont aussi. De nombreux autres modules exécutent l'activité de ménage dans le cadre de leurs propres fonctions hook_cron() .

Vous pouvez également fouiller la file d'attente des problèmes. Il y a eu quelques bogues avec _{cache_form}_, et vous en rencontrez peut-être un.

24
mpdonadio

Règle du pouce: Cron doit être exécuté régulièrement pour le ménage de votre site Web.

Vous avez mentionné dans votre commentaire à MPD que malgré la configuration du cron et leur exécution régulière, votre table cache_form grandit rapidement.

Une solution à cela consiste à exécuter votre cron plus fréquemment. Dites toutes les six heures ou moins? Si vous ne pouvez pas le faire, lisez la suite.

Solution alternative:

mymodule_cron() {
    cache_clear_all(NULL, 'cache_form');
}

Installez Elysia Cron et maintenant vous pouvez exécuter la fonction cron de votre module séparément. Vous pouvez conserver la fréquence du cron Elysia pour que votre module fonctionne toutes les six heures. Pour que votre table cache_form Soit élaguée toutes les six heures.

Pendant ce processus d'élagage, les entrées qui ne datent pas de plus de 6 heures ne seront pas supprimées. La raison en est que si toutes les entrées sont supprimées, tous les formulaires qui sont soumis au moment de la suppression des entrées peuvent se comporter bizarrement.

Regardez le code dans https://api.drupal.org/api/drupal/includes!form.inc/function/form_set_cache/7

function form_set_cache($form_build_id, $form, $form_state) {
  // 6 hours cache life time for forms should be plenty.
  $expire = 21600;

Au fur et à mesure que le commentaire se lit, ils supposent que cela devrait être suffisant et dans votre cas, cela devient trop pour vous. L'astuce consiste donc à effacer la table cache_form plus fréquemment et à réduire la valeur de $ expire à une valeur inférieure.Si vous souhaitez effacer les entrées cache_form plus fréquemment que la valeur par défaut de 6 six heures, vous devez modifier le TTL des entrées cache_form.

Vous pouvez le faire en installant cacheboject puis en implémentant le hook_cacheobject_presave Dans lequel vous pouvez modifier le TTL en 2 ou 3 heures.

mymodule_cacheobject_presave()($object, $cid, $bin) {
  // Extend the expiry period for prototype forms used in ajax enabled forms.                                                                  
  $cache_ttl = 1 ; // Change it to any number of hours
  if ($bin == 'cache_form') {
    $object->expire = REQUEST_TIME + $cache_ttl * 3600;
  }
}

Un inconvénient de cette approche est que si les formulaires ne sont pas soumis dans les 2 heures (la valeur RTL que vous définissez), les données du formulaire peuvent être perdues et vous pouvez obtenir des problèmes de formulaire expiré.

6
Gokul N K

Utilisez le module Safe cache_form Clear .

Il vous permettra d'abord de tailler la table à une taille raisonnable, puis de la maintenir.

Extrait extrait de la page du projet:

Supprimez en toute sécurité un nombre limité d'éléments de la table cache_form.

Une fois le module installé, élaguez d'abord le cache_form: exécutez drush safe-cache-form-clear jusqu'à ce que la taille du tableau reste cohérente, indiquant que vous avez supprimé tous les enregistrements datant de plus de 6 heures.

Il continuera ensuite à fonctionner sur cron.

Il s'agit du module documenté à cet effet par Acquia pour leurs abonnés. La page de documentation Acquia fournit de bonnes informations supplémentaires.

1
Kay V

Pour contourner ce problème, j'ai créé le module https://www.drupal.org/project/session_cache_form

1
impol

Lorsque j'avais des problèmes de performances sur un site sur lequel je travaillais, je suis tombé sur cela après avoir corrigé la mise en cache. Vous pouvez lire l'article ici: https://thinktandem.io/blog/2017/11/22/debugging-with-new-relic-blazemeter-strace-more/

Depuis mon article de blog, vous pouvez ajouter une configuration de file d'attente et de cron, puis utiliser quelque chose comme Elysia Cron pour que tout fonctionne bien ensemble:

/**
 * Implements hook_cron_queue_info()
 */
function THE MODULE_cron_queue_info() {
  // Set up the worker queue.
  $queues['THE MODULE_queue'] = array(
    'worker callback' => 'THE MODULE_queue_process',
    'time' => 600,
  );
  return $queues;
}

/**
 * Implements hook_cron()
 */
function THE MODULE_cron() {
  // Load up our worker queue.
  $queue = DrupalQueue::get('THE MODULE_queue');

  // Set up the query for expired results.
  $sql = "SELECT cid FROM {cache_form} WHERE expire < :time";
  $query = db_query($sql, array(':time' => REQUEST_TIME));
  $results = $query->fetchAll(PDO::FETCH_ASSOC);

  // Split this into chunks for safety and speed.
  $chunks = array_chunk($results, 5000);
  foreach ($chunks as $chunk) {
    // Add the chunk to the queue worker.
    $queue->createItem($chunk);
  }
}

/**
 * Worker callback defined in hook_cron_queue_info().
 *
 * @param array $data
 *   The array of cids we want to delete.
 */
function THE MODULE_queue_process($data) {
  db_delete('cache_form')
    ->condition('cid', $data, 'IN')
    ->execute();
}
1
John O