# Freeze pendant MAJ d'un device Z2M

**URL:** <https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659>\
**Category:** Configuration\
**Created:** [Août 18, 2026, 9:33 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659 "2026-08-18T09:33:43Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 9:33 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/1 "2026-08-18T09:33:43Z")

</div>

Bonjour à tous,

**CECI EST UN APPEL À L’AIDE XD**

Je tente de mettre a jours mes devices, mais sur certain gladys freeze car je suppose qu’ils ont beaucoup d’état.  
Je dois m’acheter deux SSD NVME pour mon nas à la fin d’année pour ameliorer ma ram (que les prix son chere maintenant 👀)

- Que puis je faire, en attendant ?
- Que dois je chercher dans les logs pour vérifier si gladys est stuck ou si elle bosse ?

Merci par avance (en attendant ma domotique est en carafe 😃

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/d/c/dc993540129677d4b81b44fbc32c9328ea958cff.png)

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 9:43 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/2 "2026-08-18T09:43:37Z")

</div>

Est-ce que tu as un accès facile à la base de données ? Est-ce que tu es prêt à supprimer des anciens états pour ces appareils ?  
Si oui, on peut te guider pour lancer des requêtes à la main.

Sinon, on peut considérer que c’est un bug et améliorer la migration pour qu’elle soit faite par morceaux ou en fond.

Tu essayes de mettre à jour dans l’interface Gladys pour z2m ? Pour ajouter une fonctionnalité ?

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 10:09 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/3 "2026-08-18T10:09:00Z")

</div>

Oui sur ça pas de soucis 🙂

Je tentais de mettre a jour ma prise pour y ajouter les features de conso d’energie depuis l’interface gladys dans decouverte puis MAJ

Le mieux serait quand même de ne pas supprimé 😃

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 10:21 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/4 "2026-08-18T10:21:47Z")

</div>

J’ai poursuivi le diagnostic avec **ChatGPT** , en profitant du fait que Gladys était encore dans l’état « freeze ».

Le problème apparaît lors de la **mise à jour/synchronisation d’un device Zigbee2MQTT depuis Gladys**. Dans mon cas, il s’agissait d’une prise qui devait récupérer de nouvelles fonctionnalités liées à l’énergie/consommation.

Plusieurs vérifications ont permis d’écarter quelques pistes :

- Le conteneur Gladys ne sature pas : environ **3 % CPU et 2,4 Go de RAM sur 19 Go disponibles** pendant le freeze.
- Zigbee2MQTT ne semble pas non plus saturé.
- Le process Node de Gladys reste vivant.
- `GET /` sur Gladys répond immédiatement en `HTTP 200`, donc Express est toujours capable de servir le frontend statique.
- En revanche, les appels à l’API dynamique, par exemple la récupération des devices via mon proxy, finissent en **timeout**.
- SQLite reste accessible depuis un autre processus pendant le freeze : des requêtes simples répondent en environ **0,5 seconde**.
- Le WAL SQLite faisait environ 1 Go, mais `PRAGMA wal_checkpoint(PASSIVE)` retourne `0|227|227`, donc pas d’indication d’un checkpoint bloqué.
- `t_device_feature_state` contient **0 ligne** (les historiques ont été migrés vers DuckDB) et `t_device_feature` seulement **446 lignes**.

Avec ChatGPT, on a ensuite inspecté directement le code présent dans mon conteneur Gladys.

La partie Zigbee2MQTT `getDiscoveredDevices.js` contient bien les correctifs récents concernant les features énergie : conservation des features `consumption/cost`, merge avec le device existant, puis appel à `addEnergyFeatures()`.

En revanche, dans mon `device.create.js`, après la mise à jour d’une feature, j’ai actuellement :

```
await deviceFeature.update(featureToUpdate, { transaction });

if (deviceFeature.keep_history === false) {
  deviceFeaturesIdsToPurge.push(deviceFeature.id);
}

```

ChatGPT a comparé ce comportement avec le code actuel de Gladys et a identifié une différence importante. Le code corrigé mémorise l’ancienne valeur :

