گیک فارسی

نوشته های یک گیک فارسی از فعالیت ها ،‌ علاقه مندی ها و نقد هایش

خطای عدم دسترسی به کاربر root در نسخه های جدید mariadb

نویسنده:
31 می 17

اگه هنوز به جای استفاده از MariaDB دارین از MySQL استفاده میکنید باید بگم خیلی در اشتباه هستین و بهتره خیلی زود به فکر مهاجرت باشین که البته این مهاجرت اصلاً سخت نیست و سازگاری خوبی بین MySQL و MariaDB وجود داره.

اخیراً بعد از نصب MariaDB روی یک سرور توی مراحل نصب پرسشی مبنی بر انتخاب گذرواژه برای root نکرد و بعد از نصب هم وقتی میخواستم با دستور mysql -u root -p ارتباط با سرور برقرار کنم خطای عدم دسترسی کاربر root میداد.

اول فکر کردم شاید گذرواژه ست نشده و با روش‌ skip-grant-tables– وارد شدم و گذرواژه را توی جدول user پایگاه mysql ست کردم اما بعد از اتمام کار متوجه شدم خیر باز هم اجازه برقراری ارتباط نمیده. خیلی شانسی متوجه شدم داره بی دردسر اجازه میده با sudo و بدون گذرواژه ارتباط برقرار کنم که با کمی جستجو متوجه شدم MariaDB داره به صورت پیش‌فرض برای کاربر root از unix_socket plugin استفاده میکنه و این plugin اجازه دسترسی از طریق socket را به کاربر متناظر سیستم میده.

خوب ایده جالبی بود چون کلاً توی محیط های production بهتره ارتباط با root برقرار نباشه و این پلاگین خیلی هم در تأمین امنیت کاربردی هست ولی اگه ارتباط از طریق root خیلی مهمه میتونید با ساختن یک کاربر دیگه مثلاً admin و دادن دسترسی های root بهش از برنامه‌های دیگه ارتباط بزنید. دوستانی هم که ترجیح میدن مثل گذشته کاربر root گذرواژه بگیره کافیه Query زیر را بزنن :

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your password'

پشتیبان گیری (Backup) از پایگاه داده MySQL و MariaDB

نویسنده:
16 ژانویه 17

برنامه نویس هایی که با پشتوانه ویندوزی و استفاده از MSSQL به لینوکس و PHP و پایگاه داده محبوب این محیط یعنی MySQL مهاجرت میکنن یا میخوان توی پروژه ای ازش استفاده کنند در زمان انتقال پروژه به سیستم دیگه ، روی وب یا کلاً زمان پشتیبان گیری سعی میکنند مثل MSSQL که یک فایل Database و Log داره و با کپی گرفتن ازش همه چیز حله با MySQL برخورد کنند و با کپی گرفتن از پوشه MySQL و جداول مربوطه خودشون را خلاص میکنند.

اما وقتی زمان بارگزاری مجدد و Restore کردن پروژه میشه تازه متوجه میشن یا اطلاعاتی را کپی نگرفتند یا MySQL فایل‌های پشتیبان را تشخیص نمیده و حواسشون به اینکه MyISAM بوده یا InnoDB نداشتند و حسابی گیر میوفتن.

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

mysqldump -e -R -h [Remote host or 127.0.0.1 or localhost] -u [Your username] --password=[Your password] [Database name] > [Filename to save backup]

توی ویندوز اسمش mysqldump.exe میشه البته. (امیدوارم تا حالا مهاجرت کرده باشین به لینوکس!)

برای بارگزاری مجدد یا Restore هم از دستورخود mysql استفاده کنید (mysql.exe ویندوز):

mysql -h [Remote host or 127.0.0.1 or localhost] -u [Your username] --password=[Your password] --default-character-set=utf8 --database=[Database name] < [Filename to load backup data]

این روش مزایای زیادی داره از جمله اینکه میتونید از پایگاه داده‌های Remote هم پشتیبان بگیرین و Restore کنین یا با یک Cronjob به صورت هفتگی از پایگاه های داده محلی یا Remote (روی وب) پشتیبان بگیرین و …

مشکل در نمایش اطلاعات فارسی به صورت علامت سوال از پایگاه داده MySQL در PHP

