آموزش‌های کلادفلر به‌زودی در این بخش قرار داده می‌شود.

دسته: لینوکس

  • کامپایلر خودمیزبان یا Self Hosting، وقتی کامپایلر با زبان خودش نوشته می‌شود

    شاید تا حالا این جمله رو شنیده باشید: «کامپایلر زبان اکس با خود زبان اکس نوشته شده». اولین باری که من این رو شنیدم، با خودم گفتم این که غیر ممکنه. مثل این میمونه که بگی یه نفر قبل از اینکه به دنیا بیاد، خودش رو به دنیا آورده. یا مثل همون معمای معروف مرغ و تخم‌مرغه. چطور میشه یه ابزار، خودش رو بسازه؟ این سوالیه که امروز میخوایم با هم به جوابش برسیم. قراره وارد دنیای «خودمیزبانی» یا «سلف هاستینگ» بشیم و ببینیم این ایده چطور کار میکنه، چرا اینقدر مهمه و اصلا چه ارزشی داره.

    این موضوع فقط یه بحث تئوری نیست. درک کردنش به شما یه دید عمیق‌تر نسبت به نحوه ساخته شدن ابزارهایی که هر روز باهاشون کار می‌کنید میده؛ از سیستم‌عاملتون گرفته تا زبان‌های برنامه‌نویسی که دوست دارید.

    خودمیزبانی یعنی چی دقیقا؟

    وقتی میگیم یه برنامه خودمیزبانه، یعنی اون برنامه با استفاده از زبانی نوشته شده که خودش قراره پردازشش کنه. مثلا یه کامپایلر خودمیزبان، کامپایلریه که سورس کدش به همون زبانی نوشته شده که برای کامپایل کردنش طراحی شده.

    این ایده برای خیلی از زبان‌های برنامه‌نویسی مثل Go یا C# یه هدف مهمه. کامپایلرهای این زبان‌ها در نهایت با خود همون زبان‌ها نوشته شدن. اما از طرف دیگه، زبان‌هایی مثل پایتون یا جاوا اسکریپت خودمیزبان نیستن. مثلا خود پایتون با زبان C نوشته شده و این موضوع هیچ مشکلی هم برای جامعه پایتون یا C ایجاد نکرده.

    این مفهوم فقط به کامپایلرها محدود نمیشه. خیلی از نرم‌افزارهای دیگه هم خودمیزبان هستن:

    • سیستم‌عامل‌ها: یه سیستم‌عامل وقتی خودمیزبانه که ابزارهای لازم برای ساختن نسخه‌های جدیدش، روی خود همون سیستم‌عامل اجرا بشن. مثلا شما میتونید نسخه جدید ویندوز رو روی یه کامپیوتر که در حال حاضر ویندوز روش نصبه، بسازید و کامپایل کنید.
    • برنامه‌های دیگه: کرنل‌ها (هسته سیستم‌عامل)، اسمبلرها (برنامه‌هایی که کد اسمبلی رو به کد ماشین تبدیل میکنن)، مفسرهای خط فرمان (مثل ترمینال) و حتی نرم‌افزارهای کنترل نسخه (مثل گیت) هم معمولا خودمیزبان هستن.

    حالا این سوال پیش میاد: آیا خودمیزبانی یه جور نشونه بلوغ برای یه زبانه؟ یا فقط یه کار اضافیه که از اهداف اصلی منحرفمون میکنه؟ برای جواب دادن به این سوال، اول باید بزرگترین چالش این مسیر رو بشناسیم.

    معمای مرغ و تخم‌مرغ: مشکل بوت‌استرپینگ

    خب، رسیدیم به همون مشکل اصلی. اگه کامپایلر زبان اکس قراره با خود زبان اکس نوشته بشه، پس اولین نسخه این کامپایلر رو کی یا چی باید کامپایل کنه؟ ما که هنوز کامپایلری برای زبان اکس نداریم! این دقیقا همون مشکل «بوت‌استرپینگ» یا به قول معروف، معمای مرغ و تخم‌مرغه.

    برای اینکه یه سیستم بتونه به مرحله خودمیزبانی برسه، اولش به یه سیستم دیگه نیاز داره تا توسعه پیدا کنه. فرض کنید دارید برای یه کامپیوتر یا سیستم‌عامل کاملا جدید برنامه مینویسید. شما هم به یه سیستم برای اجرای نرم‌افزارهای توسعه نیاز دارید و هم به خود اون نرم‌افزارها برای نوشتن و ساختن سیستم‌عامل. این یه دور باطله.

    راه حل این مشکل استفاده از چیزی به اسم «کراس کامپایلر» (Cross Compiler) یا «کراس اسمبلر» هست. کراس کامپایلر یه کامپایلره که روی یه پلتفرم (مثلا ویندوز) اجرا میشه، اما کدی که تولید میکنه برای یه پلتفرم دیگه (مثلا یه کنسول بازی یا یه برد الکترونیکی) قابل اجراست. اینطوری میشه برای یه ماشینی که هنوز کامپایلر خودمیزبان نداره، نرم‌افزار ساخت.

    وقتی نرم‌افزار اولیه ساخته شد، میشه اون رو با استفاده از ابزارهایی مثل فلش مموری، دیسک یا کابل JTAG به سیستم مقصد منتقل کرد. این روش دقیقا همون کاریه که برای ساختن نرم‌افزار برای کنسول‌های بازی یا گوشی‌های موبایل انجام میدن؛ چون این دستگاه‌ها معمولا ابزارهای توسعه رو روی خودشون ندارن.

    وقتی سیستم به اندازه کافی بالغ شد و تونست کد خودش رو کامپایل کنه، دیگه نیازی به اون سیستم اولیه نیست و وابستگی از بین میره. در این نقطه میگیم اون سیستم «خودمیزبان» شده.

    فرآیند بوت‌استرپینگ برای یک کامپایلر

    این فرآیند برای کامپایلرها هم دقیقا به همین شکله. چون کامپایلرهای خودمیزبان هم با همون مشکل بوت‌استرپینگ درگیرن، اولین نسخه از کامپایلر یه زبان جدید باید با یه زبان موجود نوشته بشه. توسعه‌دهنده‌ها ممکنه از اسمبلی، C/C++ یا حتی زبان‌های اسکریپتی مثل پایتون یا Lua برای ساختن نسخه اولیه استفاده کنن.

    وقتی زبان جدید به اندازه کافی کامل و قدرتمند شد، توسعه کامپایلر به خود اون زبان منتقل میشه. از اون به بعد، کامپایلر میتونه خودش رو بسازه و کامپایل کنه.

    یه مثال خیلی جالب، داستان ساخت کامپایلر زبان اسکالا (Scala) هست. نسخه اولیه کامپایلر اسکالا با جاوا نوشته شده بود. اما نسخه‌های بعدی (مثلا نسخه ۲) خودمیزبان شدن، یعنی با خود اسکالا نوشته شدن. یا مثلا زبان کافی‌اسکریپت (CoffeeScript) که در ابتدا کامپایلرش با زبان روبی (Ruby) نوشته شده بود.

    پس اگه یه نفر به شما گفت «کامپایلر کافی‌اسکریپت با کافی‌اسکریپت نوشته شده»، این جمله یه کم گمراه‌کننده‌ست. جمله دقیق‌تر اینه:

    • نسخه ۶ کامپایلر کافی‌اسکریپت با نسخه ۵ نوشته شده، نسخه ۷ با نسخه ۶، نسخه ۸ با نسخه ۷ و همینطور الی آخر.

    این فرآیند مثل بالا رفتن از یه نردبونه. شما با استفاده از نسخه فعلی، یه نسخه جدید و بهتر از نردبون رو میسازید، بعد روی نردبون جدید میرید و نردبون قبلی رو دور میندازید. این چرخه همینطور ادامه پیدا میکنه.

    یه مثال عملی (و یه کم خنده‌دار): زبان برنامه‌نویسی گلابی!

    برای اینکه این فرآیند رو بهتر بفهمیم، بیاید با هم یه زبان برنامه‌نویسی خیالی و مسخره به اسم «گلابی» (Gluby) بسازیم و کامپایلرش رو خودمیزبان کنیم. این مثال رو رابرت هیتون برای آموزش همین مفهوم ساخته.

    قوانین زبان گلابی خیلی ساده‌ست:

    • این زبان از نظر سینتکس دقیقا مثل زبان روبی (Ruby) هست.
    • فقط یه فرق کوچیک داره: به جای علامت مساوی (=)، باید از کلمه انگلیسی EQUALS استفاده کنید.
    • شما حق ندارید از کلمه EQUALS در هیچ جای دیگه‌ای از برنامه‌تون استفاده کنید، وگرنه همه چیز خراب میشه!

    حالا میخوایم برای این زبان یه کامپایلر خودمیزبان بنویسیم.

    مرحله اول: نسخه صفر کامپایلر گلابی (نوشته شده با پایتون)

    همونطور که گفتیم، برای شروع به یه زبان دیگه نیاز داریم. ما اینجا از پایتون استفاده می‌کنیم. پس نسخه صفر (v0) کامپایلر گلابی ما یه برنامه پایتونیه. کار این برنامه خیلی ساده‌ست:

    • یه فایل با پسوند .gl (فایل سورس گلابی) رو به عنوان ورودی میگیره.
    • تمام کلمات EQUALS رو پیدا میکنه و اونها رو با علامت = جایگزین میکنه.
    • خروجی رو توی یه فایل جدید با پسوند .blc ذخیره میکنه.

    این فایل خروجی در واقع یه کد روبی معتبره که میشه با مفسر روبی اجراش کرد. کد پایتونش چیزی شبیه این میشه:

    from functools import reduce
    import sys
    if __name__ == '__main__':
        input_filename = sys.argv[1]
        input_filename_chunks = input_filename.split('.')
        output_filename = "%s.blc" % "".join(input_filename_chunks[0:-1])
        # "=" is 61 in ASCII
        swaps = [(chr(61), 'EQUALS')]
        with open(input_filename) as input_f:
            with open(output_filename, 'w+') as output_f:
                # Read all the lines in the source code
                for l in input_f.readlines():
                    # Make the swaps
                    new_l = reduce(
                        (lambda running_l, sw: running_l.replace(swap[1], swap[0])),
                        swaps,
                        l
                    )
                    # Write out a line to the compiled file
                    output_f.write(new_l)

    خب، ما الان یه کامپایلر اولیه داریم. این کامپایلر میتونه کد گلابی رو به کد روبی تبدیل کنه. حالا وقت مرحله بعده.

    مرحله دوم: نسخه یک کامپایلر گلابی (نوشته شده با خود گلابی!)

    حالا که زبان گلابی به اندازه کافی قدرتمند شده (چون تمام قدرت روبی رو به ارث برده)، میتونیم ازش برای بازنویسی خود کامپایلر استفاده کنیم. نسخه یک (v1) کامپایلر گلابی، با سینتکس خود گلابی نوشته میشه. یعنی به جای = از EQUALS استفاده می‌کنیم.

    input_filename EQUALS ARGV[1]
    input_filename_chunks EQUALS input_filename.split('.')
    output_filename EQUALS "#{input_filename_chunks[0...-1].join('')}.blc"
    # Use ASCII 69 instead of "E" to make sure we don’t replace the string
    #"EQUALS" when compiling this program.
    swaps EQUALS [[61.chr, 69.chr + 'QUALS']]
    File.open(input_filename, "r") do |input_f|
        File.open(output_filename, "w+") do |output_f|
            input_f.each_line do |l|
                new_l EQUALS swaps.reduce(l) do |memo, swap|
                    memo.gsub(swap[1], swap[0])
                end
            end
            output_f.puts(new_l)
        end
    end

    حالا اون لحظه جادویی فرا میرسه. ما این کد (که سورس نسخه ۱ کامپایلره) رو به کامپایلر نسخه صفر (همون برنامه پایتونی) میدیم. برنامه پایتونی تمام EQUALS ها رو با = عوض میکنه و یه فایل خروجی به ما میده. این فایل خروجی، یه برنامه روبی کاملا قابل اجراست.

    و این برنامه قابل اجرا چیه؟ این خود کامپایلر نسخه یک گلابیه

    از این لحظه به بعد، ما دیگه هیچ نیازی به اون کد پایتونی اولیه نداریم. میتونیم برای همیشه حذفش کنیم. چرا؟ چون الان یه کامپایلر جدید داریم که هم سورس کدش به زبان گلابیه و هم نسخه قابل اجراش موجوده. برای کامپایل کردن نسخه‌های بعدی کامپایلر (مثلا نسخه ۲)، از همین نسخه ۱ استفاده می‌کنیم. زبان گلابی رسما خودمیزبان شد!

    سازنده این زبان خیالی در ادامه به شوخی میگه که داره روی نسخه ۲ کار میکنه و میخواد به جای کلمه end از عبارت ALL_HAIL_ROBERT استفاده کنه.

    چرا این همه دردسر؟ مزایای خودمیزبانی چیه؟

    خب، حالا که فهمیدیم خودمیزبانی چیه و چطور کار میکنه، سوال اصلی اینه: چرا یه تیم باید این همه هزینه و ریسک رو قبول کنه و کامپایلرش رو خودمیزبان کنه؟ این کار چه فایده‌ای داره؟

    شرکت مایکروسافت یه تجربه بزرگ در این زمینه داره. کامپایلرهای زبان سی‌شارپ از نسخه ۱.۰ تا ۶.۰ با زبان C++ نوشته شده بودن. اما برای نسخه ۶.۰، تیم رو به دو بخش تقسیم کردن: یه تیم به توسعه ویژگی‌های جدید روی همون کدبیس C++ ادامه داد و تیم دوم وظیفه داشت کل کامپایلر رو از اول با خود سی‌شارپ بازنویسی کنه. این یه تصمیم فوق‌العاده پرهزینه و پرریسک برای یکی از مهمترین محصولات مایکروسافت بود. پس حتما دلایل خیلی خوبی براش داشتن. بیاید این دلایل رو بررسی کنیم:

    ۱. بهترین تست ممکن برای زبان (Dogfooding)

    این یکی از مهمترین مزایای خودمیزبانیه که تقریبا همه بهش اشاره میکنن. اصطلاح «Dogfooding» یعنی «غذای سگ خودت رو بخوری». یعنی از محصولی که خودت تولید میکنی، خودت هم استفاده کنی.

    • یه تست واقعی و پیچیده: یه کامپایلر برنامه خیلی پیچیده‌ایه. اگه یه زبان اونقدر قدرتمند باشه که بشه باهاش یه کامپایلر نوشت، این نشون میده که احتمالا برای نوشتن طیف وسیعی از برنامه‌های پیچیده دیگه هم مناسبه. این یه جور «آزمون تورنسل» برای زبان محسوب میشه.
    • پیدا کردن سریع باگ‌ها و مشکلات عملکردی: وقتی توسعه‌دهنده‌های کامپایلر هر روز از کامپایلر خودشون برای کامپایل کردن خود کامپایلر استفاده میکنن، خیلی سریع با باگ‌ها، مشکلات عملکردی و نقاط ضعف زبان روبرو میشن. تیم سی‌شارپ میخواست کامپایلر جدیدشون بتونه برنامه‌های چند میلیون خطی رو به راحتی مدیریت کنه. داشتن خود کامپایلر به عنوان یه کیس تستی بزرگ، بهشون خیلی کمک کرد تا مشکلات رو سریع پیدا و حل کنن.
    • بررسی جامع سازگاری: کامپایلر باید بتونه کد آبجکت خودش رو بازتولید کنه. این یه بررسی سازگاری خیلی کامله که نشون میده کامپایلر کارش رو درست انجام میده.

    یه نویسنده در این مورد از تجربه شخصی خودش میگه. اون مجبور بوده با یه کامپایلر معروف که خودمیزبان نیست کار کنه و میگه تقریبا هر دو روز یک بار با خطای segfault (یه نوع کرش کردن برنامه) مواجه میشده. اون با خودش فکر میکنه که اگه طراحان اون کامپایلر مجبور بودن هر روز ازش استفاده کنن، حتما این مشکلات خیلی زودتر حل میشد.

    ۲. راحتی و بهره‌وری تیم توسعه

    • تخصص در یک زبان: وقتی کامپایلر خودمیزبانه، توسعه‌دهنده‌ها و کسایی که باگ‌ها رو گزارش میدن، فقط کافیه به همون زبان مسلط باشن. این کار باعث میشه تعداد زبان‌هایی که تیم باید بدونه کمتر بشه. در حالت عادی، تیم باید زبان ماشین (یا اسمبلی)، زبان هدف (که کامپایلر براش ساخته میشه) و زبان سورس کامپایلر رو بلد باشه. اما در حالت خودمیزبان، این تعداد به دو زبان کاهش پیدا میکنه.
    • استفاده از ویژگی‌های سطح بالا: توسعه‌دهنده‌ها میتونن از ویژگی‌های راحت‌تر و سطح بالاتر زبان خودشون برای توسعه کامپایلر استفاده کنن. تیم سی‌شارپ همگی برنامه‌نویس‌های متخصص سی‌شارپ بودن و شکی نبود که میتونن با این زبان خیلی بهره‌وری بالایی داشته باشن. سی‌شارپ هم به طور خاص طوری طراحی شده بود که یه جایگزین امن‌تر و پربازده‌تر برای کدبیس‌های بزرگ C++ باشه.

    ۳. بهبود خودکار کامپایلر

    این یکی از جالب‌ترین مزایاست. هر بهبودی که در بخش بک‌اند (Backend) کامپایلر ایجاد میشه، نه تنها روی برنامه‌هایی که کاربران مینویسن تاثیر مثبت داره، بلکه روی خود کامپایلر هم تاثیر میذاره. یعنی وقتی شما کامپایلر رو طوری بهینه میکنید که کد سریع‌تری تولید کنه، دفعه بعدی که خود کامپایلر رو با خودش کامپایل میکنید، نسخه جدید کامپایلر هم سریع‌تر اجرا میشه! این یه چرخه بهبود مستمر ایجاد میکنه.

    ۴. تاثیر در طراحی خود زبان

    استفاده از زبان برای ساختن کامپایلر خودش، میتونه روی طراحی ویژگی‌های جدید زبان هم تاثیر بذاره. البته تیم سی‌شارپ مراقب بود که در دام طراحی زبان فقط برای نیازهای تیم کامپایلر نیفته، اما در طول مسیر به چند تا مشکل برخوردن که باعث شد ویژگی‌های جدیدی به زبان اضافه بشه.

    برای مثال، آندرس هایلزبرگ (طراح اصلی سی‌شارپ) همیشه با اضافه کردن «فیلترهای استثنا» (exception filters) مخالف بود، در حالی که این ویژگی در زبان ویژوال بیسیک وجود داشت. اما تیم کامپایلر در حین کار چند تا مورد استفاده خیلی خوب براش پیدا کردن و تونستن آندرس رو قانع کنن که این ویژگی به سی‌شارپ هم اضافه بشه.

    ۵. مشارکت بیشتر جامعه

    اگه کامپایلر با یه زبان شناخته‌شده و محبوب نوشته شده باشه، احتمال اینکه جامعه برنامه‌نویس‌ها در توسعه‌ش مشارکت کنن خیلی بیشتره. زبان سی‌شارپ میلیون‌ها کاربر داشت. وقتی کامپایلر جدیدش به اسم «رازلین» (Roslyn) به صورت اوپن سورس منتشر شد، حمایت و مشارکت جامعه در ده سال گذشته برای این پروژه خیلی مفید بوده.

    ۶. ساخت اکوسیستم ابزارها

    یکی از اهداف اصلی تیم سی‌شارپ از بازنویسی کامپایلر، فقط خودمیزبانی نبود. اونها میخواستن تحلیل‌گرهای لغوی، سینتکسی و معنایی کامپایلر رو به صورت یه سری سرویس در بیارن که هر کسی بتونه ازشون استفاده کنه، نه فقط تیم IDE. اونها میدونستن که داخل خود مایکروسافت نیاز زیادی به یه کتابخونه از سرویس‌های کامپایلر وجود داره.

    اونها پیش‌بینی کردن که یه اکوسیستم بزرگ از افزونه‌های تحلیل کد برای IDE ها به وجود میاد. و زبان طبیعی برای نوشتن این افزونه‌ها چی بود؟ خود سی‌شارپ. پس منطقی بود که خود «کامپایلر به عنوان سرویس» هم با سی‌شارپ نوشته بشه.

    نگاهی به تاریخ: اولین‌ها و مهم‌ترین‌ها

    ایده خودمیزبانی یه ایده جدیده نیست و تاریخچه جالبی داره. بیاید چند تا از موارد مهم رو با هم مرور کنیم.

    • Lisp (۱۹۶۲): اولین کامپایلر خودمیزبان (به جز اسمبلرها) برای زبان لیسپ توسط هارت و لوین در MIT در سال ۱۹۶۲ نوشته شد. داستانش خیلی جالبه. اونها یه کامپایلر لیسپ رو با خود لیسپ نوشتن و اون رو داخل یه مفسر لیسپ که از قبل وجود داشت تست کردن. اونها اینقدر کامپایلر رو بهبود دادن تا به جایی رسید که تونست سورس کد خودش رو کامپایل کنه. در اون لحظه، کامپایلر رسما خودمیزبان شد. این تکنیک وقتی عملیه که از قبل یه مفسر برای اون زبان وجود داشته باشه.
    • Unix و زبان C: کن تامپسون توسعه یونیکس رو در سال ۱۹۶۸ شروع کرد. اون برنامه‌ها رو روی یه کامپیوتر بزرگ GE-635 مینوشت و کامپایل میکرد، بعد اونها رو به یه کامپیوتر کوچیکتر به اسم PDP-7 منتقل میکرد تا تستشون کنه. بعد از اینکه هسته اولیه یونیکس، مفسر فرمان، ویرایشگر، اسمبلر و چند تا ابزار دیگه کامل شدن، سیستم‌عامل یونیکس خودمیزبان شد. یعنی از اون به بعد میشد برنامه‌ها رو روی خود همون PDP-7 نوشت، کامپایل کرد و تست کرد.
    • TMG: یه داستان فوق‌العاده دیگه مربوط به داگلاس مک‌ایلروی هست. اون یه کامپایلر-کامپایلر (برنامه‌ای که کامپایلر میسازه) به اسم TMG رو روی کاغذ با خود سینتکس TMG نوشت. بعدش به قول خودش «تصمیم گرفت تیکه کاغذش رو به تیکه کاغذش بده». یعنی خودش شخصا و به صورت دستی، فرآیند کامپایل رو روی کاغذ انجام داد و یه خروجی اسمبلی تولید کرد. بعد اون کد اسمبلی رو تایپ کرد و روی PDP-7 کن تامپسون اسمبل کرد و اجرا کرد!
    • پروژه گنو (GNU): توسعه سیستم گنو به شدت به GCC (مجموعه کامپایلرهای گنو) و گنو ایمکس (یه ویرایشگر محبوب) وابسته است. این ابزارها امکان توسعه پایدار و مستقل نرم‌افزارهای آزاد رو برای پروژه گنو فراهم کردن.

    امروزه زبان‌های خیلی زیادی کامپایلرهای خودمیزبان دارن. این لیست فقط بخشی از اونهاست:

    AdaCC++C#
    GoHaskellJavaKotlin
    LispPython (PyPy)RustScala
    SwiftTypeScriptZigو خیلی‌های دیگه…

    آیا خودمیزبانی همیشه بهترین راهه؟

    با تمام مزایایی که گفتیم، خودمیزبانی یه سری چالش هم داره. همونطور که توسعه‌دهنده زبان Leaf اشاره کرد، «دردسر بوت‌استرپینگ» یه مشکل واقعیه و میتونه تمرکز تیم رو از اهداف اصلی زبان، مثل اضافه کردن ویژگی‌های جدید، منحرف کنه.

    یه سوال جالب دیگه هم در این مورد مطرح میشه: آیا زبانی که برای کامپایل شدن به یه کتابخونه بزرگ مثل LLVM وابسته است، واقعا خودمیزبانه؟

    بعضی‌ها معتقدن که اگه کامپایلر شما نتونه سورس کد LLVM رو هم کامپایل کنه، پس کاملا خودمیزبان نیست. شاید خودمیزبانی واقعی زمانی اتفاق بیفته که زبان شما بک‌اند (Backend) خودش رو هم داشته باشه، حتی اگه خیلی ضعیف باشه. در این صورت، LLVM فقط یه هدف (Target) دیگه در کنار بقیه هدف‌ها محسوب میشه. این بحث نشون میده که مفهوم خودمیزبانی میتونه لایه‌های مختلفی داشته باشه.

    از کجا شروع کنیم؟ راهنمای عملی برای کنجکاوها

    اگه به این موضوع علاقه‌مند شدید و دوست دارید بدونید چطور میشه یه کامپایلر رو خودمیزبان کرد، اینجا یه نقشه راه کلی بر اساس تجربیات دیگران وجود داره. فرآیند برای زبان‌های مفسری و کامپایلری یه کم متفاوته.

    برای زبان‌های مفسری/دینامیک:

    1. یه رانتایم (Runtime) اولیه با یه زبان موجود مثل C، راست یا گو بنویسید.
    2. این رانتایم رو گسترش بدید تا بتونه با فایل سیستم کار کنه و فرمت‌های اجرایی نیتیو رو بفهمه.
    3. حالا دوباره همون رانتایم رو این بار با استفاده از زبان خودتون بازنویسی کنید.
    4. رانتایمی که تازه نوشتید رو با استفاده از رانتایم اولیه اجرا کنید و اون رو به یه فایل اجرایی خروجی بگیرید.
    5. تبریک میگم! مفسر یا REPL شما خودمیزبان شد!

    یه مثال خوب در این زمینه، زبان اینکو (Inko) هست. کامپایلر فعلیش با روبی نوشته شده و سازنده‌ش داره تلاش میکنه اون رو خودمیزبان کنه. در اینکو، عملیات‌های سطح پایین (مثل باز کردن فایل) به صورت دستورات ماشین مجازی (VM instructions) پیاده‌سازی شدن. برای مثال، کدی که پروسس در حال اجرا رو برمیگردونه این شکلیه:

    def current -> Process {
      _INKOC.process_current
    }

    اینجا _INKOC.process_current یه دستور اولیه‌ست که کامپایلر اون رو به یه دستور ماشین مجازی تبدیل میکنه. این روش به سازنده اینکو اجازه میده بدون تغییر سینتکس زبان، این قابلیت‌های سطح پایین رو اضافه کنه.

    برای زبان‌های کامپایلری (با استفاده از LLVM):

    1. یه فرانت‌اند (Frontend) بنویسید که زبان شما رو بگیره و اون رو به یه نمایش میانی (Intermediate Representation یا IR) برای یه بک‌اند مثل LLVM یا GCC تبدیل کنه.
    2. یه بک‌اند با زبان خودتون بنویسید که این نمایش میانی رو بگیره و به اسمبلی یا بایت‌کد تبدیل کنه. این بک‌اند جدید رو با استفاده از فرانت‌اند اولیه کامپایل کنید.
    3. اگه بک‌اند جدید شما از نمایش میانی متفاوتی استفاده میکنه، فرانت‌اند رو طوری تغییر بدید که باهاش سازگار باشه.
    4. حالا فرانت‌اند رو هم با زبان خودتون بازنویسی کنید و اون رو با استفاده از فرانت‌اند قدیمی و بک‌اند جدید کامپایل کنید.
    5. الان شما یه تولچین (toolchain) کاملا نیتیو دارید که با زبان خودتون نوشته شده!

    یک پروژه واقعی: استارفورث (Starforth)

    برای اینکه ببینیم این ایده‌ها در عمل چطور پیاده میشن، بیاید نگاهی به پروژه استارفورث بندازیم. این پروژه توسط یه برنامه‌نویس شروع شده که همیشه به زبان فورث (Forth) علاقه داشته. فورث یه زبان خیلی خاصه که فقط با یه استک کار میکنه و از نوشتار لهستانی معکوس استفاده میکنه. یعنی به جای 2 + 2 مینویسید 2 2 +.

    نقطه عطف برای این برنامه‌نویس زمانی بود که فهمید در زبان فورث، وقتی اسم یه متغیر (مثلا foo) رو مینویسید، آدرس اون متغیر روی استک قرار میگیره. بعد با یه عملگر به اسم @ (fetch) میشه اون آدرس رو از روی استک خوند و به مقدار داخلش دسترسی پیدا کرد. اونجا بود که متوجه شد: فورث اشاره‌گر (pointer) داره!

    این کشف باعث شد که تصمیم بگیره یه کامپایلر جدید به اسم استارفورث بنویسه و این اهداف رو برای خودش مشخص کرد:

    • تولید کد ماشین واقعی: برخلاف پروژه‌های قبلیش که برای ماشین‌های مجازی بودن، این بار میخواست کد ماشین واقعی تولید کنه.
    • خودمیزبانی: کامپایلر باید بتونه سورس کد خودش رو کامپایل کنه.
    • کامپایلر پیش از اجرا (Ahead-of-Time): برخلاف اکثر پیاده‌سازی‌های فورث که مفسری هستن، این کامپایلر باید کارش رو انجام بده و از مسیر خارج بشه.
    • بوت‌استرپ فقط با یک اسمبلر: فایل باینری اولیه باید تا حد ممکن کوچیک باشه و فقط با یه اسمبلر ساده قابل ساخت باشه.

    تصمیمات فنی پروژه هم اینها بودن:

    • محیط هدف: لینوکس.
    • معماری: x86 ۳۲ بیتی (چون کدش کوچیکتره و حس و حال روزهای قدیم رو داره!).
    • خروجی: فایل‌های باینری ELF کاملا مستقل، بدون هیچ وابستگی به کتابخانه‌های اشتراکی مثل libc.

    این پروژه نشون میده که چطور یه علاقه شخصی به یه زبان خاص میتونه به یه پروژه چالش‌برانگیز و آموزنده برای ساخت یه کامپایلر خودمیزبان تبدیل بشه.

    پرسش و پاسخ

    سوال ۱: پس خلاصه، یه کامپایلر خودمیزبان یعنی با همون زبانی نوشته شده که خودش کامپایل میکنه. این چطور ممکنه؟

    جواب: این کار از طریق یه فرآیندی به اسم «بوت‌استرپینگ» انجام میشه. شما نسخه اولیه کامپایلر (نسخه صفر) رو با یه زبان دیگه که از قبل وجود داره (مثلا پایتون یا C++) مینویسید. بعد با استفاده از این کامپایلر اولیه، نسخه جدید کامپایلر (نسخه یک) رو که با زبان خودش نوشته شده، کامپایل میکنید. وقتی نسخه یک ساخته شد، دیگه نیازی به نسخه صفر ندارید و از اون به بعد کامپایلر میتونه خودش رو کامپایل و به‌روزرسانی کنه.

    سوال ۲: اصلی‌ترین فایده این همه زحمت چیه؟

    جواب: مهمترین فایده‌ش «Dogfooding» هست. یعنی شما از محصول خودتون استفاده میکنید. این کار بهترین تست ممکن برای زبان شماست. چون کامپایلر یه برنامه خیلی پیچیده‌ست، اگه زبان شما بتونه از پس نوشتن خودش بربیاد، یعنی به بلوغ و قدرت کافی رسیده. این فرآیند به پیدا کردن سریع باگ‌ها، مشکلات عملکردی و حتی بهبود طراحی خود زبان کمک میکنه.

    سوال ۳: آیا همه زبان‌های بزرگ مثل پایتون خودمیزبان هستن؟

    جواب: نه لزوما. مثلا مفسر اصلی پایتون (CPython) با زبان C نوشته شده. کامپایلر جاوا اسکریپت هم همینطور. خودمیزبان نبودن یه زبان به هیچ وجه نشونه ضعف اون نیست و چیزی از ارزش‌های اون زبان یا زبانی که باهاش نوشته شده کم نمیکنه. این فقط یه انتخاب در مسیر توسعه‌ست.

    سوال ۴: اولین کامپایلر خودمیزبان برای چه زبانی ساخته شد؟

    جواب: اولین کامپایلر خودمیزبان (به جز اسمبلرها که از ابتدا خودمیزبان بودن) برای زبان Lisp در سال ۱۹۶۲ در دانشگاه MIT توسط هارت و لوین ساخته شد. اونها کامپایلر لیسپ رو داخل یه مفسر لیسپ توسعه دادن تا به نقطه‌ای رسید که تونست خودش رو کامپایل کنه.

    منابع

    • [2] What are the benefits to self-hosting compilers? – Programming Language Design and Implementation Stack Exchange
    • [4] Why would we want a self-hosting compiler? – Computer Science Stack Exchange
    • [6] Why are self-hosting compilers considered a rite of passage for new languages? – Software Engineering Stack Exchange
    • [8] elektito | Starforth: A Minimal Self-Hosting Compiler
    • [1] Self Hosting? : r/ProgrammingLanguages
    • [3] Self-hosting (compilers) – Wikipedia
    • [5] What is a self-hosting compiler? | Robert Heaton
    • [7] What is self-hosting, and is there value in it? – DEV Community
  • پست‌گرس‌کیوال PostgreSQL چیست؟ راهنمای استفاده اولیه

    طبق گفته سازنده‌هاش، پست‌گرس‌کیوال یک سیستم مدیریت پایگاه داده شی‌گرا-رابطه‌ای و متن‌بازه. میدونم، میدونم، این جمله خودش کلی کلمه قلمبه سلمبه داره. بیاین تیکه‌تیکه‌ش کنیم:

    • پایگاه داده (Database): فکر کنین یه دفترچه یادداشت خیلی خیلی بزرگ و هوشمند دارین که میتونین اطلاعات رو خیلی مرتب و منظم توش ذخیره کنین. مثلا اطلاعات دانشجوهای یه دانشگاه، محصولات یه فروشگاه آنلاین، یا لیست آهنگ‌های یه اپلیکیشن موسیقی. به این دفترچه هوشمند میگن پایگاه داده. کارش اینه که اطلاعات رو نگه داره، بهمون اجازه بده توش جستجو کنیم، اطلاعات جدید اضافه کنیم یا اطلاعات قبلی رو تغییر بدیم.
    • سیستم مدیریت پایگاه داده (Database System): حالا اون نرم‌افزاری که به ما اجازه میده اون دفترچه هوشمند (پایگاه داده) رو بسازیم و مدیریتش کنیم، میشه سیستم مدیریت پایگاه داده. پست‌گرس‌کیوال دقیقا همین کار رو میکنه. یه جورایی مثل اون برنامه دفترچه یادداشت توی کامپیوتر یا گوشیتونه، ولی هزاران بار قوی‌تر و پیشرفته‌تر.
    • رابطه‌ای (Relational): این کلمه یعنی اطلاعات توی جدول‌های مختلفی ذخیره میشن که به هم ربط دارن. مثلا یه جدول داریم برای دانشجوها، یه جدول دیگه برای درس‌ها. بعد میتونیم بین این دوتا جدول یه رابطه برقرار کنیم تا مشخص بشه هر دانشجویی چه درس‌هایی رو برداشته. اینجوری همه چیز خیلی منظم و دسته‌بندی شده باقی میمونه.
    • شی‌گرا (Object-Relational): این یه ویژگی پیشرفته‌تره. یعنی پست‌گرس‌کیوال فقط به مدل رابطه‌ای محدود نیست و میتونه ساختارهای داده پیچیده‌تری رو هم مدیریت کنه. فعلا خیلی درگیر این قسمتش نشین، همینقدر بدونین که این ویژگی دستش رو برای کارهای پیچیده‌تر باز میذاره.
    • متن‌باز (Open Source): این یعنی کد اصلی برنامه پست‌گرس‌کیوال در دسترس همه هست. هر کسی میتونه اون رو ببینه، تغییر بده و حتی در بهتر شدنش کمک کنه. این باعث میشه یه جامعه بزرگ از متخصص‌ها در سراسر دنیا روی توسعه‌ش کار کنن و همیشه در حال پیشرفت باشه.

    این سیستم بیشتر از ۳۵ ساله که داره به صورت فعال توسعه داده میشه. این زمان طولانی باعث شده که به عنوان یه ابزار خیلی قابل اعتماد، پر از امکانات و با عملکرد خوب شناخته بشه. به خاطر همین متن‌باز بودنش، کلی اطلاعات و راهنمای رسمی برای نصب و استفاده ازش وجود داره. جامعه کاربری خیلی بزرگی هم داره که همیشه آماده کمک کردن هستن و میتونین از طریق اونها با طرز کارش آشنا بشین یا حتی فرصت‌های شغلی پیدا کنین.

    بخش دوم: سرور، کلاینت، اس‌کیوال؛ مفاهیم پایه رو یاد بگیریم

    وقتی برای اولین بار با ابزارهایی مثل پست‌گرس‌کیوال کار میکنین، یه سری کلمه‌ها مثل «سرور» مدام به چشمتون میخوره. یکی از کاربرها توی ردیت دقیقا همین سوال رو پرسیده بود که «این سرورهایی که توی pgAdmin (یه ابزار برای مدیریت پست‌گرس) میبینیم چی هستن؟» این سوال خیلی خوبیه، چون به قلب ماجرا میزنه.

    سرور چیه و چه ربطی به پایگاه داده داره؟

    بیایم با تعریف اصلی شروع کنیم.
    یک سرور (Server) میتونه یه قطعه سخت‌افزاری باشه (مثلا یه کامپیوتر خیلی قوی) یا یه نرم‌افزار که به بقیه برنامه‌ها یا دستگاه‌ها سرویس میده. به اون برنامه‌هایی که سرویس میگیرن میگن کلاینت (Client).

    حالا، سرور پایگاه داده (Database Server) یه سروره که یه برنامه پایگاه داده (مثل پست‌گرس‌کیوال) روش نصبه و داره سرویس‌های مربوط به پایگاه داده رو به بقیه برنامه‌ها ارائه میده.

    تصور کنین شما یه اپلیکیشن روی گوشیتون دارین (مثلا اینستاگرام). این اپلیکیشن کلاینته. وقتی شما میخواین عکس‌های جدید رو ببینین، اپلیکیشن شما یه درخواست به سرورهای اینستاگرام میفرسته. روی اون سرورها، یه سرور پایگاه داده نصبه که اطلاعات عکس‌ها، کامنت‌ها و لایک‌ها رو نگه میداره. سرور پایگاه داده اطلاعات رو پیدا میکنه و برای اپلیکیشن شما میفرسته.

    پس وقتی توی ابزاری مثل pgAdmin یه چیزی به اسم «Servers» میبینین، منظور همون اتصال به یک سرور پایگاه داده هست. شما میتونین از کامپیوتر خودتون به چندین سرور پایگاه داده مختلف وصل بشین. مثلا یکی ممکنه روی کامپیوتر خودتون نصب باشه برای تمرین (که بهش میگن سرور محلی یا Local Server) و یکی دیگه ممکنه یه کامپیوتر اون سر دنیا باشه که اطلاعات واقعی یه سایت روشه (سرور راه دور یا Remote Server).

    گاهی هم ممکنه ببینین کنار اسم سرور یه عدد نوشته شده، مثلا «PostgreSQL 13». این عدد معمولا به نسخه اون نرم‌افزار پست‌گرس‌کیوال که روی سرور نصبه اشاره داره.

    پست‌گرس‌کیوال زبانه یا سرور؟ قصه SQL چیه؟

    اینم یه سوال خیلی رایجه. خیلیا گیج میشن که فرق بین SQL و PostgreSQL چیه.
    بذارین اینطوری بگم:

    • SQL (Structured Query Language): این اسم یک زبانه. یه زبان استاندارد برای حرف زدن با پایگاه داده‌های رابطه‌ای. شما با استفاده از دستورهای این زبان، از پایگاه داده میخواین که یه کاری براتون انجام بده. مثلا «این اطلاعات رو بهم نشون بده» یا «این کاربر جدید رو اضافه کن».
    • PostgreSQL: این اسم یک نرم‌افزاره. یک سیستم مدیریت پایگاه داده. این نرم‌افزار زبان SQL رو میفهمه. شما دستورهای SQL رو بهش میدین و اون براتون اجراشون میکنه.

    پس پست‌گرس‌کیوال هم یک سروره (نرم‌افزاری که سرویس میده) و هم میشه گفت یه جورایی یه «زبانه» چون نسخه مخصوص به خودش از SQL رو پیاده‌سازی کرده.

    یه نکته جالب اینه که شرکت‌های مختلف، نرم‌افزارهای پایگاه داده خودشون رو ساختن. مثلا:

    • Oracle
    • MySQL (که الان مال اوراکله)
    • MariaDB
    • Microsoft SQL Server
    • و البته PostgreSQL

    همه اینها زبان استاندارد SQL رو به عنوان پایه قبول دارن، ولی هر کدوم یه سری دستورها و ویژگی‌های مخصوص به خودشون رو هم اضافه کردن. مثل لهجه‌های مختلف یه زبان میمونه. هسته اصلی یکیه، ولی تو جزئیات تفاوت دارن. اگه بخوایم با نمودار ون تصور کنیم، یه دایره بزرگ هست به اسم SQL که دستورهای اصلی توشه، و بعد دایره‌های کوچیکتری برای هر کدوم از این نرم‌افزارها (PostgreSQL, MySQL, …) وجود داره که بخش زیادی‌شون با هم همپوشانی داره.

    یه نکته دیگه هم اینکه حواستون باشه اسم «SQL Server» که مال مایکروسافته رو با مفهوم کلی «سرور SQL» اشتباه نگیرین. اولی اسم یه محصول خاصه، دومی یه مفهوم کلی.

    دو نوع دستور مهم در SQL

    وقتی با کد SQL سر و کار دارین، خوبه که بدونین دستورهاش معمولا به دو دسته اصلی تقسیم میشن:

    1. DML (Data Manipulation Language): زبان دستکاری داده‌ها. این دستورها کارشون با خود داده‌هاست. یعنی داده‌ها رو «تغییر» میدن. مثلا:
      • INSERT: یه ردیف داده جدید اضافه میکنه.
      • UPDATE: داده‌های موجود رو به‌روز میکنه.
      • DELETE: داده‌ها رو حذف میکنه.
    2. DDL (Data Definition Language): زبان تعریف داده‌ها. این دستورها با ساختار پایگاه داده کار دارن. یعنی اون جدول‌ها و روابط بینشون رو «تعریف» یا «تغیبر» میدن. مثلا:
      • CREATE TABLE: یه جدول جدید میسازه.
      • ALTER TABLE: ساختار یه جدول موجود رو تغییر میده.
      • DROP TABLE: یه جدول رو کلا حذف میکنه.

    درک این تفاوت بهتون کمک میکنه که بهتر بفهمین هر دستور داره چیکار میکنه.

    بخش سوم: چطوری پست‌گرس‌کیوال رو نصب و راه‌اندازی کنیم؟

    خب، حالا که با مفاهیم اولیه آشنا شدیم، ببینیم چطوری میشه این نرم‌افزار رو روی کامپیوترمون داشته باشیم. راه‌های مختلفی برای این کار وجود داره.

    راه‌های مختلف برای دریافت پست‌گرس‌کیوال

    شما میتونین پست‌گرس‌کیوال رو به چند شکل مختلف دانلود کنین:

    • بسته‌های آماده (Ready-to-use packages) یا نصب‌کننده‌ها (Installers): این ساده‌ترین راهه. برای سیستم‌عامل‌های مختلف مثل ویندوز، مک و توزیع‌های مختلف لینوکس، فایل‌های نصب آماده‌ای وجود داره که شما فقط دانلود و اجراشون میکنین و مراحل رو دنبال میکنین.
    • سورس کد (Source code archive): اگه خیلی حرفه‌ای هستین و دوست دارین خودتون نرم‌افزار رو از پایه بسازین (کامپایل کنین)، میتونین سورس کدش رو دانلود کنین. دستورالعمل‌های ساختنش هم توی راهنمای رسمیش هست. مخزن سورس کدش هم روی git.postgresql.org قرار داره.
    • نسخه‌های آزمایشی (Beta and release candidates): اگه دوست دارین ویژگی‌های جدیدی که هنوز به طور رسمی منتشر نشدن رو تست کنین، میتونین نسخه‌های بتا یا کاندیدای انتشار رو دانلود کنین. خیلی مهمه که بدونین این نسخه‌ها فقط برای تست هستن و نباید روی سیستم‌های واقعی و کاری ازشون استفاده کنین.

    پشته‌های نرم‌افزاری آماده

    گاهی اوقات شما برای راه‌اندازی یه وبسایت یا برنامه، فقط به پایگاه داده نیاز ندارین. به یه وب سرور (مثل آپاچی) و یه زبان برنامه‌نویسی (مثل PHP) هم احتیاج دارین. به مجموعه این نرم‌افزارها که با هم کار میکنن میگن «پشته» یا Stack.

    شرکتی به اسم BitNami پشته‌های آماده‌ای رو درست کرده که کار رو خیلی راحت میکنه. این پشته‌ها شامل این موارد هستن:

    • LAPP: لینوکس + آپاچی + پی‌اچ‌پی + پست‌گرس‌کیوال
    • MAPP: مک + آپاچی + پی‌اچ‌پی + پست‌گرس‌کیوال
    • WAPP: ویندوز + آپاچی + پی‌اچ‌پی + پست‌گرس‌کیوال

    با نصب این پشته‌ها، همه ابزارهای لازم برای شروع کار به صورت یکجا و هماهنگ با هم نصب میشن.

    نرم‌افزارهای جانبی و کاتالوگ

    دنیای پست‌گرس‌کیوال خیلی بزرگه و کلی نرم‌افزار دیگه هم وجود داره که باهاش کار میکنن ولی به صورت پیش‌فرض همراهش نیستن. توی سایت رسمی پست‌گرس‌کیوال یه بخشی به اسم «کاتالوگ نرم‌افزار» (Software Catalogue) وجود داره که لیست بزرگی از برنامه‌های تجاری و متن‌باز، رابط‌ها و افزونه‌های مختلف رو میتونین توش پیدا کنین. اگه خودتون هم محصولی ساختین که با پست‌گرس‌کیوال کار میکنه، میتونین با پر کردن یه فرم، اون رو به این کاتالوگ اضافه کنین.

    یک راه ساده برای تمرین: Docker

    اگه تازه دارین یاد میگیرین، شاید نخواین کلی نرم‌افزار روی سیستم‌عامل اصلیتون نصب کنین. اینجا ابزاری به اسم داکر (Docker) خیلی به درد میخوره. داکر به شما اجازه میده برنامه‌ها رو توی محیط‌های ایزوله‌ای به اسم «کانتینر» اجرا کنین. اینجوری میتونین یه پایگاه داده پست‌گرس‌کیوال رو خیلی سریع راه بندازین، باهاش تمرین کنین و بعد با یه دستور ساده همه چیز رو پاک کنین، بدون اینکه کامپیوترتون شلوغ بشه.

    مثلا با دستور زیر میشه یه کانتینر پست‌گرس نسخه ۱۳.۳ رو راه انداخت:

    docker run --rm -p 5432:5432 --name some-postgres-container-name -e POSTGRES_PASSWORD=mysecretpassword postgres:13.3

    بیاین این دستور رو با هم بررسی کنیم:

    • docker run: به داکر میگه یه کانتینر جدید رو اجرا کن.
    • --rm: میگه وقتی کارم با کانتینر تموم شد و متوقفش کردم، خودکار حذفش کن. این برای تمرین عالیه.
    • -p 5432:5432: این بخش مربوط به پورت‌هاست. میگه پورت 5432 کامپیوتر من رو به پورت 5432 داخل کانتینر وصل کن. پورت 5432 پورت استاندارد پست‌گرس‌کیواله.
    • --name some-postgres-container-name: یه اسم برای کانتینرمون انتخاب میکنیم.
    • -e POSTGRES_PASSWORD=mysecretpassword: یه متغیر محیطی به اسم POSTGRES_PASSWORD رو تنظیم میکنه و مقدارش رو برابر با mysecretpassword قرار میده. این پسورد کاربر اصلی پایگاه داده میشه.
    • postgres:13.3: اسم و نسخه ایمیجی که میخوایم از روش کانتینر رو بسازیم. اینجا یعنی ایمیج رسمی پست‌گرس با نسخه 13.3.

    یه نکته مهم اینه که همیشه سعی کنین نسخه مشخصی از ایمیج رو استفاده کنین (مثلا 13.3) و از latest استفاده نکنین، چون ممکنه در آینده آپدیت بشه و رفتارش تغییر کنه.

    بخش چهارم: وقتی اوضاع خراب میشه؛ آموزش عیب‌یابی (Troubleshooting)

    هیچ سیستمی همیشه بی‌نقص کار نمیکنه. گاهی وقتا به مشکل میخوریم. مهم اینه که بدونیم چطوری مشکل رو پیدا و حل کنیم. تو این بخش میخوایم دو تا سناریوی واقعی از مشکلاتی که برای کاربرا پیش اومده رو با هم بررسی کنیم و ببینیم چطوری میشه مثل یه کارآگاه، رد خطاها رو گرفت و به جواب رسید.

    سناریو اول: «بعد از آپدیت، سیستم بالا نمیاد و میگه سرور پست‌گرس استارت نشد!»

    این مشکل برای یه کاربر سیستم‌عامل مانجارو لینوکس پیش اومده بود. کامپیوترش که برای کار ازش استفاده میکرد، بعد از یه آپدیت دیگه بالا نمیومد و روی لوگوی ASRock (مارک مادربوردش) گیر میکرد. پیام خطای اصلی این بود: Failed to start PostgreSQL database server (سرور پایگاه داده پست‌گرس‌کیوال شروع به کار نکرد).

    اینجا کاربر با کمک بقیه، شروع به تحقیق میکنه. اولین قدم اینه که ببینیم سیستم دقیقا داره چه خطاهایی میده. برای این کار از یه دستور به اسم journalctl استفاده میشه. این دستور، گزارش‌ها و رویدادهای سیستم (که بهشون میگن log) رو نشون میده.

    دستوری که استفاده شد این بود: journalctl -xep 0..3

    • journalctl: خود برنامه.
    • -x: اطلاعات بیشتری در مورد هر خطا میده.
    • -e: مستقیم میره به آخر گزارش‌ها که جدیدترین خطاها اونجا هستن.
    • -p 0..3: میگه فقط پیام‌هایی با اولویت بالا رو نشون بده (از ۰ تا ۳ که شامل Emergency, Alert, Critical, Error میشه).

    حالا بیاین با هم لاگ‌هایی که این دستور نشون داده رو بررسی کنیم. این لاگ‌ها خیلی طولانی و ترسناک به نظر میرسن، ولی اگه با دقت و حوصله بخونیمشون، سرنخ‌های خوبی بهمون میدن.

    کالبدشکافی لاگ‌های سیستم

    من بخش‌های مهم و تکراری لاگ رو براتون جدا کردم تا تحلیلشون کنیم.

    سرنخ اول: مشکلات مربوط به Firmware و Microcode

    Jun 01 12:43:27 user-pc kernel: [Firmware Bug]: TSC_DEADLINE disabled due to Errata; please update microcode to version: 0x3a (or later)
    • kernel: هسته اصلی سیستم‌عامل. این پیام از پایین‌ترین سطح نرم‌افزاری سیستم میاد.
    • Firmware Bug: یعنی یه باگ توی سفت‌افزار (نرم‌افزار سطح پایینی که روی سخت‌افزارها مثل CPU یا مادربورد اجرا میشه) وجود داره.
    • please update microcode: سیستم داره پیشنهاد میده که میکروکد سی‌پی‌یو رو آپدیت کنیم. میکروکد یه جورایی مثل یه آپدیت برای خود سی‌پی‌یو هست که بعضی از باگ‌هاش رو برطرف میکنه.

    نتیجه‌گیری اولیه:

    همین اول کار، سیستم داره بهمون میگه که یه مشکل سطح پایین سخت‌افزاری/نرم‌افزاری وجود داره. این خودش یه زنگ خطره.

    سرنخ دوم: پیدا نشدن ماژول‌های کرنل

    این خطا بارها و بارها توی لاگ‌ها تکرار شده:

    Jun 01 12:43:27 user-pc systemd-modules-load[337]: Failed to find module 'vboxdrv'
    Jun 01 12:43:27 user-pc systemd-modules-load[337]: Failed to find module 'vboxnetadp'
    Jun 01 12:43:27 user-pc systemd-modules-load[337]: Failed to find module 'vboxnetflt'
    Jun 01 14:59:29 user-pc systemd-modules-load[319]: Failed to find module 'nvidia'
    Jun 01 14:59:29 user-pc systemd-modules-load[319]: Failed to find module 'nvidia-drm'
    Jun 01 14:59:29 user-pc systemd-modules-load[319]: Failed to find module 'zfs'
    • systemd-modules-load: یه بخشی از سیستم‌عامل که مسئول بارگذاری ماژول‌های کرنله.
    • ماژول کرنل چیه؟ فکر کنین کرنل سیستم‌عامل مثل یه موتور ماشینه. ماژول‌ها مثل قطعات اضافی هستن که به این موتور وصل میشن تا کارهای خاصی رو انجام بدن. مثلا درایور کارت گرافیک، درایور کارت شبکه و… .
    • Failed to find module: یعنی سیستم نتونسته این ماژول‌ها رو پیدا و بارگذاری کنه.
    • vboxdrv, vboxnetadp, vboxnetflt: اینها مربوط به نرم‌افزار VirtualBox هستن که برای ساخت ماشین‌های مجازی استفاده میشه.
    • nvidia, nvidia-drm: اینها مربوط به درایور کارت گرافیک Nvidia هستن.
    • zfs: این مربوط به یه نوع سیستم فایل پیشرفته به اسم ZFS هست.

    نتیجه‌گیری دوم:

    به نظر میاد بعد از اون آپدیت، درایورهای مهمی مثل درایور کارت گرافیک و ابزارهای مجازی‌سازی به درستی نصب نشدن یا با نسخه جدید کرنل سازگار نیستن. این میتونه باعث بی‌ثباتی کل سیستم بشه.

    سرنخ سوم: خطاهای مربوط به حافظه و سخت‌افزار

    این خطا هم خیلی زیاد تکرار شده:

    Jun 01 12:43:44 user-pc kernel: EDAC sbridge: CPU SrcID #0, Ha #0, Channel #0 has DIMMs, but ECC is disabled
    Jun 01 12:43:44 user-pc kernel: EDAC sbridge: Couldn't find mci handler
    Jun 01 12:43:44 user-pc kernel: EDAC sbridge: Failed to register device with error -19.
    • EDAC (Error Detection and Correction): یه قابلیتی توی سخت‌افزارها برای پیدا کردن و تصحیح خطاهای حافظه.
    • ECC is disabled: یعنی حافظه ECC (که نوع خاصی از رم برای سرورهاست و قابلیت تصحیح خطا داره) غیرفعاله. این ممکنه برای یه کامپیوتر شخصی عادی باشه، ولی خود پیام خطا نشون میده که سیستم در حال بررسی عمیق سخت‌افزاره.
    • Failed to register device with error -19: این پیام خیلی کلیه ولی نشون میده که کرنل نتونسته یه قطعه سخت‌افزاری رو به درستی شناسایی و راه‌اندازی کنه.

    نتیجه‌گیری سوم:

    علاوه بر مشکلات درایور، به نظر میاد سیستم در ارتباط با بعضی از قطعات سخت‌افزاری هم مشکل داره.

    سرنخ چهارم: خطای نهایی پست‌گرس

    و بالاخره میرسیم به خطایی که کاربر از اول دیده بود:

    Jun 01 12:43:46 user-pc systemd[1]: Failed to start PostgreSQL database server.

    این پیام توسط systemd صادر شده که مدیر سیستم و سرویس‌ها در لینوکسه. این پیام به ما نمیگه چرا پست‌گرس استارت نشده، فقط میگه که تلاشش برای این کار ناموفق بوده.

    جمع‌بندی کارآگاهی سناریو اول:

    مشکل اصلی به احتمال زیاد خود پست‌گرس‌کیوال نیست. مشکل اینه که کل سیستم‌عامل بعد از آپدیت به هم ریخته و بی‌ثبات شده. وقتی درایورهای اصلی مثل درایور گرافیک بارگذاری نمیشن و کرنل در شناسایی سخت‌افزارها مشکل داره، سیستم نمیتونه یه محیط پایدار برای اجرای سرویس‌های دیگه مثل پست‌گرس‌کیوال فراهم کنه. راه‌حل در این مورد، احتمالا تعمیر سیستم‌عامل، نصب مجدد درایورها، یا برگردوندن آپدیت‌هاست، نه دستکاری کردن تنظیمات خود پست‌گرس. این یه درس مهمه: گاهی اوقات ریشه مشکل جاییه که اصلا انتظارش رو نداریم.


    سناریو دوم: «نمیتونم به سرور وصل بشم، میگه همچین فایلی وجود نداره!»

    این یکی مشکل رایج‌تریه و معمولا مستقیم به خود پست‌گرس ربط داره. یه کاربر روی اوبونتو ۱۸.۰۴ با این خطا مواجه شده:

    psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket “/var/run/postgresql/.s.PGSQL.5432”?

    این خطا یعنی برنامه psql (که ابزار خط فرمان برای وصل شدن به پست‌گرسه) نتونسته به سرور پست‌گرس وصل بشه. داره میپرسه که آیا سرور به صورت محلی (locally) روشنه و روی یه چیزی به اسم «سوکت دامنه یونیکس» داره گوش میده یا نه.

    بیاین مراحل عیب‌یابی این کاربر رو دنبال کنیم:

    قدم اول: وضعیت سرویس رو چک کنیم

    اولین کاری که باید بکنیم اینه که ببینیم آیا سرویس پست‌گرس‌کیوال اصلا روشنه یا نه.

    sudo systemctl status postgresql

    کاربر این دستور رو زده و دیده که سیستم میگه سرویس «فعاله». حتی با دستور restart هم سرویس رو دوباره راه‌اندازی کرده ولی مشکل حل نشده. این یکم عجیبه.

    قدم دوم: لیست کلاسترهای پست‌گرس رو ببینیم

    در سیستم‌عامل‌های مبتنی بر دبیان (مثل اوبونتو)، پست‌گرس با مفهومی به اسم «کلاستر» کار میکنه. هر کلاستر یه نمونه جدا از سرور پست‌گرسه که میتونه تنظیمات، پورت و مسیر داده‌های خودشو داشته باشه. با دستور زیر میشه لیست کلاسترها رو دید:

    pg_lsclusters

    وقتی کاربر این دستور رو میزنه، با این خروجی مواجه میشه:

    Ver Cluster Port Status Owner Data directory Log file
    10 main 5432 down postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
    11 main 5433 down postgres /var/lib/postgresql/11/main /var/log/postgresql/postgresql-11-main.log
    12 main 5434 down postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

    این خروجی خیلی مهمه! ستون Status (وضعیت) برای همه کلاسترها down (خاموش) رو نشون میده. پس بر خلاف چیزی که systemctl میگفت، سرورهای پست‌گرس در واقع خاموش هستن!

    قدم سوم: تلاش برای روشن کردن دستی کلاستر

    حالا کاربر سعی میکنه یکی از کلاسترها رو دستی روشن کنه:

    sudo pg_ctlcluster 10 main start

    اما این دستور هم خطا میده و میگه سرویس نتونسته استارت بشه و برای جزئیات بیشتر لاگ‌ها رو چک کنین.

    قدم چهارم: خوندن فایل لاگ پست‌گرس

    این مهم‌ترین مرحله‌ست. ما باید بریم سراغ فایل لاگی که خود پست‌گرس‌کیوال مینویسه تا ببینیم دردش چیه. مسیر فایل لاگ توی خروجی pg_lsclusters مشخص شده بود.

    sudo nano /var/log/postgresql/postgresql-10-main.log

    (nano یه ویرایشگر متن ساده در خط فرمانه)

    و بالاخره، سرنخ اصلی پیدا میشه. داخل فایل لاگ این خطا نوشته شده:

    2020-09-29 02:27:06.445 WAT [25041] FATAL: data directory "/var/lib/postgresql/10/main" has group or world access
    2020-09-29 02:27:06.445 WAT [25041] DETAIL: Permissions should be u=rwx (0700).
    • FATAL: یعنی یه خطای خیلی جدی که جلوی اجرای برنامه رو گرفته.
    • data directory ... has group or world access: میگه پوشه‌ای که داده‌های پست‌گرس توش ذخیره میشه (/var/lib/postgresql/10/main)، دسترسی‌های بیش از حدی داره. یعنی بقیه کاربرهای سیستم (group یا world) هم میتونن بهش دسترسی داشته باشن.
    • Permissions should be u=rwx (0700): خود پست‌گرس داره راه‌حل رو هم میگه. میگه سطح دسترسی (Permission) این پوشه باید 0700 باشه.

    سطح دسترسی یا Permission چیه؟

    در سیستم‌عامل‌های لینوکسی، برای هر فایل و پوشه مشخص میشه که چه کسانی چه کارهایی میتونن روش انجام بدن. این افراد به سه دسته تقسیم میشن:

    • User (u): مالک فایل.
    • Group (g): گروهی که مالک فایل عضو اون هست.
    • Others/World (o): بقیه کاربران سیستم.

    کارها هم سه نوع هستن:

    • Read (r): خوندن
    • Write (w): نوشتن
    • Execute (x): اجرا کردن

    سطح دسترسی 0700 یعنی:

    • User: دسترسی کامل برای خوندن، نوشتن و اجرا کردن داره (rwx).
    • Group: هیچ دسترسی‌ای نداره.
    • Others: هیچ دسترسی‌ای نداره.

    چرا پست‌گرس اینقدر حساسه؟

    چون داده‌های داخل پایگاه داده خیلی مهمن. اگه هر کاربری توی سیستم بتونه فایل‌های داده رو بخونه یا تغییر بده، یه فاجعه امنیتی رخ میده. برای همین پست‌گرس قبل از اینکه روشن بشه، چک میکنه و اگه ببینه پوشه داده‌هاش امن نیست، اصلا روشن نمیشه.

    قدم پنجم: تصحیح سطح دسترسی و راه‌اندازی مجدد

    حالا که مشکل پیدا شد، راه‌حلش ساده‌ست. باید سطح دسترسی پوشه‌ها رو درست کنیم.

    sudo chmod -R 0700 /var/lib/postgresql/10/main
    sudo chmod -R 0700 /var/lib/postgresql/11/main
    sudo chmod -R 0700 /var/lib/postgresql/12/main
    • chmod: دستوری برای تغییر سطح دسترسی.
    • -R: یعنی این تغییر رو روی خود پوشه و تمام فایل‌ها و پوشه‌های داخلش هم اعمال کن (Recursive).

    بعد از اجرای این دستورها، کاربر دوباره سعی میکنه کلاسترها رو روشن کنه:

    sudo pg_ctlcluster 10 main start
    sudo pg_ctlcluster 11 main start
    sudo pg_ctlcluster 12 main start

    و این بار موفقیت‌آمیز بود. در نهایت با چک کردن دوباره وضعیت کلاسترها، میبینه که همه online شدن:

    Ver Cluster Port Status Owner Data directory Log file
    10 main 5432 online postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
    11 main 5433 online postgres /var/lib/postgresql/11/main /var/log/postgresql/postgresql-11-main.log
    12 main 5434 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

    و مشکل حل میشه.


    سناریو سوم: خطای «authentication failed» با داکر

    یه مشکل رایج دیگه وقتی پیش میاد که شما هم روی کامپیوتر خودتون (مثلا ویندوز ۱۱) پست‌گرس رو نصب کردین، و هم دارین سعی میکنین یه نسخه دیگه از پست‌گرس رو با داکر اجرا کنین.

    مشکل اینه: هر دوتاشون به صورت پیش‌فرض سعی میکنن از پورت 5432 استفاده کنن.

    پورت شبکه چیه؟

    فکر کنین آدرس آی‌پی کامپیوتر شما مثل آدرس یه ساختمون بزرگه. پورت‌ها مثل شماره واحد‌های توی اون ساختمون هستن. وقتی یه برنامه میخواد با یه برنامه دیگه روی شبکه حرف بزنه، باید هم آدرس ساختمون (IP) و هم شماره واحد (Port) رو بدونه.

    وقتی شما دو تا سرور پست‌گرس رو همزمان روشن میکنین که هر دو میخوان از پورت 5432 استفاده کنن، مثل این میمونه که دو نفر بخوان توی یه آپارتمان با شماره واحد یکسان زندگی کنن. سیستم قاطی میکنه و نمیدونه درخواست‌ها رو باید به کدوم یکی بفرسته.

    علامت مشکل چیه؟

    معمولا خطایی مثل p1000 authentication failed میگیرین. دلیلش اینه که ابزار شما (مثلا Prisma که یه ابزار برای کار با پایگاه داده‌ست) داره سعی میکنه با اطلاعات کاربری پست‌گرسِ داخل داکر، به پست‌گرسِ نصب شده روی کامپیوتر اصلیتون وصل بشه (چون اون پورت 5432 رو اشغال کرده). طبیعتا اطلاعات کاربری با هم نمیخونه و خطا میده.

    راه‌حل چیه؟

    راه‌حل ساده‌ست: باید شماره پورت یکی از اونها رو عوض کنیم. توی سناریوی داکر، این کار خیلی راحته. فقط کافیه موقع اجرای کانتینر، نگاشت پورت رو تغییر بدیم.

    دستور قبلی این بود:

    docker run ... -p 5432:5432 ...

    دستور جدید این میشه:

    docker run ... -p 5433:5432 ...

    این تغییر یعنی چی؟

    • -p 5433:5432: به داکر میگه «هر درخواستی به پورت 5433 کامپیوتر من اومد، اون رو بفرست به پورت 5432 داخل کانتینر».

    اینجوری، پست‌گرس نصب شده روی سیستم اصلی شما روی پورت 5432 کار میکنه و پست‌گرس داخل داکر روی پورت 5433. دیگه با هم تداخلی ندارن و شما میتونین با مشخص کردن پورت درست، به هر کدوم که خواستین وصل بشین.

    بخش پنجم: مدیریت روزمره پایگاه داده

    خب، حالا که سرورمون راه افتاده و مشکلات احتمالی رو هم بلدیم حل کنیم، بیاین یه نگاهی به کارهای روزمره بندازیم.

    پایگاه داده‌های پیش‌فرض: postgres, template1, template0

    وقتی پست‌گرس‌کیوال برای اولین بار نصب میشه، چند تا پایگاه داده رو به صورت خودکار میسازه. شاید از خودتون بپرسین اینها به چه دردی میخورن.

    • postgres: این پایگاه داده به عنوان نقطه اتصال پیش‌فرض برای ابزارها و کاربرها ساخته شده. وقتی شما برنامه‌ای مثل psql رو باز میکنین و مشخص نمیکنین به کدوم پایگاه داده میخواین وصل بشین، به صورت خودکار به postgres وصل میشه. یه جورایی مثل لابی یه هتله. شما اول وارد لابی میشین، بعد تصمیم میگیرین به کدوم اتاق برین. خود سرور پست‌گرس برای کار کردنش به این پایگاه داده نیازی نداره، ولی خیلی از ابزارهای جانبی فرض میکنن که این پایگاه داده وجود داره. پس بهتره حذفش نکنین.
    • template1: این یکی خیلی جالبه. اسمش یعنی «قالب شماره ۱». هر وقت شما یه پایگاه داده جدید میسازین، پست‌گرس در واقع یه کپی کامل از template1 درست میکنه. پس اگه شما یه جدول یا یه تنظیم خاصی رو توی template1 ایجاد کنین، تمام پایگاه داده‌های جدیدی که از اون به بعد میسازین، اون جدول یا تنظیم رو به ارث میبرن. این یه ابزار قدرتمند برای استانداردسازی پایگاه داده‌هاتونه.
    • template0: اینم یه قالبه، ولی یه قالب دست‌نخورده و تمیز. یه جورایی نسخه «تنظیمات کارخانه» محسوب میشه. گاهی اوقات ممکنه شما template1 رو خراب کنین (مثلا یه چیزی توش اضافه کنین که نباید میکردین). از اونجایی که برای ساختن یه کپی از یه قالب، نباید هیچ اتصال دیگه‌ای به اون قالب وجود داشته باشه، اگه template1 خراب بشه، درست کردنش سخته. اینجا template0 به کمکتون میاد. میتونین template1 رو حذف کنین و یه template1 جدید از روی template0 بسازین.

    پس به طور خلاصه:

    • postgres: برای اتصال اولیه.
    • template1: قالب پیش‌فرض برای ساخت پایگاه داده‌های جدید.
    • template0: نسخه پشتیبان و تمیز از قالب، برای روز مبادا.

    کپی کردن یک پایگاه داده از یه سرور به سرور دیگه

    یکی از کارهای خیلی رایج، کپی کردن یه پایگاه داده از یه محیط به محیط دیگه‌ست. مثلا از سرور اصلی (Production) به یه سرور تستی (Development) تا بتونین بدون ریسک، روی داده‌های واقعی کار کنین. راه‌های مختلفی برای این کار هست.

    روش اول: استفاده از pg_dump و psql (روش کلاسیک)

    این روش خیلی محبوبه و از دو تا ابزار خط فرمان استفاده میکنه: pg_dump برای گرفتن خروجی (بکاپ) و psql برای برگردوندن اون خروجی (ریستور).

    میشه این دوتا رو با هم ترکیب کرد تا بدون ساختن فایل واسطه، کار انجام بشه. به این کار میگن «پایپ کردن» (Piping) که با علامت | انجام میشه.

    pg_dump -C -h localhost -U localuser dbname | psql -h remotehost -U remoteuser dbname

    بیاین این دستور رو بشکافیم:

    • pg_dump: ابزار بکاپ‌گیری.
    • -C: به pg_dump میگه که دستور CREATE DATABASE رو هم توی خروجی بذاره. اینجوری لازم نیست پایگاه داده مقصد رو از قبل بسازیم.
    • -h localhost: میگه به سروری که روی همین کامپیوتر (localhost) هست وصل شو.
    • -U localuser: با کاربر localuser وصل شو.
    • dbname: اسم پایگاه داده‌ای که میخوایم ازش بکاپ بگیریم.
    • |: این علامت جادوییه. خروجی دستور سمت چپش رو به عنوان ورودی به دستور سمت راستش میده.
    • psql: ابزار کلاینت پست‌گرس که اینجا برای ریستور کردن استفاده میشه.
    • -h remotehost: میگه به سرور مقصد که آدرسش remotehost هست وصل شو.
    • -U remoteuser: با کاربر remoteuser به سرور مقصد وصل شو.

    اگه پایگاه داده بزرگ باشه یا سرعت شبکه کم باشه، شاید بهتر باشه اول خروجی رو توی یه فایل ذخیره کنین، فایل رو فشرده کنین، به سرور مقصد منتقل کنین و بعد اونجا ریستور کنین.

    # روی سرور مبدا
    pg_dump -C -Fp -f dump.sql -U postgres some_database_name
    scp dump.sql development:
    rm dump.sql
    
    # روی سرور مقصد
    ssh development
    psql -U postgres -f dump.sql

    روش دوم: استفاده از تونل فشرده با SSH

    اگه میخواین همزمان هم کار فشرده‌سازی و هم انتقال امن رو انجام بدین، میتونین از این روش استفاده کنین:

    pg_dump -C dbname | bzip2 | ssh remoteuser@remotehost "bunzip2 | psql dbname"

    اینجا خروجی pg_dump اول با bzip2 فشرده میشه، بعد از طریق یه اتصال امن ssh به سرور مقصد فرستاده میشه، اونجا از حالت فشرده خارج میشه (bunzip2) و در نهایت با psql ریستور میشه.

    روش سوم: pg_basebackup (برای حرفه‌ای‌ها و دیتابیس‌های بزرگ)

    این ابزار برای وقتیه که شما میخواین یه کپی کامل و دقیق از کل «کلاستر» پایگاه داده بگیرین، نه فقط یه پایگاه داده خاص. این روش سریع‌تره، مخصوصا برای دیتابیس‌های خیلی بزرگ. این کار یه جورایی مثل کلون کردن هارد دیسک سرور پایگاه داده‌ست.

    برای استفاده از این روش باید یه سری تنظیمات روی سرور مبدا انجام بدین:

    1. در فایل postgresql.conf، گزینه listen_addresses رو روی '*' تنظیم کنین تا سرور از آی‌پی‌های دیگه هم اتصال قبول کنه.
    2. باز هم در همین فایل، wal_level رو حداقل روی replica بذارین.
    3. و max_wal_senders رو روی یه عددی بزرگتر از صفر (مثلا ۱ یا بیشتر) تنظیم کنین.
    4. در فایل pg_hba.conf، یه خط اضافه کنین که به سرور مقصد اجازه اتصال برای «replication» (همانندسازی) بده.
      host replication postgres DST_IP/32 trust
      (به جای DST_IP باید آی‌پی سرور مقصد رو بذارین).
    5. بعد از این تغییرات، سرور پست‌گرس رو ریستارت کنین.

    حالا روی سرور مقصد:

    1. سرویس پست‌گرس رو متوقف کنین (sudo service postgresql stop).
    2. تمام محتویات پوشه داده‌های پست‌گرس رو پاک کنین (مثلا /var/lib/postgresql/12/main/*). مواظب باشین این کار رو روی سرور اشتباهی انجام ندین!
    3. دستور pg_basebackup رو اجرا کنین:
    sudo -u postgres pg_basebackup -h SRC_IP -U postgres -D /var/lib/postgresql/12/main/ --progress

    (به جای SRC_IP آی‌پی سرور مبدا رو بذارین).

    1. بعد از اینکه کارش تموم شد، سرویس پست‌گرس رو روی سرور مقصد روشن کنین (sudo service postgresql start).

    حالا شما یه کپی دقیق از کل سرور مبدا روی سرور مقصد دارین.

    روش چهارم: استفاده از رابط گرافیکی (GUI) مثل pgAdmin

    اگه با خط فرمان راحت نیستین، همیشه میتونین از ابزارهای گرافیکی استفاده کنین. با pgAdmin مراحل خیلی ساده‌ست:

    1. به هر دو سرور مبدا و مقصد وصل بشین.
    2. روی پایگاه داده مبدا کلیک راست کنین و گزینه «Backup» رو بزنین. یه فایل بکاپ براتون میسازه.
    3. روی سرور مقصد کلیک راست کنین، «Create» و بعد «Database» رو بزنین و یه پایگاه داده جدید با همون مشخصات پایگاه داده مبدا بسازین.
    4. روی پایگاه داده جدیدی که ساختین کلیک راست کنین و «Restore» رو بزنین. فایل بکاپی که در مرحله ۲ ساختین رو بهش بدین تا اطلاعات رو برگردونه.

    بخش ششم: چطوری سرعت رو بالا نگه داریم؟ نگاهی به بهینه‌سازی عملکرد

    گاهی اوقات ممکنه پایگاه داده شما کند بشه، مخصوصا وقتی حجم داده‌ها زیاد میشه و تعداد کاربرها بالا میره. به این وضعیت میگن «بار بالا» (High Load). مدیریت این وضعیت یه بحث خیلی بزرگه، ولی بیاین چند تا نکته کلیدی رو با هم مرور کنیم.

    ۱. اول بفهمین دیتابیس داره چیکار میکنه.
    مشکلات عملکردی معمولا به خاطر چند تا «کوئری» (Query) یا همون پرس‌وجوی سنگین و پرهزینه‌ست که زیاد اجرا میشن. اولین قدم اینه که این کوئری‌ها رو پیدا کنین.

    ۲. از EXPLAIN ANALYZE استفاده کنین.
    این یکی از قدرتمندترین ابزارهای شماست. وقتی قبل از هر کوئری SELECT، عبارت EXPLAIN ANALYZE رو بنویسین، پست‌گرس به جای اجرای عادی کوئری، به شما یه گزارش کامل از «نقشه اجرا» (Execution Plan) اون کوئری میده. یعنی بهتون میگه که برای پیدا کردن جواب، دقیقا چه قدم‌هایی رو برداشته و هر قدم چقدر زمان برده.

    ۳. حواستون به «Sequential Scans» باشه.
    وقتی توی خروجی EXPLAIN دیدین که روی یه جدول بزرگ داره «Sequential Scan» انجام میشه، باید حواستون رو جمع کنین. این یعنی پست‌گرس داره کل جدول رو ردیف به ردیف از اول تا آخر میخونه تا داده مورد نظر شما رو پیدا کنه. این کار برای جدول‌های بزرگ خیلی خیلی کنده.

    ۴. از ایندکس (Index) استفاده کنین.
    راه‌حل Sequential Scan معمولا ساختن «ایندکس» هست. ایندکس مثل فهرست آخر یه کتاب قطوره. شما برای پیدا کردن یه مطلب، کل کتاب رو صفحه به صفحه نمیخونین، بلکه میرین سراغ فهرست و مستقیم به صفحه مورد نظر میرین. ایندکس هم برای پایگاه داده همین کار رو میکنه. شما روی ستون‌هایی که معمولا توی شرط WHERE کوئری‌هاتون استفاده میکنین، ایندکس میسازین. اینجوری پست‌گرس میتونه خیلی سریع‌تر ردیف‌های مورد نظر رو پیدا کنه.

    ۵. VACUUM و ANALYZE رو فراموش نکنین.
    وقتی شما داده‌ها رو توی پست‌گرس UPDATE یا DELETE میکنین، فضای اونها فورا آزاد نمیشه. به مرور زمان این فضاهای مرده جمع میشن و باعث میشن جدول‌ها بزرگتر از اندازه واقعی‌شون بشن (به این میگن Bloat). دستور VACUUM این فضاهای مرده رو تمیز و قابل استفاده مجدد میکنه.

    دستور ANALYZE هم اطلاعات آماری در مورد توزیع داده‌ها توی جدول‌ها جمع‌آوری میکنه. پست‌گرس از این آمارها استفاده میکنه تا بهترین و بهینه‌ترین نقشه اجرا رو برای کوئری‌های شما انتخاب کنه.

    در خیلی از تنظیمات پیش‌فرض، سرویس «autovacuum» فعاله و این کارها رو خودکار انجام میده، ولی خوبه که بدونین این دستورها وجود دارن و گاهی اوقات لازمه به صورت دستی اجرا بشن.

    بخش هفتم: پرسش و پاسخ (سوالات متداول شما)

    در طول این مقاله به سوالات مختلفی اشاره کردیم. بیاین اینجا چند تا از مهم‌ترین‌هاشون رو به صورت خلاصه مرور کنیم.

    سوال ۱: بالاخره پست‌گرس‌کیوال یه زبانه یا یه سرور؟
    پست‌گرس‌کیوال یک نرم‌افزار مدیریت پایگاه داده هست که به عنوان یک سرور عمل میکنه. این نرم‌افزار، زبان SQL (زبان استاندارد کوئری‌نویسی) رو میفهمه و اجرا میکنه. پس خودش زبان نیست، بلکه اجراکننده زبانه.

    سوال ۲: این «سرورهایی» که توی pgAdmin میبینم چی هستن؟ یعنی چند تا کامپیوتر مختلفن؟
    هر «سرور» توی pgAdmin نشون‌دهنده یک اتصال به یک نمونه (instance) از سرور پایگاه داده پست‌گرس‌کیواله. این سرور میتونه روی کامپیوتر خود شما باشه (localhost) یا روی یه کامپیوتر دیگه در شبکه یا اینترنت. شما میتونین به چندین سرور مختلف به صورت همزمان متصل باشین.

    سوال ۳: من پایگاه داده‌هایی به اسم postgres و template1 میبینم. اینها چی هستن و میتونم پاکشون کنم؟

    • postgres: پایگاه داده پیش‌فرض برای اتصال اولیه ابزارها و کاربران. بهتره پاکش نکنین چون خیلی از برنامه‌ها به وجودش تکیه میکنن.
    • template1: قالبی که تمام پایگاه داده‌های جدید از روی اون کپی میشن. پاک کردنش ایده خوبی نیست، مگه اینکه بخواین از روی template0 (قالب پشتیبان) یه نسخه جدید ازش بسازین.

    سوال ۴: ساده‌ترین راه برای کپی کردن یه پایگاه داده از کامپیوتر خودم به یه سرور دیگه چیه؟
    برای دیتابیس‌های کوچیک و متوسط، استفاده از ترکیب pg_dump و psql با پایپ کردن خیلی ساده و سریعه:
    pg_dump -C -h [آدرس مبدا] -U [کاربر مبدا] [اسم دیتابیس مبدا] | psql -h [آدرس مقصد] -U [کاربر مقصد] [اسم دیتابیس مقصد]

    سوال ۵: سرور پست‌گرس من بعد از آپدیت سیستم‌عامل روشن نمیشه و کلی خطای عجیب در مورد nvidia و vboxdrv میبینم. مشکل چیه؟
    به احتمال خیلی زیاد مشکل از خود پست‌گرس نیست. این خطاها نشون میدن که کل سیستم‌عامل شما بعد از آپدیت دچار بی‌ثباتی شده و درایورهای مهمی بارگذاری نشدن. در چنین شرایطی، سیستم نمیتونه محیط پایداری برای اجرای سرویس پست‌گرس فراهم کنه. شما باید اول مشکلات سیستم‌عامل و درایورهاتون رو حل کنین.

    سوال ۶: میخوام وصل بشم ولی خطای authentication failed یا could not connect to server میگیرم. اولین چیزایی که باید چک کنم چی هستن؟

    • آیا سرویس پست‌گرس اصلا روشنه؟ با دستورهایی مثل systemctl status postgresql یا pg_lsclusters وضعیتش رو چک کنین.
    • آیا سطح دسترسی پوشه داده‌ها درسته؟ همونطور که دیدیم، پست‌گرس به این موضوع خیلی حساسه. لاگ‌های پست‌گرس رو چک کنین تا ببینین خطایی در این مورد وجود نداره.
    • آیا تداخل پورت وجود نداره؟ مطمئن بشین که هیچ برنامه دیگه‌ای (مثلا یه نسخه دیگه از پست‌گرس) در حال استفاده از همون پورتی که شما میخواین بهش وصل بشین (معمولا 5432) نیست.
    • آیا اطلاعات اتصال (آدرس سرور، نام کاربری، پسورد) رو درست وارد میکنین؟ این مورد خیلی ساده به نظر میرسه ولی زیاد اتفاق میفته

    منابع

    • [2] After Upgrading, Can’t Boot “Failed to start PostgreSQL database server” – Computer Used for Work – Support – Manjaro Linux Forum
    • [4] Default database named postgres on Postgresql server – Stack Overflow
    • [6] linux – managing high load of a postgresql database – Server Fault
    • [8] PostgreSQL: Why psql can’t connect to server? – Stack Overflow
    • [10] p1000 authentication failed against database server · prisma/prisma · Discussion #8925 · GitHub
    • [1] Noob Question: What are “servers” in postgreSQL/pgAdmin? : r/PostgreSQL
    • [3] PostgreSQL: The world’s most advanced open source database
    • [5] sql – If I’m using PostgreSQL, do I need a server too? Like AWS RDS? – Stack Overflow
    • [7] PostgreSQL: Downloads
    • [9] Copying PostgreSQL database to another server – Stack Overflow
  • آشنایی با MariaDB Server؛ جایگزین اوپن‌سورس MySQL

    ماریا دی‌بی سرور (MariaDB Server) یک سیستم مدیریت پایگاه داده رابطه‌ای هست. حالا این یعنی چی؟ یعنی یک نرم‌افزاره که به شما اجازه میده داده‌ها رو به صورت ساختاریافته و منظم، مثل جدول‌هایی که به هم ربط دارن، ذخیره کنید و بعدا بهشون دسترسی داشته باشید. فکر کنید یه عالمه اطلاعات دارید، از اطلاعات کاربرا گرفته تا محصولات یه فروشگاه. ماریا دی‌بی اینا رو براتون مرتب و منظم نگه میداره.

    جالبی ماجرا اینجاست که ماریا دی‌بی از یه خانواده خیلی معروف میاد. اون در واقع یه «فورک» (Fork) یا انشعاب از سرور مای‌اس‌کیوال (MySQL) هست. فورک یعنی چی؟ یعنی یه عده از توسعه‌دهنده‌های اصلی یه پروژه نرم‌افزاری، یه کپی از کد اون پروژه برمیدارن و مسیر توسعه خودشون رو جداگونه ادامه میدن.

    داستان اینجوری شروع شد که یه سری از اعضای اصلی تیم مای‌اس‌کیوال، بعد از اینکه شرکت اوراکل (Oracle Corporation) مای‌اس‌کیوال رو خرید، نگران آینده‌اش شدن. اونا میخواستن مطمئن بشن که این پایگاه داده همیشه متن‌باز و رایگان باقی میمونه. برای همین، پروژه ماریا دی‌بی رو شروع کردن. اسمش هم جالبه؛ مایکل وایدنیوس (Michael “Monty” Widenius) که یکی از بنیان‌گذارهای اصلی مای‌اس‌کیوال و ماریا دی‌بی هست، اسم دختر کوچیکترش، «ماریا»، رو روی این پروژه گذاشت. جالبه بدونید اسم دختر دیگه‌اش «مای» (My) بود که اسم مای‌اس‌کیوال هم از اون گرفته شده.

    هدف اصلی از ساخت ماریا دی‌بی این بود که به عنوان یه جایگزین مستقیم یا «drop-in replacement» برای مای‌اس‌کیوال عمل کنه. یعنی شما بتونید خیلی راحت مای‌اس‌کیوال رو از روی سرورتون بردارید و ماریا دی‌بی رو به جاش نصب کنید، بدون اینکه نیاز باشه کد برنامه‌هاتون رو تغییر بدید. البته ماریا دی‌بی فقط یه کپی ساده نیست؛ توسعه‌دهنده‌ها سعی کردن ویژگی‌های جدید، موتورهای ذخیره‌سازی (Storage Engines) تازه، باگ‌های کمتر و عملکرد بهتری رو بهش اضافه کنن.

    این پروژه توسط جامعه برنامه‌نویس‌ها توسعه داده میشه و با توسعه‌دهنده‌های خارجی هم همکاری فعالی داره تا یه سرور SQL متن‌باز با بیشترین امکانات، پایداری و لایسنس منطقی رو ارائه بده.

    کی پشت ماریا دی‌بی ایستاده؟

    دو تا نهاد اصلی پشت این پروژه هستن:

    1. بنیاد ماریا دی‌بی (MariaDB Foundation): این یه سازمان غیرانتفاعی هست که وظیفه‌اش نظارت بر توسعه و حفاظت از ماهیت متن‌باز و رایگان ماریا دی‌بی هست. اونا تضمین میکنن که این پروژه همیشه در دسترس همه باشه و هیچ شرکت تجاری نتونه کنترل کاملش رو به دست بگیره.
    2. شرکت ماریا دی‌بی (MariaDB Corporation): این یه شرکت تجاریه که محصولات و خدمات حرفه‌ای بر پایه ماریا دی‌بی ارائه میده. خیلی از توسعه‌دهنده‌های اصلی ماریا دی‌بی توی این شرکت کار میکنن. این شرکت نسخه‌های تجاری با امکانات بیشتر و پشتیبانی تخصصی میفروشه و از این راه درآمد کسب میکنه.

    پس یادتون باشه، خود سرور ماریا دی‌بی رایگان و متن‌بازه، اما یه شرکت هم هست که خدمات پولی حول اون ارائه میده.

    ویژگی‌های کلیدی و تفاوت‌ها

    ماریا دی‌بی تلاش میکنه سازگاری بالایی با مای‌اس‌کیوال داشته باشه. رابط برنامه‌نویسی (API) و پروتکل‌هاش دقیقا با مای‌اس‌کیوال مطابقت دارن. این یعنی همه ابزارها، کتابخانه‌ها و برنامه‌هایی که با مای‌اس‌کیوال کار میکنن، باید با ماریا دی‌بی هم کار کنن. به همین دلیل، خیلی از توزیع‌های لینوکس مثل فدورا (Fedora)، دبیان (Debian) و رد هت (Red Hat Enterprise Linux) به جای مای‌اس‌کیوال، به صورت پیش‌فرض از ماریا دی‌بی استفاده میکنن.

    با این حال، با گذر زمان و اضافه شدن ویژگی‌های جدید، مسیر این دو پروژه داره از هم کمی جدا میشه. مثلا ماریا دی‌بی موتورهای ذخیره‌سازی جدیدی مثل Aria، ColumnStore و MyRocks رو معرفی کرده. همچنین تو نسخه‌های جدیدش، امکانات مربوط به داده‌های جغرافیایی (GIS) و JSON هم اضافه شده.

    بنیاد ماریا دی‌بی: نگهبان کد

    همونطور که گفتیم، بنیاد ماریا دی‌بی یه نهاد غیرانتفاعی هست که توی دلاور (Delaware) آمریکا ثبت شده و هدفش اینه که از آینده ماریا دی‌بی محافظت کنه. ماموریت این بنیاد روی سه تا اصل بنا شده:

    • باز بودن (Openness): تضمین میکنن که کدهای ماریا دی‌بی همیشه برای استفاده و مشارکت همه باز باقی بمونه و تصمیم‌های فنی بر اساس شایستگی گرفته بشه.
    • پذیرش (Adoption): تلاش میکنن تا استفاده از ماریا دی‌بی توسط کاربرها و در پلتفرم‌های مختلف بیشتر بشه.
    • تداوم (Continuity): مستقل از هر نهاد تجاری، تداوم اکوسیستم ماریا دی‌بی رو فراهم میکنن.

    کارمندهای این بنیاد با انجام کارهای زیر از پروژه پشتیبانی میکنن:

    • تشویق به پذیرش، مشارکت و توزیع سرور ماریا دی‌بی.
    • کمک به مشارکت‌کننده‌های جدید تا کدها رو بهتر بفهمن.
    • مشارکت در طراحی ویژگی‌های جدید و تضمین کیفیت کد.
    • اطمینان از به‌روز بودن مستندات.
    • پورت کردن و بسته‌بندی ماریا دی‌بی برای پلتفرم‌ها و سیستم‌عامل‌های مختلف.
    • صحبت در رویدادها برای افزایش آگاهی و استفاده.

    این بنیاد از طریق حامیان مالی شرکتی و فردی تامین میشه. این حامی‌ها به دسته‌های مختلفی مثل الماس، پلاتینیوم، طلا و نقره تقسیم میشن.

    حامیان مالی بنیاد ماریا دی‌بی

    اینجا لیست برخی از سازمان‌هایی که از این بنیاد حمایت مالی قابل توجهی میکنن رو میبینیم:

    • حامیان الماس (Diamond sponsors):
      • DBS: یک گروه خدمات مالی پیشرو در آسیا با بیش از ۲۸۰ شعبه در ۱۸ بازار. دفتر مرکزی اون در سنگاپور قرار داره.
    • حامیان پلاتینیوم (Platinum sponsors):
      • MariaDB Corporation: عضو موسس بنیاد و مشارکت‌کننده اصلی کد. محصولات و خدمات تجاری حول ماریا دی‌بی ارائه میده.
      • Acronis: شرکتی که حفاظت از داده و امنیت سایبری رو با هم ترکیب میکنه.
      • Alibaba Cloud: ارائه‌دهنده خدمات رایانش ابری جهانی.
      • Intel: غول فناوری و سازنده پردازنده‌ها که در پیشرفت‌های محاسباتی نقش داشته.
      • ServiceNow: پلتفرمی که به کارمندها اجازه میده اونطور که میخوان کار کنن.
      • Constructor: پلتفرمی برای آموزش و پژوهش با تخصص در هوش ماشینی و علم داده.
      • WebPros: ارائه‌دهنده اکوسیستم کامل برای توانمندسازی حرفه‌ای‌های وب.
    • حامیان طلا (Gold Sponsors):
      • Hetzner: یکی از بزرگترین شرکت‌های میزبانی وب در اروپا که در سال ۱۹۹۷ تاسیس شده.
      • IONOS: شریک دیجیتالی‌سازی برای کسب‌وکارهای کوچک و متوسط در اروپا.
      • Scarf: پیشگام در زمینه تحلیل استفاده از نرم‌افزارهای متن‌باز.
    • حامیان نقره (Silver Sponsors):
      • این لیست شامل شرکت‌های زیادی مثل ArbauDie.IT، Automattic (سازنده WordPress.com)، Crest Infosolutions، Kinsta، Nexedi، Nextcloud، RAVATAR، Releem، Rumahweb، SkySQL، team.blue، Tempesta Technologies، Tencent Cloud، Vettabase، Wikimedia movement و Cyber Leo میشه که هر کدوم در زمینه‌های مختلف فناوری فعالیت دارن.

    نحوه مدیریت و تصمیم‌گیری در پروژه

    یکی از سوال‌های مهم اینه که تصمیم‌ها توی این پروژه چطور گرفته میشه. بنیاد ماریا دی‌بی یه ساختار مدیریتی شفاف داره:

    • تصمیم‌های فنی: تصمیم‌های مربوط به مشارکت در کدها توسط خود مشارکت‌کننده‌ها گرفته میشه. اگه نیاز به اجماع عمومی باشه، موضوع در لیست‌های ایمیل عمومی ماریا دی‌بی و بقیه کانال‌های شفاف آنلاین بحث میشه تا اکثریت توسعه‌دهنده‌ها به توافق برسن. هیچ فرد یا شرکتی نمیتونه اولویت‌ها یا کد رو به جامعه دیکته کنه.
    • هیئت مدیره (Board of directors): بنیاد به صورت قانونی توسط هیئت مدیره کنترل میشه. این هیئت تصمیم میگیره که بنیاد چطور میتونه به بهترین شکل به جامعه ماریا دی‌بی خدمت کنه، اما تصمیم‌های فنی نمیگیره.

    اعضای هیئت مدیره بنیاد ماریا دی‌بی

    هیئت مدیره از افراد مختلفی تشکیل شده که هر کدوم نماینده بخش خاصی هستن. در اینجا به چند نفر از اعضای کلیدی اشاره میکنیم:

    • مدیران موسس (Ex officio):
      • Sergei Golubchik: معمار ارشد سرور ماریا دی‌بی در شرکت ماریا دی‌بی.
      • Michael “Monty” Widenius: بنیان‌گذار ماریا دی‌بی و مای‌اس‌کیوال.
    • مدیران نماینده شرکت‌ها:
      • Jignesh Shah: مدیر بخش RDS Open Source در آمازون وب سرویسز (AWS).
      • Rohit De Souza: مدیرعامل شرکت MariaDB plc.
    • مدیران فردی:
      • Kaj Arnö: رئیس اجرایی بنیاد.
      • Todd Boyd: عضو ارشد فنی در IBM.
      • Eric Herman: رئیس هیئت مدیره از سال ۲۰۱۶ تا ۲۰۲۵.
      • و افراد دیگه‌ای مثل Espen Håkonsen، Sean Peng و Steve Shaw.

    هر کدوم از این افراد سابقه طولانی در دنیای نرم‌افزار، پایگاه داده و مدیریت دارن. برای مثال، Kaj Arnö قبل از پیوستن به بنیاد، در شرکت MySQL AB و Sun Microsystems سمت‌های مختلفی داشته و یکی از بنیان‌گذارهای شرکت ماریا دی‌بی هم بوده. یا Sergei Golubchik که از سال ۱۹۹۸ توسعه‌دهنده مای‌اس‌کیوال بوده و تقریبا روی همه بخش‌های سرور کار کرده.

    نسخه‌بندی و چرخه‌های انتشار

    ماریا دی‌بی یک سیاست مشخص برای انتشار نسخه‌هاش داره. این به کاربرها کمک میکنه تا بدونن هر نسخه تا کی پشتیبانی میشه و کی باید سیستم‌هاشون رو آپدیت کنن.

    نسخه‌های با پشتیبانی بلندمدت (LTS)

    هر سال یک نسخه جدید با پشتیبانی بلندمدت یا LTS معرفی میشه. این نسخه‌ها برای مدت طولانی‌تری (معمولا ۳ تا ۵ سال) آپدیت‌های امنیتی و رفع باگ دریافت میکنن. این برای شرکت‌ها و کاربرانی که به پایداری نیاز دارن و نمیتونن هر چند ماه یکبار پایگاه داده‌شون رو آپدیت کنن، خیلی مهمه.

    برای مثال، نسخه‌هایی مثل 10.6، 10.11 و 11.4 نسخه‌های LTS هستن.

    نسخه‌های غلتان (Rolling releases)

    این نسخه‌ها به صورت فصلی (هر سه ماه) منتشر میشن و شامل آخرین ویژگی‌ها، رفع باگ‌ها و بهبودها هستن. این نسخه‌ها برای کسانی مناسبن که میخوان همیشه از جدیدترین امکانات استفاده کنن.

    شماره‌گذاری نسخه‌ها چطوریه؟

    شماره نسخه‌ها معمولا به صورت a.b.c هست. مثلا 11.4.7.

    • a (Major version): نسخه اصلی رو نشون میده (مثلا سری ۱۱). این عدد معمولا سالی یک بار زیاد میشه و ممکنه تغییرات بزرگی که با نسخه‌های قبلی ناسازگار هستن رو شامل بشه.
    • b (Minor version): نسخه فرعی رو نشون میده که امکانات جدید بهش اضافه شده ولی با نسخه‌های قبلی همون سری سازگاره. این عدد هر سه ماه زیاد میشه.
    • c (Patch version): این عدد با هر آپدیت برای رفع باگ یا مشکلات امنیتی زیاد میشه و هیچ ویژگی جدیدی بهش اضافه نمیشه.

    اینجا یه جدول از نسخه‌های مختلف و تاریخ پایان پشتیبانی اونها رو میبینید:

    نسخهتاریخ انتشار اولیهپایان پشتیبانی (Community)
    11.8۴ ژوئن ۲۰۲۵۴ ژوئن ۲۰۲۸
    11.4۲۹ می ۲۰۲۴۲۹ می ۲۰۲۹
    10.11۱۶ فوریه ۲۰۲۳۱۶ فوریه ۲۰۲۸
    10.6۶ ژوئیه ۲۰۲۱۶ ژوئیه ۲۰۲۶
    10.5۲۴ ژوئن ۲۰۲۰۲۴ ژوئن ۲۰۲۵
    10.4۱۸ ژوئن ۲۰۱۹۱۸ ژوئن ۲۰۲۴
    10.3۲۵ می ۲۰۱۸۲۵ می ۲۰۲۳

    نکته مهم: در همه آپدیت‌ها، حتی آپدیت‌های بزرگ، تیم ماریا دی‌بی تضمین میکنه که ابزار mariadb-upgrade به درستی کار میکنه و شما میتونید فایل‌های پایگاه داده رو از هر نسخه قدیمی‌تری (حتی مای‌اس‌کیوال قبل از نسخه ۸.۰) آپدیت کنید.

    چطور ماریا دی‌بی رو نصب و استفاده کنیم؟

    ماریا دی‌بی یکی از محبوب‌ترین پایگاه داده‌های رابطه‌ای متن‌بازه و توی مخازن استاندارد همه توزیع‌های اصلی لینوکس پیدا میشه. کافیه با استفاده از مدیر بسته سیستم‌عاملتون دنبال بسته mariadb-server بگردید و نصبش کنید.

    اما گاهی اوقات ممکنه به مشکلاتی بربخورید. بیاید چند تا از مشکلات رایجی که کاربرها باهاش مواجه شدن رو بررسی کنیم.

    مشکل ۱: چرا نصب KDE باعث نصب ماریا دی‌بی میشه؟

    یه کاربر در ردیت (Reddit) سوال جالبی پرسیده بود. اون میخواست روی سیستم عامل فدورا که فقط محیط دسکتاپ گنوم (GNOME) داشت، محیط کی‌دی‌ای (KDE Plasma Workspaces) رو هم نصب کنه. وقتی دستور نصب رو زد، متوجه شد که mariadb-server هم به عنوان یکی از بسته‌های مورد نیاز (dependency) داره نصب میشه.

    این براش عجیب بود که چرا یه محیط دسکتاپ باید به یه سیستم مدیریت پایگاه داده کامل وابسته باشه. این موضوع نشون میده که گاهی اوقات وابستگی‌های بین بسته‌ها در سیستم‌عامل‌های لینوکس میتونه پیچیده و غیرمنتظره باشه. در این مورد خاص، احتمالا یکی از برنامه‌های زیرمجموعه کی‌دی‌ای برای مدیریت اطلاعاتش از یک پایگاه داده محلی استفاده میکنه و توسعه‌دهنده‌ها ماریا دی‌بی رو به عنوان گزینه پیش‌فرض انتخاب کردن.

    مشکل ۲: رمز عبور پیش‌فرض ماریا دی‌بی در فدورا چیه؟

    این یکی از سوال‌های خیلی پرتکرار در سایت Stack Overflow هست. یه کاربر میگه که ماریا دی‌بی رو روی فدورا نصب کرده ولی ازش رمز عبور روت (root) پرسیده نشده. هر رمزی رو هم که امتحان کرده، جواب نداده.

    جواب اینه: رمز عبور پیش‌فرض خالیه!

    اما قضیه به همین سادگی نیست. در نسخه‌های جدید ماریا دی‌بی روی لینوکس، برای بالا بردن امنیت، به صورت پیش‌فرض از یه پلاگین احراز هویت به اسم unix_socket استفاده میشه. این پلاگین میگه: «اگه کاربری که داره سعی میکنه به عنوان root وارد پایگاه داده بشه، همون کاربر root سیستم‌عامل باشه، دیگه نیازی به رمز عبور نیست.»

    پس برای اینکه به عنوان کاربر root وارد ماریا دی‌بی بشید، باید خود دستور رو هم با دسترسی root اجرا کنید. به این صورت:

    sudo mysql

    با این دستور، بدون نیاز به رمز عبور وارد محیط ماریا دی‌بی میشید.

    اگه بخواید یه رمز عبور برای کاربر root تنظیم کنید تا از راه‌های دیگه هم بشه بهش وصل شد، باید از اسکریپت mysql_secure_installation استفاده کنید. این اسکریپت هم باید با sudo اجرا بشه:

    sudo mysql_secure_installation

    این اسکریپت از شما چند تا سوال امنیتی میپرسه، مثل تنظیم رمز عبور روت، حذف کاربرهای ناشناس، غیرفعال کردن ورود روت از راه دور و حذف پایگاه داده تستی. در مرحله اول که رمز عبور فعلی رو میپرسه، چون خالیه، فقط کافیه کلید Enter رو بزنید.

    مشکل ۳: خطای عدم نصب به خاطر وابستگی‌ها

    گاهی اوقات موقع نصب، ممکنه با خطای unmet dependencies مواجه بشید. یه کاربر در Stack Overflow گزارش داده بود که موقع نصب mariadb-server روی اوبونتو ۱۲.۰۴، با این خطا مواجه شده که بسته mariadb-server-5.5 نصب نمیشه. مشکل از اینجا بود که یه نسخه از کتابخانه libmysqlclient18 روی سیستمش نصب بود که با نسخه‌ای که ماریا دی‌بی نیاز داشت، تداخل داشت.

    اینجور مشکلات معمولا وقتی پیش میاد که شما از مخازن نرم‌افزاری مختلفی استفاده میکنید و نسخه‌های بسته‌ها با هم هماهنگ نیستن. این یه نمونه خوبه که نشون میده مدیریت بسته‌ها و وابستگی‌هاشون چقدر میتونه حساس باشه.

    شرکت ماریا دی‌بی و نسخه تجاری

    همونطور که گفتیم، علاوه بر بنیاد، یه شرکت تجاری هم به اسم MariaDB Corporation وجود داره. این شرکت در سال ۲۰۱۰ توسط تعدادی از بنیان‌گذاران اصلی پروژه تاسیس شد تا بتونه کسب‌وکاری حول این نرم‌افزار متن‌باز بسازه.

    این شرکت یه پلتفرم به اسم MariaDB Enterprise Platform ارائه میده که برای استفاده‌های تجاری و حساس طراحی شده. این پلتفرم شامل موارد زیره:

    • MariaDB Enterprise Server: یه نسخه تقویت‌شده، امن و پایدار از سرور کامیونیتی.
    • MariaDB MaxScale: یک پروکسی پایگاه داده پیشرفته که برای افزایش دسترسی‌پذیری (high availability)، مقیاس‌پذیری و امنیت استفاده میشه.
    • MariaDB Xpand: یک موتور ذخیره‌سازی توزیع‌شده برای مقیاس‌پذیری بسیار بالای بارهای کاری تراکنشی.
    • MariaDB ColumnStore: یک موتور ذخیره‌سازی ستونی برای تحلیل داده‌های حجیم به صورت تعاملی.

    این شرکت ادعا میکنه که ۷۵ درصد از شرکت‌های لیست Fortune 500 از ماریا دی‌بی استفاده میکنن و مهاجرت از پایگاه داده‌های انحصاری به ماریا دی‌بی میتونه تا ۹۰ درصد در هزینه‌ها صرفه‌جویی کنه. یکی از مشتری‌های بزرگشون بانک DBS هست که ۵۴ درصد از برنامه‌های بانکی حیاتی خودش رو به ماریا دی‌بی منتقل کرده.

    در فوریه ۲۰۲۲، این شرکت اعلام کرد که قصد داره از طریق ترکیب با یک شرکت دیگه، وارد بورس نیویورک (NYSE) بشه.

    پلاگین بازخورد کاربر (User Feedback Plugin)

    از اکتبر ۲۰۱۱، ماریا دی‌بی یه پلاگین به اسم «بازخورد کاربر» رو معرفی کرد. این پلاگین به صورت پیش‌فرض غیرفعاله، اما اگه فعالش کنید، به صورت دوره‌ای یه سری اطلاعات مربوط به پیکربندی و نحوه استفاده از ماریا دی‌بی رو به سایت mariadb.org میفرسته.

    هدف از این کار چیه؟
    هدف اصلی اینه که به تیم توسعه کمک کنه تا مسیر مهندسی و توسعه جامعه رو در جهت درستی هدایت کنن. این اطلاعات بهشون نشون میده که:

    • ماریا دی‌بی روی چه پلتفرم‌ها و سخت‌افزارهایی اجرا میشه.
    • توزیع جهانی کاربرها چطوریه.
    • چه نسخه‌هایی از ماریا دی‌بی بیشتر استفاده میشن.
    • کدوم ویژگی‌ها محبوب‌تر هستن.

    چه اطلاعاتی جمع‌آوری میشه؟
    این پلاگین فقط اطلاعات غیرحساس رو جمع میکنه. مثل:

    • نوع و سرعت پردازنده و تعداد هسته‌ها.
    • اطلاعات سیستم‌عامل و توزیع.
    • لیست موتورهای ذخیره‌سازی و پلاگین‌های در حال استفاده.

    خیالتون راحت باشه! این پلاگین هیچ‌وقت اطلاعات شخصی یا حساس مثل نام کاربری، اسم پایگاه داده‌ها، محتوای جداول یا هر چیزی که بشه باهاش کاربر رو ردیابی کرد، ارسال نمیکنه.

    یک سوال مهم در معماری: پایگاه داده متمرکز یا غیرمتمرکز؟

    یه مدیر سیستم تازه‌کار سوال خوبی در ردیت پرسیده بود: «آیا بهترین کار اینه که همه پایگاه داده‌های MySQL/MariaDB رو روی یک سرور متمرکز کنیم؟»

    اون توضیح داده بود که برای هر سرویس وبی که راه میندازه (مثل Nextcloud)، یه ماشین مجازی جدید میسازه و روی همون ماشین یه سرور مای‌اس‌کیوال هم نصب میکنه. حالا به این فکر افتاده که آیا بهتر نیست یه ماشین مجازی جدا فقط برای پایگاه داده داشته باشه و بقیه سرویس‌ها از طریق شبکه به اون وصل بشن؟

    این یه سوال معماری خیلی مهمه. جواب کوتاهی که بقیه کاربرها بهش دادن این بود: «نه، این لزوما بهترین راه نیست.»

    دلایل مختلفی برای این جواب وجود داره:

    • نقطه شکست واحد (Single Point of Failure): اگه اون سرور پایگاه داده مرکزی به هر دلیلی از کار بیفته، تمام سرویس‌های شما با هم از کار میفتن.
    • تداخل منابع: سرویس‌های مختلف ممکنه نیازهای متفاوتی به پایگاه داده داشته باشن. یه سرویس ممکنه فشار زیادی به دیسک بیاره، یکی دیگه به پردازنده. وقتی همه روی یه سرور باشن، ممکنه برای منابع با هم رقابت کنن و عملکرد هم رو مختل کنن.
    • امنیت و ایزوله‌سازی: وقتی هر سرویس پایگاه داده خودش رو داره، اگه یکی از سرویس‌ها هک بشه، فقط داده‌های همون سرویس در خطره. اما در مدل متمرکز، ممکنه نفوذ به یک پایگاه داده راه رو برای دسترسی به بقیه داده‌ها هم باز کنه.

    البته مدل متمرکز مزایایی مثل مدیریت راحت‌تر و کاهش هزینه‌های نگهداری هم داره. در نهایت، انتخاب بین این دو مدل بستگی به اندازه، حساسیت و نیازهای هر پروژه داره.

    پرسش و پاسخ نهایی

    حالا که با کلیات ماریا دی‌بی آشنا شدیم، بیاید چند تا سوال کلیدی رو مرور کنیم تا مطمئن بشیم همه چیز خوب جا افتاده.

    سوال ۱: فرق اصلی بین بنیاد ماریا دی‌بی و شرکت ماریا دی‌بی چیه؟
    جواب: بنیاد ماریا دی‌بی یک سازمان غیرانتفاعی هست که وظیفه‌اش حفاظت از ماهیت متن‌باز و رایگان پروژه و مدیریت جامعه توسعه‌دهنده‌هاست. اما شرکت ماریا دی‌بی یک نهاد تجاری هست که محصولات و خدمات پولی مثل پشتیبانی تخصصی و نسخه‌های تجاری با امکانات بیشتر رو بر پایه ماریا دی‌بی ارائه میده.

    سوال ۲: آیا ماریا دی‌بی فقط یه کپی از مای‌اس‌کیواله؟
    جواب: نه. ماریا دی‌بی به عنوان یک «فورک» از مای‌اس‌کیوال شروع شد و هدفش سازگاری بالا با اون بود. اما در طول زمان، ویژگی‌ها، بهینه‌سازی‌ها و موتورهای ذخیره‌سازی جدیدی بهش اضافه شده که در مای‌اس‌کیوال وجود نداره. پس در حالی که ریشه مشترکی دارن، الان دو پروژه جدا با مسیر توسعه متفاوت هستن.

    سوال ۳: چرا میگن ماریا دی‌بی یه جایگزین «drop-in» برای مای‌اس‌کیواله؟
    جواب: چون API و پروتکل‌هاش با مای‌اس‌کیوال سازگاره. این یعنی شما میتونید سرور مای‌اس‌کیوال رو با سرور ماریا دی‌بی جایگزین کنید و برنامه‌های شما (مثل سایت وردپرسی یا هر برنامه دیگه‌ای که به پایگاه داده وصل میشه) باید بدون هیچ تغییری به کارشون ادامه بدن.

    سوال ۴: آیا برای استفاده از سرور ماریا دی‌بی باید پول بدم؟
    جواب: نه. سرور ماریا دی‌بی (MariaDB Community Server) تحت لایسنس GNU General Public License نسخه ۲ (GPLv2) منتشر میشه که یعنی کاملا رایگان و متن‌بازه. شما میتونید آزادانه اون رو دانلود، نصب، استفاده و تغییر بدید. نسخه‌های پولی مربوط به پلتفرم تجاری شرکت ماریا دی‌بی هست که امکانات اضافی و پشتیبانی ارائه میده.

    سوال ۵: چرا روی سیستم من وقتی ماریا دی‌بی رو نصب کردم، رمز عبور روت نداشت؟
    جواب: در بسیاری از توزیع‌های لینوکس، ماریا دی‌بی به صورت پیش‌فرض از پلاگین احراز هویت unix_socket استفاده میکنه. این پلاگین به کاربر root سیستم‌عامل اجازه میده بدون نیاز به رمز عبور به عنوان کاربر root پایگاه داده وارد بشه. برای این کار باید از دستور sudo mysql استفاده کنید. این یک اقدام امنیتیه تا جلوی حملات به رمز عبور روت از طریق شبکه گرفته بشه.

    منابع

    • [2] Why does installing KDE plasma workspaces install mariadb server? : r/Fedora
    • [4] ubuntu – Installing MariaDB – Unmet dependencies, mariadb-server-5.5 – Stack Overflow
    • [6] Is centralizing MySQL/mariadb databases on one server best-practice ? : r/sysadmin
    • [8] mysql – What’s the default password of mariadb on fedora? – Stack Overflow
    • [10] MariaDB – Wikipedia
    • [1] MariaDB Foundation – MariaDB.org
    • [3] MariaDB Enterprise Open Source Database | MariaDB
    • [5] Download MariaDB Server – MariaDB.org
    • [7] GitHub – MariaDB/server: MariaDB server is a community developed fork of MySQL server. Started by core members of the original MySQL team, MariaDB actively works with outside developers to deliver the most featureful, stable, and sanely licensed open SQL server in the industry.
    • [9] About MariaDB Server – MariaDB.org