```
const keepHistoryBeforeUpdate = deviceFeature.keep_history;

await deviceFeature.update(featureToUpdate, { transaction });

if (
  keepHistoryBeforeUpdate !== false &&
  deviceFeature.keep_history === false
) {
  deviceFeaturesIdsToPurge.push(deviceFeature.id);
}

```

La différence est que dans ma version, **chaque mise à jour d’un device peut redemander une purge pour toutes les features qui ont déjà `keep_history=false`** , même si cette valeur n’a pas changé.

Après la transaction, Gladys émet ensuite :

```
this.eventManager.emit(
  EVENTS.DEVICE.PURGE_STATES_SINGLE_FEATURE,
  deviceFeatureIdToPurge
);

```

L’hypothèse actuelle proposée par **ChatGPT** est donc que les mises à jour Z2M provoquent une accumulation de tâches de purge inutiles. Ces traitements passent notamment par DuckDB et pourraient s’accumuler jusqu’à rendre les API dynamiques de Gladys non réactives, alors que le process Node lui-même continue de fonctionner.

Cette hypothèse correspond particulièrement bien au comportement observé : **CPU/RAM normaux + frontend statique accessible + SQLite accessible + API Gladys qui timeout**.

---

<div class="post-metadata">

**Author:** ![mutmut](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/mutmut/32/14064_2.png) [@mutmut](https://community.gladysassistant.com/u/mutmut)\
**Post date:** [Août 18, 2026, 10:32 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/5 "2026-08-18T10:32:39Z")

</div>

Ce n’est pas la même intégration mais ça ressemble très étrangement à ce que j’ai eu et que j’ai ouvert en Issue : [Overkiz integration: assigning a room to a device takes several minutes (freezes the interface) · Issue #2900 · GladysAssistant/Gladys · GitHub](https://github.com/GladysAssistant/Gladys/issues/2900)

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 11:02 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/6 "2026-08-18T11:02:02Z")

</div>

@pierre-gilles @cicoub13 petite avancé

Résumé par chatGPT:

## Freeze complet de Gladys lors de la mise à jour d’un appareil Zigbee2MQTT

Je rencontre un blocage reproductible de Gladys lorsque je mets à jour depuis l’interface Zigbee2MQTT une prise nommée **Station informatique**.

À l’origine, je voulais simplement mettre à jour cet appareil car certaines fonctionnalités liées à l’énergie/consommation étaient absentes.

### Symptômes

Lors de la mise à jour de l’appareil depuis Gladys :

- la requête finit par timeout ;

- l’interface devient partiellement ou totalement inutilisable ;

- les écritures SQLite commencent ensuite à échouer avec :

Par exemple :

```
Unable to reset failure count of integration ...
SQLITE_BUSY: database is locked

```

Le serveur HTTP lui-même continue toutefois à répondre sur le port 8455.

### Configuration DB

La base SQLite est assez importante :

```
gladys-production.db ~12 Go
gladys-production.db-wal ~1 Go
gladys-production.duckdb ~1,9 Go

```

SQLite fonctionne en WAL :

```
PRAGMA journal_mode;
wal

```

Un checkpoint passif fonctionne :

```
PRAGMA wal_checkpoint(PASSIVE);
0|227|227

```

Les requêtes simples sur SQLite restent rapides :

```
SELECT COUNT(*) FROM t_device_feature;
446

real 0m0.090s

```

Et :

```
SELECT COUNT(*) FROM t_device_feature_state;
0

```

Les états semblent donc bien avoir été migrés vers DuckDB.

### Appareil concerné

L’appareil est :

```
id:
fd928ba6-ca0d-4a0d-8483-5b74cfddce8c

external_id:
zigbee2mqtt:Station informatique

```

Avant la tentative de mise à jour, ses features enregistrées sont notamment :

```
Commutateur
Puissance consommée
Intensité consommée
Tension moyenne
Energie consommée
Intensité du signal
Mode de contrôle d'accès

```

La feature «&nbsp;Mode de contrôle d’accès&nbsp;» correspond à :

```
zigbee2mqtt:Station informatique:access-control:mode:child_lock

```

### Investigation dans device.create.js

J’ai instrumenté :

```
/src/server/lib/device/device.create.js

```

afin de déterminer précisément où la transaction se bloque.

Le début de la mise à jour fonctionne normalement :

```
[DEBUG DEVICE CREATE] START zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] BEFORE getDeviceInDb zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] AFTER getDeviceInDb zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] BEFORE device update zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] AFTER device update zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] BEFORE feature cleanup zigbee2mqtt:Station informatique

```

Le blocage se produit donc pendant cette partie de `device.create.js` :

```
await Promise.map(deviceInDb.features, async (existingFeature) => {
  if (!matchFeatureInList(existingFeature, features)) {
    await existingFeature.destroy({ transaction });
  }
});

```

J’ai ensuite instrumenté chaque feature.

Résultat :

```
[DEBUG FEATURE CLEANUP] ...:switch:binary:state matched= true
[DEBUG FEATURE CLEANUP] ...:switch:power:power matched= true
[DEBUG FEATURE CLEANUP] ...:switch:current:current matched= true
[DEBUG FEATURE CLEANUP] ...:switch:voltage:voltage matched= true
[DEBUG FEATURE CLEANUP] ...:switch:energy:energy matched= true

```

Puis :

```
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:access-control:mode:child_lock matched= false
[DEBUG FEATURE DESTROY] BEFORE zigbee2mqtt:Station informatique:access-control:mode:child_lock

```

Et **aucun `DEBUG FEATURE DESTROY AFTER` n’apparaît**.

La feature suivante est encore inspectée par le `Promise.map` :

```
[DEBUG FEATURE CLEANUP] ...:signal:integer:linkquality matched= true

```

mais le `Promise.map` ne termine jamais puisque le `destroy()` de `child_lock` reste bloqué.

### Ce qui semble se produire

La nouvelle définition remontée par Zigbee2MQTT ne contient plus la feature :

```
access-control:mode:child_lock

```

Gladys considère donc logiquement cette ancienne feature comme supprimée et exécute :

```
await existingFeature.destroy({ transaction });

```

C’est précisément cet appel qui ne retourne pas.

La transaction `device.create()` reste alors ouverte.

Peu après, d’autres composants de Gladys essayent d’écrire dans SQLite et commencent à produire :

```
SQLITE_BUSY: database is locked

```

Par exemple les mises à jour de `t_service` :

```
UPDATE `t_service`
SET `failure_count`=$1,`updated_at`=$2
WHERE `id` = $3

```

finissent en `SequelizeTimeoutError`.

Cela donne donc, à ce stade, la séquence suivante :

```
Mise à jour appareil Z2M
    ↓
device.create()
    ↓
deviceInDb.update() OK
    ↓
nettoyage des anciennes features
    ↓
child_lock absent du nouveau device
    ↓
existingFeature.destroy({transaction})
    ↓
BLOCAGE
    ↓
transaction SQLite restant ouverte
    ↓
autres écritures
    ↓
SQLITE_BUSY / database is locked

```

### À propos de l’énergie

Le problème est apparu pendant que j’essayais de récupérer les fonctionnalités de consommation d’énergie de cette prise, ce qui m’avait initialement orienté vers le nouveau code d’energy monitoring.

Cependant les traces montrent maintenant que **le blocage intervient avant la création/mise à jour des features énergie**.

La feature `energy` existante est d’ailleurs correctement reconnue :

```
zigbee2mqtt:Station informatique:switch:energy:energy matched=true

```

Le blocage est déclenché par la tentative de suppression de l’ancienne feature `child_lock`.

### Autre observation

Pendant le freeze, le service Energy Monitoring continue à démarrer ses traitements et indique notamment :

```
Found 52 energy devices
Found 0 devices with both INDEX and thirty-minutes-consumption features

```

Puis les `SQLITE_BUSY` apparaissent sur différentes parties de Gladys.

J’ai également vérifié `t_job` : les jobs de migration SQLite → DuckDB et de purge des états orphelins DuckDB sont indiqués `success`.

### Patch testé sans succès

J’avais également testé une modification de `device.create.js` afin de ne déclencher la purge des états que lorsque `keep_history` passe réellement de `true` à `false` :

```
const keepHistoryBeforeUpdate = deviceFeature.keep_history;

await deviceFeature.update(featureToUpdate, { transaction });

if (keepHistoryBeforeUpdate !== false && deviceFeature.keep_history === false) {
  deviceFeaturesIdsToPurge.push(deviceFeature.id);
}

```

Cela ne corrige pas ce problème : grâce aux traces supplémentaires, on sait maintenant que le freeze intervient plus tôt, pendant le `destroy()` de la feature obsolète.

### État actuel du diagnostic

Le point de blocage reproductible est donc maintenant identifié assez précisément :

```
existingFeature.destroy({ transaction })

```

pour :

```
zigbee2mqtt:Station informatique:access-control:mode:child_lock

```

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 11:13 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/7 "2026-08-18T11:13:31Z")