نویسنده:
6 سپتامبر 16

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

مشکل نمایش متون فارسی به صورت علامت سوال

از اونجا که غالباً هر کسی در بخشی از پروسه انجام کار مشکل داره من به ترتیب مراحل اطمینان از درستی انجام کار را در چند شماره توضیح میدم :

۱ – زمانی که پایگاه داده را روی سیستم خودتون نصب میکنید اطمینان حاصل کنید که در مراحل نصب ، پشتیبانی از utf8 را در تنظیمات mysql انجام میدین. روی هاست ها میشه ۹۹ درصد مطمئن بود که از utf8 روی mysql پشتیبانی میشه.

۲ – زمانی که جدول را ایجاد میکنید بهتره برای جلوگیری از مشکلات آتی و فارغ از اینکه Charset پیش‌فرض و Colltation پیش‌فرض در زمان نصب MySQL چی بوده خودتون جداول را با Charset از نوع utf8 و Collation از نوع utf8_persian_ci ایجاد کنید.

توجه: اگه این دو مورد خیلی براتون ملموس نیست اهمیتی نداره ! اگه توی phpmyadmin یا هر برنامه مدیریت پایگاه داده‌ای که استفاده میکنید میتونید فارسی بنویسین و ذخیره کنین و نمایش بگیرین پس کلاً با utf8 مشکل ندارین مگه جاهای خاص که ربطی به موضوع این پست نداره و اگه مشکل دارین با پشتیبانی شرکت میزبان وب خودتون تماس بگیرین.

۳ – حتماً اطمینان حاصل کنید که charset صفحه html را توی تگ meta برابر با utf8 قرار بدین :
در html4 و xhtml

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

در html5

<meta charset="UTF-8">

۴ – اگه از کتابخونه mysql توی php استفاده میکنید حتماً بعد از mysql_connect (دقیقاً بعدش نه اینکه بعد از select گرفتن این کار را انجام بدین !!!) mysql_set_charset را اجرا کنین :

$link = mysql_connect("server_ip_address","mysql_user_name","mysql_pass",true);
mysql_set_charset('utf8',$link);

توجه: ممکنه خیلی جاها ببینید گفته باشن این دو query را بعد از connect اجرا کنین :

mysql_query("SET NAMES 'utf8'",$link);
mysql_query("SET character_set_connection = 'utf8'",$link);

اما تابع mysql_set_charset بهتر و بهینه تره چون باعث میشه زمان استفاده از تابع mysql_real_escape_string که برای جلوگیری از حملات SQL Injection خیلی مهم هست کاراکتر های یونیکد به درستی escape بشن که در حالت پیشنهادی دوم این اتفاق نمیفته و شما در مقابل برخی حملات SQL Injection در خطر قرار میگیرین !

۵ – اگه از کتابخونه mysqli استفاده میکنید بعد از connect متد set_charset را صدا بزنید :

$db = new mysqli('server_ip_address', 'db-user', 'db-pass', 'db-name');
$db->set_charset("utf8");

۶ – اگه از کتابخونه pdo استفاده میکنید زمان connect باید charset را توی dsn مشخص کنید:

$link = new PDO("mysql:host=localhost;dbname=DB;charset=utf8");

توجه: کلاً بهتره کتابخونه mysql را بی‌خیال بشین چون دیگه توی نسخه های جدید php پشتیبانی نمیشه و کلاً حذف شده. اما در مورد mysqli و pdo خیلی سلیقه‌ای هست که توصیه میکنم اگه از mysql استفاده میکنید و قصد جایگزینیش با mssql و پایگاه های دیگه را ندارید حتماً از mysqli استفاده کنید چون سریعتر از PDO هست و برای پایگاه داده mysql بهینه شده.

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>نمایش محتوای جدول</title>
<style>
  body{
      font-family:tahoma;
      font-size:12px;
  }
</style>
</head>

