Сайтни бошқа хостингга кўчириш ёки захира нусхадан тиклаш пайтида энг кўп учрайдиган тўсиқ катта MySQL базани импорт қилишдир. Бир неча мегабайтли база phpMyAdmin орқали бир зумда юкланади, аммо ҳажм юзлаб мегабайт ёки бир неча гигабайтга етганда жараён ярим йўлда узилиб қолади. Браузер ойнаси оқ саҳифа кўрсатади, phpMyAdmin вақт тугагани ҳақида хабар беради ёки MySQL уланишни ўзи узиб қўяди. Бу мақолада шундай хатоларнинг сабабини ва катта базани хатосиз импорт қилишнинг амалий усулларини кўриб чиқамиз.
Нега катта дамп phpMyAdmin орқали юкланмайди
phpMyAdmin оддий PHP иловаси, шунинг учун у PHP созламалари билан чекланган. Файлни юклаш учун upload_max_filesize ва post_max_size қийматлари дамп ҳажмидан катта бўлиши керак, акс ҳолда файл серверга умуман етиб бормайди. Файл етиб борган тақдирда ҳам скрипт max_execution_time билан белгиланган вақтдан ортиқ ишлай олмайди, кўп гигабайтли базани эса бир неча дақиқада импорт қилиб бўлмайди. Бундан ташқари, веб-сервер ва прокси ҳам ўз кутиш лимитларига эга, шу сабаб браузер 504 Gateway Timeout хатосини кўрсатиши мумкин, орқада эса импорт ярим ҳолатда тўхтаб қолади.
Ярим импорт қилинган база хавфли ҳолат ҳисобланади. Баъзи жадваллар тўлиқ, баъзилари бўш ёки чала бўлади, сайт эса очиқ хато бермасдан нотўғри ишлаши мумкин. Шунинг учун импорт узилган бўлса, қолган қисмини "юклаб қўйишга" уринмасдан, базани тозалаб, жараённи бошидан қайта бошлаш тўғрироқ бўлади.
max_allowed_packet хатоси нимани билдиради
Иккинчи кенг тарқалган муаммо MySQL сервернинг ўзида юзага келади. max_allowed_packet параметри сервер бир марта қабул қила оладиган энг катта пакет ёки сўров ҳажмини белгилайди. mysqldump одатда кўп қаторни битта узун INSERT буйруғига бирлаштиради, расм ёки катта матн сақланган BLOB ва LONGTEXT устунлари бўлса, битта қатор ҳам бир неча мегабайтга етади. Агар шундай сўров лимитдан катта бўлса, қуйидаги хатолардан бири чиқади:
ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes
ERROR 2006 (HY000): MySQL server has gone away
Иккинчи хабар бошқа сабабларга ҳам боғлиқ бўлиши мумкин, масалан, уланиш узоқ вақт бўш туриб узилганда. Лекин импорт пайтида, айниқса катта жадвалга келганда чиқса, биринчи навбатда пакет лимитини текшириш керак. Мижоз томонида лимитни буйруқ сатрида оширса бўлади, сервер томонидаги глобал қийматни эса shared хостингда фойдаланувчи ўзи ўзгартира олмайди, бунинг учун хостинг техник ёрдамига мурожаат қилинади.
Энг ишончли усул: SSH ва mysql буйруғи
Агар хостингингизда SSH кириш ёқилган бўлса, катта базани буйруқ сатри орқали импорт қилиш энг барқарор йўлдир. Бу ҳолатда PHP лимитлари ва браузер кутиш вақти умуман иштирок этмайди, жараён сервернинг ўзида ишлайди. Аввал дамп файлини FTP ёки SFTP орқали хостинг папкасига юклайсиз, сўнг қуйидаги буйруқни ишлатасиз:
mysql -u baza_user -p --default-character-set=utf8mb4 \
--max_allowed_packet=512M baza_nomi < dump.sql
Дамп сиқилган ҳолатда бўлса, уни олдин очиб ўтириш шарт эмас, оқим орқали тўғридан-тўғри узатиш мумкин. Бу диск жойини тежайди, чунки матнли SQL дамп сиқилганда одатда бир неча баробар кичраяди:
gunzip < dump.sql.gz | mysql -u baza_user -p baza_nomi
Узоқ давом этадиган импортни SSH сессия узилиб қолса ҳам тўхтамайдиган қилиб ишга тушириш фойдали. Бунинг учун nohup ёки серверда мавжуд бўлса screen ишлатилади. Парол сўралмаслиги учун уни фақат сизга ўқиш ҳуқуқи берилган созлама файлига ёзиш мумкин:
# ~/.my.cnf (huquq: chmod 600 ~/.my.cnf)
[client]
user=baza_user
password=PAROL
nohup sh -c 'gunzip < dump.sql.gz | mysql baza_nomi' > import.log 2>&1 &
Импорт тугагач import.log файлини кўриб чиқинг: бўш бўлса, хато юз бермаган. Ишингиз тугагач .my.cnf файлидаги паролни ўчириб қўйиш хавфсизлик нуқтаи назаридан тўғри қарор, чунки бу файл серверда очиқ матн кўринишида сақланади.
Дампни тўғри тайёрлаш
Импортнинг муваффақияти кўп жиҳатдан дамп қандай олинганига боғлиқ. Эски сервердан экспорт қилганда mysqldump буйруғига бир нечта параметр қўшиш кейинги босқични анча осонлаштиради. --single-transaction InnoDB жадвалларини сайтни тўхтатмасдан изчил ҳолатда сақлайди, --quick эса катта жадвалларни хотирага тўлиқ юкламасдан қаторма-қатор ўқийди:
mysqldump -u baza_user -p --single-transaction --quick \
--default-character-set=utf8mb4 baza_nomi | gzip > dump.sql.gz
Агар база жуда катта бўлса, уни жадваллар бўйича алоҳида файлларга бўлиш мумкин. Шунда бирор жадвалда хато чиқса, бутун жараённи эмас, фақат шу жадвални қайта юклайсиз. Файлни split билан сатрлар сони бўйича бўлиш тавсия этилмайди, чунки битта INSERT буйруғи ўртасидан кесилиб, бузилган SQL ҳосил бўлиши мумкин. Кодлашга ҳам эътибор беринг: эски базада utf8, янгисида utf8mb4 бўлса, импорт тугагач кирилл ҳарфлари ва эмодзи белгиларини текшириб чиқинг.
SSH бўлмаса нима қилиш керак
Баъзи тарифларда буйруқ сатри мавжуд бўлмайди. Бундай ҳолатда учта йўл бор. Биринчиси, дампни жадваллар бўйича бир нечта кичик файлга бўлиб, phpMyAdmin орқали навбатма-навбат импорт қилиш: ҳар бир файл юклаш лимитидан кичик бўлиши керак. Иккинчиси, катта дампни қисмлаб ўқиб, ҳар сўровда маълум миқдордаги буйруқни бажарадиган босқичма-босқич импорт скриптларидан фойдаланиш, улар PHP вақт лимитига тушиб қолмайди. Учинчиси ва энг содда йўли, файлни хостингга юклаб, импорт ишини техник ёрдамга топшириш.
Масалан, Тошкентдаги электроника дўконининг misol.uz сайти бошқа провайдердан кўчирилаётганини тасаввур қилинг. Маҳсулотлар, буюртмалар тарихи ва логлар билан база 2,5 GB ни ташкил қилади, phpMyAdmin орқали юклашга ҳар уриниш ўн дақиқадан сўнг узилиб қолади. Дампни gzip билан сиқиб, SSH орқали юқоридаги буйруқ билан импорт қилиш бутун ишни тахминан ярим соатда якунлайди ва ҳеч қандай кутиш хатоси чиқмайди. sayt.uz хостингида ҳам шундай ҳолатда файлни юклаб, кабинет орқали тикет очиб ёрдам сўраш мумкин.
Импортдан кейин нимани текшириш керак
Импорт хатосиз тугагани ҳали ҳамма нарса жойида эканини англатмайди. Жадваллар сонини эски ва янги базада солиштиринг, энг муҳим жадваллардаги қаторлар сонини SELECT COUNT(*) билан текширинг. Сайтнинг конфигурация файлида янги база номи, фойдаланувчи ва парол тўғри ёзилганини кўриб чиқинг, сўнг саҳифаларни, қидирувни ва буюртма бериш жараёнини синаб кўринг. Агар матнларда сўроқ белгилари ёки тушунарсиз белгилар пайдо бўлса, бу кодлаш муаммосидан дарак беради ва импортни тўғри --default-character-set билан қайтадан бажариш керак бўлади.