</div>

Il faudrait initier une tâche de destruction des états en asynchrone pour pouvoir continuer le travail.

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 11:19 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/8 "2026-08-18T11:19:38Z")

</div>

### Mise à jour : cause du blocage identifiée plus précisément

J’ai continué à investiguer le freeze lors de la mise à jour d’un périphérique Zigbee2MQTT.

Le périphérique concerné est :

- `Station informatique`
- external ID : `zigbee2mqtt:Station informatique`

J’ai ajouté temporairement des logs de debug autour du nettoyage des features dans `device.create.js`.

Lors de la mise à jour, Gladys arrive normalement jusqu’au nettoyage des features :

```plaintext
[DEBUG DEVICE CREATE] START zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] BEFORE getDeviceInDb zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] AFTER getDeviceInDb zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] BEFORE device update zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] AFTER device update zigbee2mqtt:Station informatique
[DEBUG DEVICE CREATE] BEFORE feature cleanup zigbee2mqtt:Station informatique
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:switch:binary:state matched= true
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:switch:power:power matched= true
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:switch:current:current matched= true
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:switch:voltage:voltage matched= true
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:switch:energy:energy matched= true
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:access-control:mode:child_lock matched= false
[DEBUG FEATURE DESTROY] BEFORE zigbee2mqtt:Station informatique:access-control:mode:child_lock
[DEBUG FEATURE CLEANUP] zigbee2mqtt:Station informatique:signal:integer:linkquality matched= true

```