<body>
<?php
  $db = new mysqli('localhost', 'db-user', 'db-pass', 'db-name');
  if($db->connect_errno > 0){
      die('خطا در زمان اتصال به پایگاه داده [' . $db->connect_error . ']');
  }else{
      $db->set_charset("utf8");
      $result = $db->query("select * from tbl_names");
      echo "<table border='1' style='direction:rtl'>";
      echo "<tr style='font-weight:bold;background-color:#ccc'>";
      echo "<td>نام</td>";
      echo "<td>نام خانوادگی</td>";
      echo "<td>کد ملی</td>";
      echo "</tr>";
      while($row = $result->fetch_assoc()){
        echo "<tr>";
        echo "<td>{$row['fld_name']}</td>";
        echo "<td>{$row['fld_family']}</td>";
        echo "<td>{$row['fld_idnumber']}</td>";
        echo "</tr>";
      }
      echo "</table>";
      $result->free();
      $db->close();
  }
?>
</body>

</html>

موفق باشین.

حل دو مشکلی که در زمان ساخت یک Procedure یا Function در MySQL معمولاً پیش میاد

نویسنده:
27 مارس 15

نمیدونم شما از Function ها ، Procedure ها یا حتی Trigger ها در MySQL استفاده میکنید یا نه و الان هم نمیخوام از بهینه سازی هایی که میشه از طریق اون ها به وجود آورد بگم. توی انجمن‌ها و در میان دوستان بارها دیدم که یکی از دلایلشون این هست که وقتی خروجی SQL میگیرن از روال یا تابعی که در MySQL ساختند و میخوان اون را توی PHPMyAdmin روی هاست اجرا کنند به خطاهایی بر میخورن که فکر میکنن دسترسی ایجاد روال یا تابع را ندارند یا کلاً با خطای غیر سر راستی مثل خطای ۱۰۶۴ مواجه میشن که برای هر نوع خطای Syntax یا مثلاً استفاده از Reserved Words میتونه باشه.

زمانی که از PHPMyAdmin یا MySQL Dump یا هر برنامه دیگه ای مثل Navicat خروجی میگیرین برای یک روال یا تابع ، توی جمله تعریفش از Definer استفاده کرده و این تعریف Definer دردسر سازه. به طور کلی کاربر برای اینکه بتونه Definer یک تابع یا روال یا … را کاربر دیگه ای قرار بده نیاز به Super Privilege داره.

حالا مشکل اینجاست که Definer ی که روی سیستم شما از MySQL خروجی گرفته میشه قائدتا (مگر اینکه نام کاربری روی سیستم شما و سرور یکی باشه ، مثلاً root که روی میزبانی های Shared احتمالش نزدیک به صفره) یکی نیستند و چون کاربری که شما برای MySQL از طریق CPanel میسازین دسترسی Super Privilege نداره خطای زیر صادر میشه :

SQL Error 1227: Access denied; you need the SUPER privilege for this operation

برای حل این مشکل کافیه Definer را از جمله Create حذف کنید یا نام کاربر سرور را با نامی که خروجی تولید کرده عوض کنید.

یکی دیگه از مشکلاتی که خیلی دیدم این هست که بعد از اجرا کردن Query مربوط به ساخت روال یا تابع خطای زیر را دریافت میکنند :

#۱۰۶۴ - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line N

این خطا مربوط میشه به بحث Delimiter ، همونطور که میدونین توی SQL وقتی میخواین چند تا دستور را پشت سر هم بفرستین به MySQL آخر هر دستور Semicolon میگذارین. حالا مشکلی که در زمان تعریف روال و تابع در MySQL وجود داره این هست که Semicolon هایی که بعد از Create یا Begin قرار میگیرن باعث میشن که تعریف کل تابع یا روال شکسته بشه و MySQL فکر کنه جمله Create کامل نیست.

راه حل خیلی ساده هستش ، کافیه در زمان اجرای Query به MySQL بگیم که از یک Delimiter غیر از Semicolon استفاده کنه. به این شکل :

delimiter $$
create procedure myProc()
begin 
SELECT * FROM table;
end;
$$
delimiter ;

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

مهاجرت به لینوکس | نصب و راه اندازی سرویس های مورد نیاز یا همون LAMP

نویسنده:
10 ژوئن 14

پیرو نوشته‌ای که با عنوان «مهاجرت به لینوکس | اوبونتو در کنار ویندوز» منتشر کردم. در چهارمین مرحله و پس از نصب سیستم عامل حالا نوبت میرسه به اینکه سرویس های مورد نیاز یک برنامه نویس وب را نصب کنیم. این سرویس ها شامل سرویس دهنده وب یعنی Apache ، زبان برنامه نویسی سمت وب یعنی PHP و پایگاه داده MySQL می‌شود که روش نصب هر کدام را توضیح می دهم.

