تصور کنید یک پرسوجوی ساده که توسط هوش مصنوعی نوشته شده، در عرض چند ثانیه پردازنده سرور تولیدی شما را به ۱۰۰٪ برساند و کل سرویس را از دسترس خارج کند. اگر فکر میکنید با دادن دسترسی «فقط خواندنی» (Read-only) امنیت دادههایتان تأمین شده است، در واقع تنها نیمی از مسیر را رفتهاید و سیستم خود را در برابر فروپاشی منابع بیدفاع گذاشتهاید. در حالی که بسیاری از تیمها برای ایمنسازی دادههای خود به نقشهای read-only تکیه میکنند، باید دانست که مجوزها (Permissions) تنها از تغییر دادهها جلوگیری میکنند، اما مانع از اتمام منابع (Resource Exhaustion) نمیشوند. یک شرط Join ساده که در یک پرسوجوی تولید شده توسط AI فراموش شده باشد، میتواند در عرض چند ثانیه CPU سرور تولیدی را به ۱۰۰٪ برساند. این همان لایهی حفاظتی است که اکثر تیمها نادیده میگیرند: تمایز حیاتی بین مدیریت مجوزها و اعمال محدودیتهای منابع.
بسیاری از توسعهدهندگان به اشتباه تصور میکنند وقتی یک مدل زبانی بزرگ (LLM) — مثل کتابخانهداری که میلیاردها صفحه را خوانده و حالا با همان لحن جواب میدهد — نتواند دستوراتی مثل INSERT یا UPDATE یا DELETE یا DROP را اجرا کند، پایگاهداده در امان است. اما این یک تصور خطرناک است. مدلهای زبانی بزرگ اغلب SQLهایی مینویسند که از نظر دستوری (Syntactically) درست هستند اما از نظر محاسباتی فاجعهبارند. آنها با اعتمادبهنفس کامل کدی را تولید میکنند، اما گاهی یک شرط Join یا یک عبارت WHERE را فراموش میکنند. این یعنی آنها در تولید پرسوجوهایی که کاملاً معتبر هستند، کاملاً read-only هستند و در عین حال کاملاً قادرند سرور شما را در ساعت ۲ بعدازظهر روز سهشنبه کرش کنند، بسیار ماهرند. این چالشها اغلب ریشه در شکاف معنایی میان ساختار دادههای سازمانی و درک مدلهای هوش مصنوعی دارد که باعث میشود مدلها بدون شناخت دقیق حجم جداول، پرسوجوهای خطرناکی تولید کنند.
به نقل از مستندات فنی، یک مثال رایج این است که از یک دستیار AI پرسیده شود: «هر مشتری در سال گذشته چند سفارش ثبت کرده است؟». مدل میداند که جدولی به نام orders و جدولی به نام customers وجود دارد، بنابراین چنین مینویسد:
SELECT c.name, COUNT(*) FROM customers c, orders o GROUP BY c.name;
این اتصال با کاما (Comma Join) بدون عبارت ON در واقع یک «حاصلضرب دکارتی» (Cartesian Product) ایجاد میکند. اگر شما ۵۰ هزار مشتری و ۲ میلیون سفارش داشته باشید، پایگاهداده پیش از آنکه حتی به مرحلهی شمارش برسد، سعی میکند یک نتیجهی میانی با ۱۰۰ میلیارد ردیف بسازد. این یک دستور SELECT کاملاً قانونی است که یک نقش read-only با خوشحالی اجازه اجرای آن را میدهد و نتیجهاش افت شدید و فوری عملکرد برای تمام کاربران است. همین فاجعه با یک دستور بهظاهر بیخطر مثل SELECT * FROM events روی جدولی با ۵۰۰ میلیون ردیف، یا یک ORDER BY بدون ایندکس روی یک مجموعهدادهی عظیم رخ میدهد. هیچکدام از اینها «حمله» نیستند؛ بلکه خروجیهای عادی مدلی هستند که نمیداند جداول شما چقدر بزرگاند.
لایهی ضروری محدودیت منابع
برای جلوگیری از این شکستها، تیمها باید یک لایهی محدودیت منابع (Resource-limit layer) پیاده کنند تا تضمین شود که حتی یک پرسوجوی بدساخت، بهجای اینکه هزینهی سنگینی تحمیل کند، بهصورت ارزان (با خطا) شکست بخورد. اولین خط دفاعی، تعیین سقف برای هر مجموعه نتیجه است. شما هرگز نباید اجازه دهید یک پرسوجو تعداد ردیفهای نامحدود برگرداند.
حتی اگر مدل دستور SELECT * FROM events WHERE user_id = 42; را بنویسد، شما باید آنچه مدل ارسال میکند را پیش از اجرا در یک لایهی LIMIT بیرونی قرار دهید:
SELECT * FROM ( SELECT * FROM events WHERE user_id = 42 ) AS ai_query LIMIT 1000;
یک مقدار پیشفرض منطقی بین ۵۰۰ تا ۱۰۰۰ ردیف است. مدل AI تقریباً هرگز برای پاسخ به یک سؤال یا خلاصه کردن یک روند، به بیش از این مقدار نیاز ندارد. این سقف هم از پایگاهداده (دادههای کمتر برای متریالیزه کردن و مرتبسازی) و هم از فرآیندی که نتایج را مصرف میکند در برابر غافلگیریهای Out-of-memory محافظت میکند. این محدودیت را قابل تنظیم (Configurable) کنید، اما حالت «بدون محدودیت» هرگز نباید حالت پیشفرض برای پرسوجویی باشد که خودتان ننوشتهاید.
اما محدودیت ردیف به تنهایی کافی نیست، زیرا یک Join دکارتی میتواند پیش از آنکه حتی یک ردیف تولید کند، منابع را بسوزاند. اینجا به «زمان تهی شدن» یا Statement Timeout نیاز دارید تا پرسوجوهایی که بیش از مدت زمان مشخصی اجرا میشوند، متوقف شوند. در PostgreSQL، میتوان این محدودیت را برای هر نقش (Role) تعریف کرد تا بهطور خودکار روی تمام نشستهایی (Sessions) که AI باز میکند اعمال شود:
ALTER ROLE ai_readonly SET statement_timeout = '30s';
پایگاهداده MySQL نیز محافظت مشابهی را از طریق max_execution_time به عنوان یک Query Hint یا متغیر سیستمی ارائه میدهد. تعیین یک سقف ۳۰ ثانیهای — که یک نقطه شروع رایج برای استفادههای تعاملی یا تحلیلی است — تضمین میکند که یک پرسوجوی runaway بهصورت ارزان شکست بخورد و یک خطای تمیز برگرداند که AI بتواند به آن واکنش نشان دهد، بهجای آنکه بهطور خاموش کل سیستم را تخریب کند. همانطور که Crunchy Data اشاره میکند، یک statement timeout تضمین میکند که هیچ کلاینت متصلی «پرسوجوهایی طولانیتر از آن زمان اجرا نکند». این تنها یک خط تنظیمات است که شعاع تخریب (Blast Radius) را بهشدت کاهش میدهد.
جداسازی ساختاری
در محیطهای تولیدی، قویترین حفاظ یک تنظیم ساده نیست، بلکه این است که AI با کدام سرور صحبت میکند. اگر دستیار شما فقط نیاز به خواندن و تحلیل دارد، هیچ دلیلی ندارد که به پایگاهداده اصلی (Primary) دسترسی داشته باشد. او را به یک Read Replica (نسخهی کپی برای خواندن) متصل کنید. این استراتژی دو مزیت حیاتی دارد:
- جداسازی ترافیک: پرسوجوهای اکتشافی و گزارشگیری با ترافیک واقعی کاربران برای دسترسی به CPU، حافظه یا قفلها (Locks) روی جداول حساس رقابت نمیکنند. یک اسکن تحلیلی سنگین روی Replica، فرآیندهای پرداخت و ورود به سیستم در سرور Primary را دستنخورده باقی میگذارد.
- ایمنی فیزیکی: یک Standby Replica در PostgreSQL طبق قوانین فیزیکی، فقط خواندنی است. این سرور هرگونه عملیات نوشتن را بدون توجه به هر چیزی رد میکند و حتی اگر شما در پیکربندی نقش read-only اشتباه کرده باشید، یک کف حفاظتی سخت فراهم میکند. این یعنی دفاع در عمق (Defense in Depth). این رویکرد در راستای پیادهسازی اصل کمترین امتیاز (Least Privilege) برای ایمنسازی عاملهای هوش مصنوعی است تا دسترسیها دقیقاً به اندازه نیاز و در محیطهای ایزوله تعریف شوند.
انتخاب مدل مناسب به ظرفیت عملیاتی شما بستگی دارد:
- نقش دسترسی کامل روی Primary: هیچ محافظت در برابر نوشتن و هیچ محافظتی در برابر بار ترافیکی ندارد. هزینه پایین.
- نقش Read-only روی Primary: از تغییر دادهها جلوگیری میکند، اما جلوی فشار به سیستم تولیدی را نمیگیرد. هزینه پایین.
- نقش Read-only + Timeout + Row Cap روی Primary: از دادهها محافظت میکند و بهطور جزئی از بار ترافیکی تولیدی جلوگیری میکند. هزینه پایین.
- استفاده از Read Replica با تمام حفاظها: از دادهها محافظت میکند و بهطور کامل ترافیک تولیدی را در امان نگه میدارد. هزینه عملیاتی بالاتر.
یک Replica هزینههای جانبی دارد، از جمله نیاز به سرور دوم، نظارت بر تأخیر در تکثیر (Replication Lag) و ملاحظات Failover. برای یک پایگاهداده کوچک یا تیمهای بسیار کوچک، یک نقش read-only همراه با timeout و row cap روی سرور اصلی، بیشترِ ایمنی مورد نیاز را فراهم میکند. اما زمانی که پایگاهداده شما حیاتی میشود و استفاده از AI از حالت اتفاقی خارج شده و به یک روند تبدیل میشود، Replica تمیزترین مرزی است که میتوانید ترسیم کنید.
مدیریت اتصال و شکل پرسوجو
علاوه بر تکتک پرسوجوها، تیمها باید خودِ اتصال (Connection) را محدود کنند. تایماوتها و محدودیت ردیفها یک پرسوجوی بد را مدیریت میکنند، اما محدودیت اتصال (Connection Limit) جلوی تعداد زیاد پرسوجوهای بد را میگیرد. اگر یک عامل AI یا یک ویژگی رو به مشتری بتواند نشستهای همزمان نامحدود باز کند، یک موج فعالیت میتواند Connection Pool شما را تخلیه کرده و اپلیکیشن واقعی شما را از دسترسی بازدارد.
میتوانید سقف تعداد اتصالات همزمان را برای نقش AI محدود کنید:
ALTER ROLE ai_readonly CONNECTION LIMIT 5;
ترکیب این مورد با statement timeout، همانطور که یکی از مهندسان Postgres گفته است، باعث میشود که «یک statement timeout و connection limit روی یک نقش read-only، ۹۰٪ ایمنی را با ۱۰٪ پیچیدگی فراهم کند».
برای محیطهای با ریسک بالاتر، تیمهای پیشرفته میتوانند «شکل پرسوجو» (Query Shape) را در لایهی اپلیکیشن، پیش از آنکه پرسوجو به دیتابیس برسد، بازرسی کنند. یک پرسوجوی گزارشگیری معمولاً شکلی پیشبینیپذیر دارد: SELECT ... FROM ... WHERE .... اگر یک پرسوجوی تولید شده ناگهان به کاتالوگهای سیستمی اشاره کند، چندین عملیات UNION را روی هم بچیند یا دهها جدول را Join کند، میتوانید آن را رد کنید. مراقب باشید که در این بخش دچار Over-engineering نشوید؛ این لایه را تنها زمانی اضافه کنید که row cap، timeout و replica کافی نباشند.
پیادهسازی از طریق MCP
پروتکل زمینهٔ مدل (MCP) محیطی طبیعی برای این حفاظهاست. یک سرور MCP بهمثابه یک کارگزار (Broker) عمل میکند؛ کلاینت AI درخواست را میفرستد و سرور — نه مدل — تصمیم میگیرد چه چیزی در واقعیت اجرا شود. این دقیقاً جای درستی برای اعمال دسترسی SELECT-only، محدودیتهای ردیف بیرونی و statement timeoutها است تا قوانین یکسانی صرفنظر از ابزار AI مورد استفاده اعمال شوند.
شما میتوانید این سیستم را خودتان بسازید یا از یک سرور MCP مدیریتشده استفاده کنید. برای مثال، سرور Draxlr بهصورت پیشفرض فقط خواندنی (فقط SELECT) است و بین AI و دیتابیس شما قرار میگیرد تا شما بهجای پیادهسازی دستی، از پیشفرضهای ایمن بهرهمند شوید. نکته کلیدی این است که اجرا (Enforcement) در لایهی کارگزار باشد، جایی که مدل نمیتواند با مهندسی پرامپت، قوانین را دور بزند.
اشتباهات رایج و نکات ظریف
هنگام ایمنسازی دسترسی AI به دیتابیس، از این تلههای رایج دوری کنید:
- تصور اینکه Read-only یعنی ایمنی: این فقط به معنای ایمنی در برابر تغییرات (Writes) است. اتمام منابع یک مشکل جداگانه است که نیاز به راهکارهای جداگانه دارد.
- تنظیم Timeoutهای خیلی بالا: یک تایماوت ۱۰ دقیقهای برای یک دستیار تعاملی عملاً هدف این کار را نابود میکند. اگر پرسوجویی واقعاً به زمان بیشتری نیاز دارد، باید بهصورت آگاهانه اجرا شود، نه از طریق مسیر پیشفرض AI.
- فراموش کردن Timeout روی Replica: رپلیکاها به
statement_timeoutمخصوص به خود نیاز دارند. این تنظیم بهطور خودکار از Primary منتقل نمیشود و یک پرسوجوی runaway روی یک رپلیکای بدون محدودیت، همچنان یک پرسوجوی تخریبگر است. - اتکا به خودِ AI برای افزودن LIMIT: مدلها اغلب این کار را میکنند، اما گاهی فراموش میکنند. حفاظهایی که شما اعمال میکنید، مواردی هستند که میتوانید روی آنها حساب کنید؛ حفاظهایی که امیدوارید مدل به یاد بیاورد، در واقع حفاظ نیستند.
- نبود سقف برای اتصالات: بسیاری از تیمها مورد تکپرسوجو را بهینه میکنند اما فراموش میکنند که همزمانی (Concurrency) میتواند بهراحتی کل سیستم را پایین بیاورد.
جمعبندی و نکات کلیدی
دسترسی Read-only کفِ ایمنی است، نه سقف آن. پرسوجوهایی که به شما آسیب میزنند، نوشتنهای مخرب نخواهند بود، بلکه SELECTهای معتبر و خوشنیتی خواهند بود که بیش از حد دادهها را اسکن میکنند. برای محافظت از سیستم خود:
۱. هر مجموعه نتیجه را با یک LIMIT بیرونی محدود کنید.
۲. یک statement_timeout تنظیم کنید تا پرسوجوهای runaway بهسرعت متوقف شوند.
۳. یک CONNECTION LIMIT روی نقش کاربر اعمال کنید.
۴. هرگاه هزینه عملیاتی آن توجیهپذیر بود، AI را به یک Read Replica متصل کنید.
این موارد را در یک کارگزار (Broker) یا لایهی اتصال اعمال کنید، نه در پرامپت، تا صرفنظر از آنچه مدل مینویسد، پابرجا بمانند. این تغییر رویکرد، تمرکز را از «AI اجازه دارد چه کاری انجام دهد» به «AI اجازه دارد چه مقدار از منابع را مصرف کند» تغییر میدهد.
نوبت شماست: شما چگونه از دیتابیس خود در برابر پرسوجوهای تولید شده توسط AI محافظت میکنید؟ از Read Replica استفاده میکنید، تایماوتهای سخت میگذارید، یا پرسوجوها را بازرسی میکنید؟ آیا تا به حال پیش آمده که یک دستیار AI پرسوجویی بنویسد که شما را غافلگیر کند؟ تجربیات خود را در کامنتها بنویسید؛ داستانهای واقعی معمولاً مفیدترین بخش یادگیری هستند.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو