فصل ۷: مدیریت و امنیت — کاربران، بکاپ، Replication و کد سمت سرور

Stored Procedure، Function، Trigger و Event: کِی استفاده کنیم؟

منطق داخل دیتابیس: ابزاری دولبه

MySQL می‌تواند کد را خودش اجرا کند: رویه (Procedure)، تابع (Function)، تریگر و رویداد زمان‌بندی‌شده (Event). این ابزارها قدرتمندند، اما منطقی که داخل دیتابیس است در git و code review و تست‌های برنامه کمتر دیده می‌شود و ORM جنگو از آن خبر ندارد.

ابزارمناسب براینامناسب برای
Procedureعملیات دسته‌ای نزدیک داده، بستن ماه مالیمنطق کسب‌وکار روزمره
Functionمحاسبه‌ی کوچک و قطعی مثل متراژکوئری درون تابع که در WHERE صدا زده شود
Triggerیکدست‌سازی داده، لاگ ممیزیارسال پیامک یا منطق پیچیده
Eventپاک‌سازی دوره‌ای جدول‌هاکارهایی که نیاز به پایش و تکرار دارند

Procedure با خطای کنترل‌شده

DELIMITER $$
CREATE PROCEDURE reserve_stock(IN p_product_id INT UNSIGNED, IN p_qty INT UNSIGNED)
BEGIN
  UPDATE products SET stock = stock - p_qty
   WHERE id = p_product_id AND stock >= p_qty;
  IF ROW_COUNT() = 0 THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'insufficient stock';
  END IF;
END$$
DELIMITER ;

CALL reserve_stock(7, 2);

Function و Trigger

CREATE FUNCTION carpet_area_m2(p_width_cm INT, p_length_cm INT)
RETURNS DECIMAL(8,2) DETERMINISTIC NO SQL
RETURN ROUND(p_width_cm * p_length_cm / 10000, 2);

-- یکدست کردن ی و ک عربی پیش از ذخیره
DELIMITER $$
CREATE TRIGGER customers_bi BEFORE INSERT ON customers
FOR EACH ROW
BEGIN
  SET NEW.full_name = REPLACE(REPLACE(NEW.full_name, 'ي', 'ی'), 'ك', 'ک');
END$$
DELIMITER ;

همین تریگر را برای BEFORE UPDATE هم بسازید؛ وگرنه ویرایش نام دوباره حروف عربی را وارد می‌کند. تریگر در این‌جا مناسب است چون داده از چند مسیر (پنل، API، ورود از اکسل) وارد می‌شود و دیتابیس تنها نقطه‌ی مشترک است.

Event: نظافت شبانه

CREATE EVENT purge_done_jobs
  ON SCHEDULE EVERY 1 DAY STARTS '2026-10-03 03:30:00'
  DO DELETE FROM jobs
     WHERE status = 'done' AND finished_at < NOW() - INTERVAL 30 DAY;

SHOW EVENTS FROM carpet_factory;

قاعده‌ی سرانگشتی: قیدهایی که «هر برنامه‌ای» باید رعایت کند و پاک‌سازی‌های ساده را در دیتابیس بگذارید؛ منطق کسب‌وکار را در کد برنامه که تست و نسخه‌بندی می‌شود.

نکته‌هایی که کمتر کسی می‌داند

  • تریگرها برای تغییراتی که با ON DELETE CASCADE کلید خارجی انجام می‌شوند اجرا نمی‌شوند؛ لاگ ممیزی مبتنی بر تریگر این حذف‌ها را نمی‌بیند.
  • با binlog روشن، ساخت تابع بدون یکی از عبارت‌های DETERMINISTIC، NO SQL یا READS SQL DATA خطای 1418 می‌دهد.
  • DELIMITER دستور کلاینت mysql است، نه SQL؛ در RunSQL مایگریشن جنگو یا درایور پایتون، CREATE PROCEDURE را بدون آن و به‌صورت یک دستور بفرستید.
  • روتین‌ها به‌طور پیش‌فرض با مجوزهای DEFINER اجرا می‌شوند؛ اگر آن کاربر حذف شود، با ERROR 1449 از کار می‌افتند. SQL SECURITY INVOKER این وابستگی را برمی‌دارد.
  • Eventها روی replica با وضعیت SLAVESIDE_DISABLED ساخته می‌شوند تا دوبار اجرا نشوند؛ بعد از جایگزینی replica به‌جای source، آن‌ها را دستی فعال کنید.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.