Hallo dedlfix,
also habe ich nach wie vor nur vom Tuten Ahnung gehabt, und konnte dazu ein bisschen auf dem Kamm blasen. Für ein Klarinettenkonzert hat's nicht gereicht…
Schlussfolgerung: Serialize-Modus einschalten. Aber auch dann musst du immer noch aufpassen. Die Funktionen arbeiten weiterhin asynchron und kehren sofort zurück...
D.h. man kommt nicht drumherum, die Dinge, die nacheinander ablaufen müssen, per Callback zu serialisieren?
Lösung für hmm müsste also sein, dass er INSERT_MITARBEITER und SELECT_USER_MITARBEITER nicht serialisieren muss, aber INSERT_USER_MITARBEITER, INSERT_SKILL und REPLACE_SKILL auf drei Callback Funktionen verteilt werden müssen?
Wobei ich ja ehrlicherweise die SQL Magic, die da ausgeübt wird, nicht verstanden habe. Beispiel: Skillniveaus.
-- INSERT_SKILL
INSERT INTO mitarbeiter_skill (mitarbeiter_id, skill, subskill, nivau)
SELECT ?m_id, ?skill, ?subskill, ?nivau
WHERE NOT EXISTS (SELECT 1 FROM mitarbeiter_skill
WHERE mitarbeiter_id = ?m_id and skill = ?skill and subskill = ?subskill)
-- REPLACE_SKILL
REPLACE INTO mitarbeiter_skill (mitarbeiter_id, skill, subskill, nivau)
SELECT ?m_id, ?skill, ?subskill, ?nivau
WHERE EXISTS (SELECT 1 FROM mitarbeiter_skill
WHERE mitarbeiter_id = ?m_id and skill = ?skill and subskill = ?subskill)
Das erste Statement fügt einen neuen Satz mit ID, Skill, Subskill und Niveau ein, wenn ein Satz mit ID, SKILL und SUBSKILL noch nicht existiert. D.h. ein Update für bestehende Sätze erfolgt nicht.
Das zweite Statement macht einen REPLACE aus einem SELECT ... WHERE EXISTS. Das klingt nach komplexem Gewusel. Zuerst wird per EXISTS (SELECT 1...) geprüft, ob der Satz zu (id,skill,subskill) schon da ist. Wenn ja, DANN wird er replaced, d.h. gelöscht und neu angelegt.
Diese beiden Statements laufen parallel los und es ist klar, dass sie kollidieren. Aber wenn man sie serialisiert, machen sie dann überhaupt noch Sinn? Wenn der INSERT etwas einfügt, wird der REPLACE es definitiv gleich wieder löschen.
Hier steht, dass der Callback eines db.run() Aufrufs ein this bekommt, in dem die Anzahl der beeinflussten Sätze steht (this.changes). Es wäre aus meiner Sicht sinnvoller, zunächst einen einfachen Update auf's Niveau zu versuchen, und wenn im Callback dazu dann this.changes===0 ist, einen INSERT folgen zu lassen. Die "INSERT ... ON DUPLICATE KEY UPDATE..." Erweiterung aus MySQL scheint's in Sqlite ja nicht zu geben. Aber diese WHERE EXISTS Hexerei kommt mir doch so vor, als gehöre sie nach Hogwarts und nicht auf einen Node-Server.
Rolf
Dosen sind silbern