قبل از شروع به نصب سرویس های مورد نیاز باز هم یاد آوری می‌کنم که بهتره ابتدا در مورد سیستم عامل جدید یعنی Ubuntu Linux آشنایی متوسطی پیدا کنید تا بتونین دستورات را اجرا کنین و فایل‌های تنظیمات را ویرایش و کار های مرتبط را انجام بدین. بهتره عجله نکنید و چند هفته‌ای را برای یادگیری سیستم عامل جدید وقت بگذارید. همیشه میتونین سؤالات خودتون را توی انجمن فارسی کاربران اوبونتو بپرسین تا دوستان من و شاید خود من در اون انجمن شما را راهنمایی کنن.

Apache
توی لینوکس سرویس دهنده های زیادی هست که میشه نصب کرد ولی من Apache را ترجیح میدم و نصب و راه اندازی Apache را توضیح میدم. برای نصب Apache توی Ubuntu و پس از زدن Ctrl + Alt + T و نمایان شدن ترمینال میزنیم :

sudo apt-get install apache2

ممکنه در زمان نصب یک Wizard ازتون سؤالاتی در مورد domain یا port یا هر تنظیماتی بپرسه که میتونید مقادیر پیش‌فرض را قبول کنین و یا اگه میدونین دارین چیکار میکنین اونها را مطابق خواسته خودتون تغییر بدین. بعد از نصب Apache اگه توی آدرس مرورگر خودتون (ترجیحاً Firefox ;)) بزنین http://localhost صفحه پیش‌فرض Apache را مشاهده میکنین که نوشته !It Works. مسیر پیش‌فرض Apache برای این وب سایت هم var/www/ هستش و میتونین فایل‌های html یا php و … را توی این پوشه بریزین دقیقاً مثل زمانی که فایل‌ها را از طریق FTP به وب سایت منتقل میکنین.

توجه : Apache نرم‌افزار بسیار قدرتمندی هستش و تنظیمات و امکانات بسیاری داره ، توی این پست مجال توضیح نیست و من به مرور زمان مطالب مرتبط با Apache مثل نحوه ساخت Virtual Host ،‌ تنظیمات مربوط به پیکربندی و … را توی پست های جداگانه خواهم نوشت.

PHP
پس از نصب Apache حالا باید PHP را نصب کنیم و این کار را با دستور زیر انجام میدیم :

sudo apt-get install php5 php5-mysql

بعد از نصب بر خلاف ویندوز که باید Apache را برای استفاده از PHP تنظیم میکردیم نیازی به هیچ تنظیماتی نیست و فقط کافیه سرویس Apache را با دستور زیر Reset کنید :

sudo service apache2 raload

حالا اگه یک فایل php در مسیر var/www/ بسازین و توش بنویسین ;()phpinfo و به نام phpinfo.php ذخیرش کنید و به آدرس http://localhost/phpinfo.php برین میتونید تمام تنظیمات و اطلاعات مرتبط با php را ببینین و مطمئن بشین همه چیز درست کار میکنه. آدرس فایل php.ini بارگزاری شده را هم میتونید ببینید و اگه نیاز هست تغییرات لازم را توش اعمال کنید. (فقط یادتون نره باید apache را rest کنید)

توجه : php دارای extension های زیادی هست مثل gd یا mcrypt یا pdo ،‌ ما در زمان نصب php5-mysql که یک extension برای ارتباط از طریق php با mysql هست را نصب کردیم. شما میتونید extension های دیگری را بر اساس نیازتون نصب کنین. برای پیدا کردن extension مورد نظر توی repo ها از دستور زیر استفاده کنید :

sudo apt-cache search php5-

MySQL
برای نصب پایگاه داده MySQL از دستور زیر استفاده میکنیم :

sudo apt-get install mysql-server

در فرآیند نصب ، گذرواژه ای که برای root در نظر میگیرین را حتماً به خاطر بسپارید تا در زمان استفاده مشکلی براتون پیش نیاد.

خوب بالاخره ما LAMP یا همون Linux, Apache, MySQL, PHP را نصب کردیم و میتونیم شروع به برنامه نویسی تحت وب کنیم. در پست بعدی مهاجرت به لینوکس ، به معرفی نرم‌افزار های جایگزین و مورد نیاز در برنامه نویسی وب و توسعه وب سایت‌ها می پردازم.

وارد سازی اطلاعات از پایگاه های دیگر (MSSQL , Excel – XLS- XLSX , …) به MySQL

نویسنده:
29 می 14

قطعا یکی از مشکلاتی که برنامه نویسان زیاد با اون روبرو می‌شوند انتقال اطلاعات از یک پایگاه اطلاعاتی به پایگاه دیگر مخصوصاً با نوع متفاوت است. مثلاً اطلاعات را از MSSQL به MySQL انتقال دهیم. یا از یک فایل Microsoft Access یا حالا هر پایگاه اطلاعاتی فایلی یا Relational. معمولاً این کار را با ابزار های رایگان مانند MySQL Workbench یا پولی مانند Navicat انجام میدهند.

اما گاهی پیش میاد که امکان انتقال مستقیم وجود نداره. در این حالت بهترین راه خروجی گرفتن اطلاعات در یک مرحله به CSV و یا در دو مرحله به Xls یا Xlsx یا Ods و سپس به CSV.

زمانی که فایل CSV نهایی را داشته باشیم با خود دستورات SQL ، واردسازی به راحتی انجام پذیره. کافیه با دستور زیر به MySQL Server وصل بشیم :

mysql -u [username] --password=[password] --database=[database] –local-infile=TRUE

بعدش با دستور زیر محتویات فایل را داخل جدول مورد نظر میریزیم :

LOAD DATA LOCAL INFILE '/home/geekfarsi/file.csv' INTO TABLE [tablename] FIELDS TERMINATED BY ';' ENCLOSED BY '"' LINES TERMINATED BY '\n' (field1, field2);

نکته : در ویندوز آدرس دهی اینطوری انجام میشه :

c:\\path\\to\\csvfile.csv

نکته : در ویندوز به جای n\ ازr\n\ استفاده میکنیم.

نکته : در صورتی که محتویات داخل فایل CSV فرمت utf-8 دارند قبل از دستور واردسازی از دستورات زیر استفاده کنید :

SET NAMES 'utf8'
SET character_set_connection = 'utf8'

خطای عجیب MySQL در زمان صدا زدن Stored Procedure

نویسنده:
12 مارس 14

من توی اکثر سرویس های Reseller که داشتم تعریف Stored Procedure ها معضل بوده و معمولاً دسترسی ایجاد نمیدهند یا باید در زمان تعریف ، Definer و تنظیمات دیگر Create Syntax را درست تنظیم کنید.

اما امروز با خطای عجیبی مواجه شدم که توضیحاتی را میدم شاید که راهگشای شخص دیگه ای باشه. خطا توی Log مربوط به php در زمان اجرای Stored Procedure این بود :

This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

خوب از خطا مشخصه اما توضیحش این هست که میگه چون Binary Logging را فعال کردین باید برای هر Procedure در زمان ایجاد تعیین کنین که آیا تغییری در Data های پایگاه میده (برای Rollback و این داستان‌ها مهم هستش) یا اصلاً SQL توش داره یا فقط دارین اطلاعات را با Select میخونین.

بعدش هم میگه میتونین با وجود امنیت پایینی که داره متغیر log_bin_trust_function_creators را استفاده کنین. که منظورش این هست که مقدارش را برابر ۱ بگذاریم تا این خطا را نگیریم.

در مورد مشکل من با توجه به اینکه من Reseller بودم یک Ticket زدم و چون زمان Up Time مربوط به MySQL را چک کرده بودم و گویا این‌ها سرویس MySQL را بروزرسانی کرده بودن و با این عدله که تا قبل از بروزرسانی همه چیز ok بوده. لطفاً اون متغیر را مقدارش را ۱ کنین که من دسترسی ندارم. دوستان خارجکی هم انجام دادند و مشکل من حل شد.

نکته : البته بهتر بود دسترسی کار با Stored Procedure ها را فعال میکردن و میگفتن برین مقادیر مورد نظر را برای هر Procedure تعیین کنید (No SQL یا READS SQL DATA).