Il n’y a jamais de log `AFTER` après la tentative de suppression de `child_lock`.

Le blocage se produit donc ici dans `device.create.js` :

```js
await existingFeature.destroy({ transaction });

```

### Pourquoi cette feature est très longue à supprimer

J’ai vérifié les lignes faisant référence à cette feature précise :

```plaintext
feature id:
557c3bba-bcc2-47e7-9f7f-f39614093509

energy_children 0
states 0
aggregates 509363
supported_options 0

```

La feature n’a donc plus d’états classiques dans SQLite, mais elle possède encore **509 363 lignes** dans :

```plaintext
t_device_feature_state_aggregate

```

La clé étrangère est configurée ainsi :

```plaintext
t_device_feature_state_aggregate.device_feature_id
    -> t_device_feature.id
    ON DELETE CASCADE

```

La table des agrégats possède bien des index, notamment :

```plaintext
t_device_feature_state_aggregate_device_feature_id
t_device_feature_state_aggregate_device_feature_id_type_created_at

```

La suppression de la feature obsolète `child_lock` entraîne donc la suppression en cascade de plus de 500 000 agrégats SQLite, directement dans la transaction de mise à jour du périphérique.

Pendant cette opération, les autres écritures SQLite commencent à échouer avec :

```plaintext
SequelizeTimeoutError
SQLITE_BUSY: database is locked

```

Par exemple, les mises à jour de `t_service.failure_count` effectuées par les intégrations externes finissent par expirer.

La requête HTTP de Gladys finit également par dépasser son délai, ce qui donne l’impression que toute l’interface est figée.

### Gladys gère déjà ce problème dans un autre chemin de code

Il est intéressant de constater que `device.destroy.js` contient déjà une protection explicite contre ce type de situation lors de la suppression complète d’un périphérique.

Le code compte les états et les agrégats avant de supprimer le périphérique. Lorsqu’il y en a trop, il évite la suppression en cascade immédiate et déclenche à la place :

