🔤
Хостинг

utf8mb4: эмоджи ва ўзбек ҳарфлари бузилмаслиги учун MySQL кодировкаси

10.11.2026
← Барча мақолалар

Сайтингизга мижоз шарҳ қолдирди, охирига табассум эмоджисини қўйди ва "Сақлаш" тугмасини босди. Натижада шарҳ ё сақланмайди, ё эмоджи ўрнида тўртта сўроқ белгиси пайдо бўлади, ёки матн айнан шу жойдан кесилиб қолади. Бундай ҳолат кўпинча эски ёки нотўғри созланган MySQL базасида учрайди ва унинг сабаби деярли ҳар доим битта: жадвал ёки уланиш кодировкаси utf8mb4 эмас. Бу мақолада муаммонинг илдизини, ўзбек ҳарфларига қандай таъсир қилишини ва базани хавфсиз ўтказиш тартибини кўриб чиқамиз.

MySQL'даги "utf8" аслида тўлиқ UTF-8 эмас

UTF-8 стандартида битта белги 1 байтдан 4 байтгача жой эгаллайди. Лотин ҳарфлари ва рақамлар 1 байт, кирилл ҳарфлари (жумладан ў, қ, ғ, ҳ) 2 байт, кўплаб махсус белгилар 3 байт, эмоджи ва баъзи кам ишлатиладиган иероглиф ва белгилар эса 4 байт олади. MySQL тарихан utf8 номи остида фақат 3 байтгача бўлган белгиларни сақлайдиган қисқартирилган вариантни жорий қилган, ҳозирги ҳужжатларда у utf8mb3 деб ҳам аталади. Тўлиқ UTF-8 ни қўллаб-қувватлайдиган кодировка эса utf8mb4 деб номланади.

Демак, жадвал utf8 билан яратилган бўлса, 4 байтли белги келганда MySQL уни сақлай олмайди. Қатъий режимда (STRICT_TRANS_TABLES) сўров хато билан қайтади, юмшоқ режимда эса белги сўроқ белгисига алмаштирилади ёки қатор кесилади. Лог файлида одатда шундай хабар кўринади:

SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xF0\x9F\x98\x80' for column 'comment' at row 1

Бу ердаги \xF0\x9F\x98\x80 байтлари айнан табассум эмоджисининг UTF-8 даги кўринишидир.

Ўзбек ҳарфлари билан боғлиқ ҳақиқий муаммо қаерда

Кўпчилик ўзбекча ў, ғ ҳарфлари ҳам эмоджи каби бузилади деб ўйлайди, лекин бу бироз бошқача. Оддий клавиатурадаги апостроф билан ёзилган o' ва g' 1 байтли белгилардан иборат, махсус ʻ (U+02BB) белгиси эса 3 байт олади, кирилл ў ва қ эса 2 байт. Шунинг учун улар utf8 жадвалда ҳам тўғри сақланади, utf8mb4 га ўтиш эса бу муаммони ҳам, эмоджи муаммосини ҳам бир йўла ёпади. Ўзбек ҳарфлари одатда бошқа сабаб билан бузилади: жадвал умуман latin1 ёки cp1251 кодировкасида яратилган бўлади ёки PHP базага уланишда кодировкани кўрсатмайди. Бундай ҳолатда кирилл матн "????" кўринишида сақланади ва уни кейин тиклашнинг иложи бўлмайди.

Ҳозирги ҳолатни қандай текшириш мумкин

Ўзгартиришдан олдин база, жадваллар ва устунлар қайси кодировкада эканини аниқ билиб олиш керак. Буни phpMyAdmin орқали ёки SQL сўрови билан қилиш мумкин. Қуйидаги сўров базадаги ҳар бир жадвалнинг collation қийматини кўрсатади, унинг номининг боши кодировкани билдиради:

SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'example_db';

SHOW VARIABLES LIKE 'character_set%';
SHOW FULL COLUMNS FROM comments;

Агар натижада latin1_swedish_ci ёки utf8_general_ci кўрсангиз, ўтказиш керак. utf8mb4_unicode_ci ёки utf8mb4_0900_ai_ci кўринса, жадваллар тартибда, муаммо уланиш созламасида бўлиши мумкин.

Базани utf8mb4 га ўтказиш тартиби

Ҳар қандай ўзгартиришдан олдин базанинг тўлиқ захира нусхасини олинг. Хостинг панелида бу бир неча тугма билан қилинади, SSH бўлса эса mysqldump ишлатилади. Захира кодировкаси ҳам аниқ кўрсатилиши муҳим, акс ҳолда думп файлнинг ўзи бузилиб қолиши мумкин:

