تكرار السؤال: …
الإجابة المختصرة
تنفذ بحجز عميل محدد من الـ pool، وتشغيل BEGIN، وتنفيذ العمليات، ثم COMMIT في حال النجاح أو ROLLBACK في كتلة catch.
الشرح
المعاملة تضمن مبدأ الذرية (Atomicity) في ACID؛ فإما أن تنجح كل التعديلات معاً أو تُلغى بالكامل. من الضروري جداً استخدام نفس الاتصال (Dedicated Client) لكل عمليات المعاملة الواحدة، لأن استدعاء pool.query() يوزع العمليات عشوائياً عبر اتصالات مختلفة مما يفسد المعاملة تماماً.
مثال بالكود
const client = await pool.connect();
try {
await client.query("BEGIN");
await client.query("UPDATE accounts SET balance = balance - 100 WHERE id = $1", [from]);
await client.query("UPDATE accounts SET balance = balance + 100 WHERE id = $1", [to]);
await client.query("COMMIT");
} catch (e) {
await client.query("ROLLBACK");
throw e;
} finally {
client.release(); // return the dedicated connection to the pool
}أخطاء شائعة
- تنفيذ أوامر BEGIN و COMMIT عبر pool.query المباشر بدلاً من عميل مخصص محجوز.