```js
this.eventManager.emit(
  EVENTS.DEVICE.PURGE_STATES_SINGLE_FEATURE,
  deviceFeature.id
);

```

La suppression du périphérique est alors interrompue afin que les historiques puissent être nettoyés auparavant.

De son côté, `device.purgeStatesByFeatureId.js` supprime volontairement les agrégats SQLite par lots :

```sql
DELETE FROM t_device_feature_state_aggregate WHERE id IN (
  SELECT id FROM t_device_feature_state_aggregate
  WHERE device_feature_id = :id
  LIMIT :limit
);

```

avec une temporisation entre les lots.

Les commentaires présents dans le code indiquent explicitement que ce fonctionnement sert notamment à éviter de bloquer la base pendant une longue période.

### Incohérence possible entre les deux chemins de suppression

Il semble donc y avoir une différence de comportement entre la suppression complète d’un périphérique et la suppression d’une feature devenue obsolète pendant une mise à jour.

Pour la suppression d’un périphérique :

```plaintext
device.destroy()
    -> compte les états
    -> s’il y en a trop :
       PURGE_STATES_SINGLE_FEATURE
       -> nettoyage progressif

```

Alors que lors de la mise à jour d’un périphérique existant :

```plaintext
device.create()
    -> détecte une feature qui n’existe plus
    -> existingFeature.destroy({ transaction })
    -> ON DELETE CASCADE SQLite
    -> suppression synchrone d’environ 509k agrégats
    -> verrou SQLite prolongé

```

Dans mon cas, la feature devenue obsolète est `child_lock`.

### Pourquoi le problème semblait initialement lié à l’énergie

Le problème a été découvert lorsque j’essayais de mettre à jour ma prise `Station informatique`.

La prise était déjà présente dans Gladys, mais il lui manquait la partie liée à la consommation d’énergie que je souhaitais récupérer lors de la mise à jour depuis Zigbee2MQTT.

Au départ, le freeze semblait donc lié à l’ajout des nouvelles features d’énergie.

Les traces montrent finalement que le blocage intervient plus tôt : pendant le nettoyage des anciennes features, lorsque Gladys tente de supprimer `child_lock`.

Ce n’est donc vraisemblablement pas directement la création des nouvelles features d’énergie qui bloque, mais la suppression d’une ancienne feature possédant un très grand nombre d’agrégats historiques.

### Piste de correction

Remplacer simplement :

```js
await existingFeature.destroy({ transaction });

```

par un événement `PURGE_STATES_SINGLE_FEATURE` ne semble pas suffisant.

Cela permettrait de purger progressivement l’historique, mais la feature obsolète elle-même resterait en base.

Il faudrait probablement un mécanisme permettant de :

1. détecter qu’une feature devenue obsolète possède beaucoup d’historique ;
2. éviter son `DELETE CASCADE` dans la transaction de mise à jour ;
3. purger ses états et agrégats progressivement en arrière-plan ;
4. supprimer ensuite la feature devenue obsolète ;
5. vérifier éventuellement qu’elle est toujours obsolète au moment de la suppression, au cas où l’intégration l’aurait exposée à nouveau entre-temps.

J’arrête mes investigations ici. J’espere que ça vous aidera 🙂

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 11:21 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/9 "2026-08-18T11:21:24Z")

</div>

Parfait. Tu fais une PR ? ou tu veux qu’on le fasse ?

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 11:24 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/10 "2026-08-18T11:24:44Z")

</div>

euh je préfère que ce soit fait par vous stp 🙂

C’est a mon sens une brique un peu trop technique pour que j’y touche 😕

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 11:41 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/11 "2026-08-18T11:41:02Z")

</div>

En continuant l’analyse, je me rends compte que tu as beaucoup d’états aggrégés dans `t_device_feature_state_aggregate` qui n’est plus utilisée. Tout est dans DuckDB (états et aggrégats calculés à la volée).

Je pense que la purge ici ne purge que les états et pas cette table :

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/c/b/cb1785d535b099f8aa009a49e9c027db68076c52.png)

Autant supprimer les données et ne pas implémenter le fix sur une table qui est censée être vide. Je continue l’investigation 🕵

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 12:10 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/12 "2026-08-18T12:10:37Z")