mysqldump --default-character-set=utf8mb4 -u example_user -p example_db > example_db_backup.sql

Шундан кейин база ва ҳар бир жадвал учун ўтказиш буйруқлари бажарилади. CONVERT TO жадвалдаги барча матн устунларини янги кодировкага ўтказади ва мавжуд маълумотни қайта кодлайди:

ALTER DATABASE example_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

ALTER TABLE comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE products CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Индекс узунлиги билан боғлиқ хато

Эски MySQL версияларида (5.6 ва ундан олдинги, айниқса COMPACT қатор форматида) ўтказиш пайтида Specified key was too long; max key length is 767 bytes хатоси чиқиши мумкин. Сабаби: utf8mb4 да ҳар белгига 4 байт ҳисобланади, шунинг учун VARCHAR(255) устунидаги индекс 1020 байтни талаб қилади. MySQL 5.7 ва ундан янги версияларда DYNAMIC қатор формати билан чегара 3072 байтгача ошган ва бу муаммо деярли учрамайди. Эски серверда эса индексланган устунни VARCHAR(191) га қисқартириш одатий ечим ҳисобланади.

PHP уланишида кодировкани кўрсатиш

Жадвалларни ўтказиш ярим иш холос. Агар илова базага уланганда кодировкани айтмаса, сервер стандарт қийматни ишлатади ва эмоджи яна бузилади. PDO учун DSN қаторига charset қўшилади, mysqli учун эса алоҳида функция чақирилади:

// PDO
$pdo = new PDO('mysql:host=localhost;dbname=example_db;charset=utf8mb4', $user, $pass);

// mysqli
$db = new mysqli('localhost', $user, $pass, 'example_db');
$db->set_charset('utf8mb4');

WordPress'да бу созлама wp-config.php файлида туради: define('DB_CHARSET', 'utf8mb4');. Laravel'да config/database.php файлидаги charset ва collation қийматлари стандарт ҳолатда аллақачон utf8mb4 бўлади, фақат эски лойиҳаларда текшириб қўйиш керак. Эски кодда учрайдиган SET NAMES utf8 қаторларини ҳам SET NAMES utf8mb4 га алмаштириш лозим.

Амалий мисол: Тошкентдаги гул дўкони

Тасаввур қилинг, Тошкентдаги гул етказиб бериш хизмати misol.uz сайтида буюртма формаси бор. Мижозлар табрик матнига кўпинча 🌹 ва 🎉 каби эмоджи қўшишади. Сайт бир неча йил олдин яратилган, orders жадвали utf8_general_ci да. Натижада эмоджили буюртмалар базага тушмай қолган, оператор эса уларни умуман кўрмаган. Дастурчи аввал захира нусха олди, сўнг orders ва order_items жадвалларини CONVERT TO билан ўтказди, PDO уланишига charset=utf8mb4 қўшди ва тест буюртма юборди. Шундан кейин табрик матнлари эмоджи билан бирга тўлиқ сақлана бошлади.

Катта жадвални ўтказиш бир неча дақиқа давом этиб, жадвални блоклаши мумкин, шунинг учун буни ташриф кам пайтда қилинг. sayt.uz хостингида базалар билан phpMyAdmin орқали ишлаш мумкин, панел эса sayt.uz кабинетидан очилади.

Ўтказишдан кейин нималарни текшириш керак

Охирги бандни алоҳида таъкидлаш керак: utf8mb4 келажакдаги маълумотни ҳимоя қилади, лекин ўтмишда йўқолган белгиларни қайтармайди. Шунинг учун янги лойиҳа яратаётганда базани ва жадвалларни дарҳол utf8mb4_unicode_ci билан яратиш энг тўғри йўл. Саволлар бўлса, sayt.uz техник ёрдамига тикет орқали мурожаат қилишингиз мумкин.

Ўхшаш мақолалар

🚦 "Too many connections" хатоси: сабаб ва ечим 📁 FileZilla ва WinSCP билан хостингга SFTP орқали уланиш 🗄️ ISPmanager'да маълумотлар базаси ва фойдаланувчи яратиш 📦 Next.js standalone build: кам ресурс билан ишлатиш ва кичик серверга жойлаш
🌐 Тил
🇺🇿 O'zbek 🇺🇿 Ўзбек ✓ 🇷🇺 Русский 🇬🇧 English