</div>

Je soupçonne qu’il te reste des états aggrégés non purgés. J’ai ouvert une PR pour les afficher ici [Show the remaining SQLite aggregates in the DuckDB migration card by cicoub13 · Pull Request #2952 · GladysAssistant/Gladys · GitHub](https://github.com/GladysAssistant/Gladys/pull/2952)

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/c/9/c9c5a85afa775df2619590fb92a276cc54bca1f9.png)

Mais si tu veux pas attendre, je pense que tu peux cliquer sur le bouton Purger, puis Nettoyer la base de données SQLite. Ton problème de mise à jour Zigbee devrait disparaître

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 2:02 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/13 "2026-08-18T14:02:27Z")

</div>

je comprend pas j’ai déjà fais a l’époque de l’arrivé de duckdb

 ![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/6/e/6ee7a4ddd8bca772e44f63c6de3bad257e437e02.png)

Je vien de cliquer sur purgé et je re freeze a nouveau  
J’ai l’impression que je suis bloqué..  
Pour me debloquer il faut je purge mais pour purger je bloque ahah #help 😵‍💫

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 2:10 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/14 "2026-08-18T14:10:36Z")

</div>

Je pense que tu n’es jamais allé jusqu’au bout. Clique sur Purger à un moment où tu n’as pas besoin de Gladys et laisse tourner. Même si tu n’as pas de retour visuel, la purge se fait.

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 2:10 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/15 "2026-08-18T14:10:40Z")

</div>

@cicoub13 pour toi la table ne sert plus ?

---

<div class="post-metadata">

**Author:** ![cicoub13](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/cicoub13/32/4482_2.png) [@cicoub13](https://community.gladysassistant.com/u/cicoub13)\
**Post date:** [Août 18, 2026, 2:11 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/16 "2026-08-18T14:11:58Z")

</div>

La table ne sert plus (sont contenu en tout cas). Il ne faut pas supprimer la table car des migrations y font toujours référence et je ne suis pas sûr du comportement si la table disparaît complètement.

Si tu es à l’aise, tu peux

- éteindre Gladys proprement
- Sauvegarder les fichiers de base de données
- TRUNCATE la table
- Démarrer Gladys

Si tu veux plus d’assurance sur tout ça, tu peux attendre que @pierre-gilles donne son avis.

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 2:15 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/17 "2026-08-18T14:15:29Z")

</div>

C’est ce que je pensais faire.  
Merci de ton retour je vais attendre son avis, peut être qu’il aura une meilleure idée 🙂

---

<div class="post-metadata">

**Author:** ![mutmut](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/mutmut/32/14064_2.png) [@mutmut](https://community.gladysassistant.com/u/mutmut)\
**Post date:** [Août 18, 2026, 6:17 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/19 "2026-08-18T18:17:47Z")

</div>

tu peux partir sur ça déjà, ça suffit amplement pour un cache RW : [Lot SSD NVME 256GB X2 - Accessoires informatique](https://www.leboncoin.fr/ad/accessoires_informatique/3247461279)

Après sur mon synology, j’avais mis les 2 ssd en stockage pour les vm (pas possible pour les docker directement) mais pas de sauvegarde par contre. Attention car méthode non officielle.

---

<div class="post-metadata">

**Author:** ![spenceur](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/spenceur/32/1961_2.png) [@spenceur](https://community.gladysassistant.com/u/spenceur)\
**Post date:** [Août 18, 2026, 10:49 UTC](https://community.gladysassistant.com/t/freeze-pendant-maj-dun-device-z2m/10659/20 "2026-08-18T22:49:28Z")

</div>

## Retour après nettoyage de la base

J’ai finalement réussi à corriger le problème (trop impatient que je suis).

Ma base SQLite `gladys-production.db` avait atteint environ **12 Go**.

### 1. Vérification de l’intégrité gladys arrêté

J’ai commencé par créé un backup de ma base puis j’ai lancer `PRAGMA quick_check;`.

Sur mon NAS, l’opération a été extrêmement longue à cause des performances I/O.

Le `quick_check` a mis environ **3 heures** à se terminer, mais a finalement retourné `ok`.

La base SQLite n’était donc **pas corrompue**.

Pendant le contrôle, le processus `sqlite3` était régulièrement en état `D` (`disk sleep`) et les compteurs `/proc/<pid>/io` montraient que les lectures continuaient bien à progresser.

### 2. Identification de la table problématique

Le problème venait principalement de la table `t_device_feature_state_aggregate`.

La base faisait environ **12 Go** , et cette table avec ses index semblait représenter l’immense majorité de l’espace utilisé.

J’ai donc arrêté Gladys avant d’intervenir sur la base.

### 3. Suppression et recréation de la table

Plutôt que de faire un énorme `DELETE FROM t_device_feature_state_aggregate;`, j’ai choisi de supprimer complètement la table puis de la recréer avec son schéma et ses index d’origine.

Là encore, l’opération a été **très longue** à cause des I/O du NAS.

Une première tentative a été interrompue après environ **1 h 30** , à cause d’une coupure de ma session SSH.

À ce moment-là, SQLite avait déjà effectué environ **4,2 Go de lectures** (`read_bytes: 4 197 961 728`).

Comme le `COMMIT` n’avait pas eu lieu, SQLite a correctement annulé la transaction et l’ancienne table était toujours présente.

### 4. Deuxième tentative avec `nohup`

J’ai donc relancé l’opération avec `nohup` afin qu’elle survive à une éventuelle déconnexion SSH.

Cette fois, l’opération est allée jusqu’au bout.

Quelques mesures pendant le `DROP TABLE` :

| Temps écoulé | Données lues |
| --- | --- |
| ~22 min | 0,73 Go |
| ~1 h 04 | 2,75 Go |
| ~1 h 32 | 4,20 Go |
| ~1 h 50 | 5,02 Go |
| ~2 h 20 | 6,02 Go |
| ~2 h 30 | 9,44 Go |
| ~2 h 39 | 10,81 Go |

L’opération complète a finalement pris environ **2 h 45**.

Le processus était presque constamment en état `D` (`disk sleep`), avec très peu de CPU utilisé. Le facteur limitant était donc clairement les **I/O du NAS**.

### 5. Vérification après recréation

Après la fin de l’opération :

`SELECT COUNT(*) FROM t_device_feature_state_aggregate;`

retourne **0**.

La table a donc bien été recréée vide.

J’ai ensuite effectué `PRAGMA wal_checkpoint(TRUNCATE);`.

Résultat : `0|0|0`.

Le WAL a donc été correctement vidé.

### 6. Espace récupéré

Le fichier SQLite fait toujours physiquement environ **12 Go** , ce qui est normal sans `VACUUM`.

En revanche :

- `page_count` = **3 118 963**
- `freelist_count` = **3 098 841**

Cela signifie qu’environ **99,35 % des pages de la base sont maintenant libres**.

L’espace n’a donc pas encore été rendu au système de fichiers, mais SQLite peut désormais le réutiliser.

Je n’ai volontairement pas encore lancé de `VACUUM`.

### 7. Résultat après redémarrage de Gladys

J’ai ensuite redémarré Gladys.

Tout fonctionne normalement.

Et surtout, j’ai refait le test qui posait problème : la modification d’un device qui était auparavant extrêmement lente/bloquée.

Cette fois, la modification du device s’est faite en **quelques secondes**.

### Conclusion

- `PRAGMA quick_check` : **OK** , mais environ **3 h**
- base SQLite : environ **12 Go**
- `t_device_feature_state_aggregate` représentait pratiquement toute la base
- première tentative de suppression interrompue après **~1 h 30**
- deuxième tentative complète : **~2 h 45**
- `freelist_count` : **3 098 841 pages libres sur 3 118 963** , soit **~99,35 %**
- après redémarrage, Gladys fonctionne normalement
- la modification du device problématique se fait maintenant en **quelques secondes**

Le souci était donc bien lié à l’explosion de `t_device_feature_state_aggregate` et aux performances I/O nécessaires pour travailler sur cette énorme table.

### Reste a faire

- Supprimer mon bckp
- faire un vacuum
- mettre des ssd nvme 😅

Merci @cicoub13 @mutmut
