RE:NODE

ბაზები12 წუთის საკითხავი

MySQL utf8mb4 და collation-ები: utf8 თუ utf8mb4, კონვერტაცია

რატომ ვერ ინახავს MySQL-ის utf8 emoji-ს, რომელი utf8mb4 collation აირჩიო, როგორ მუშაობს კავშირის charset და როგორ გადაიყვანო ბაზა mojibake-ის გარეშე.

0 მკითხველი

MySQL-ში utf8 არ არის UTF-8. ეს utf8mb3-ის ფსევდონიმია, სამბაიტიანი ქვესიმრავლე, რომელიც ვერ ინახავს ვერცერთ სიმბოლოს Basic Multilingual Plane-ის გარეთ - მათ შორის ყველა emoji-ს, ბევრ CJK სიმბოლოს და მათემატიკური თუ ისტორიული დამწერლობების ნაწილს. utf8mb4 ნამდვილი UTF-8-ია და MySQL 8.0-დან ნაგულისხმევი სიმბოლოების ნაკრებია, utf8mb4_0900_ai_ci ნაგულისხმევი collation-ით. თუ ბაზას დღეს ქმნი, ყველგან utf8mb4 გამოიყენე: ბაზაში, ცხრილებში, სვეტებში და კავშირში. თუ utf8-ზე ან latin1-ზე მყოფი ბაზა მემკვიდრეობით მიიღე, მისი კონვერტაცია შესაძლებელია, მაგრამ როგორ გააკეთებ, დამოკიდებულია იმაზე, სწორადაა თუ არა მასში მონაცემები შენახული, და ამაში შეცდომა სწორედ ის გზაა, რომლითაც ტექსტი é-ად იქცევა.

ეს სახელმძღვანელო ხსნის განსხვავებას, როგორ აირჩიო collation, კავშირის რომელი პარამეტრები უნდა ემთხვეოდეს, და როგორ გადაიყვანო არსებული ბაზა უსაფრთხოდ MySQL 8.0-ზე ან 8.4 LTS-ზე.

utf8, utf8mb3 და utf8mb4#

UTF-8 ყოველ სიმბოლოს ერთიდან ოთხ ბაიტამდე აკოდირებს. ASCII ერთ ბაიტს იკავებს, ევროპული და ახლო აღმოსავლეთის ასოების უმეტესობა - ორს, ჩინური, იაპონური და კორეული სიმბოლოების უმეტესობა - სამს, ხოლო ყველაფერი U+FFFF-ის ზემოთ - emoji, იშვიათი CJK, მუსიკალური სიმბოლოები - ოთხს. როცა MySQL-მა 2002 წელს Unicode-ის მხარდაჭერა დაამატა, ადგილის დასაზოგად თავისი utf8 სიმბოლოზე სამ ბაიტამდე შეზღუდა, და ეს გადაწყვეტილება მას შემდეგ ხალხს ფეხს უდებს.

სახელიბაიტი სიმბოლოზეEmojiსტატუსი
latin11არამხოლოდ დასავლეთ ევროპული; ძველი ნაგულისხმევი 8.0-მდე
utf8mb31-3არამოძველებული
utf81-3არაutf8mb3-ის ფსევდონიმი 8.4-ში
utf8mb41-4კინაგულისხმევი 8.0-დან; ეს გამოიყენე

MySQL 8.0.30-დან სერვერი SHOW CREATE TABLE-სა და information_schema-ში utf8-ის ნაცვლად utf8mb3-ს აჩვენებს, რაც მდგომარეობას ბოლოს და ბოლოს ხილულს ხდის. გეგმა ისაა, რომ მომავალ ვერსიაში utf8 utf8mb4-ის ფსევდონიმი გახდეს; სანამ ეს მოხდება, არასოდეს დაწერო utf8 სქემაში, კონფიგურაციის ფაილში ან კავშირის სტრიქონში. დაწერე utf8mb4.

emoji-ს შენახვის მცდელობა utf8mb3 სვეტში ნაგულისხმევი მკაცრი SQL რეჟიმით ხმამაღლა მარცხდება:

code
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x98\x80' for column 'body' at row 1

\xF0 ოთხბაიტიანი მიმდევრობის პირველი ბაიტია. მკაცრი რეჟიმის გარეშე MySQL სიმბოლოს წყვეტს ან ?-ით ცვლის და აგრძელებს, რაც უარესია: მონაცემები ჩუმად ზიანდება. თუ კითხვის ნიშნებს ხედავ იქ, სადაც მომხმარებლებმა emoji აკრიფეს, ან სვეტი, ან კავშირი არ არის utf8mb4.

Collation-ები: რას ნიშნავს სახელები#

სიმბოლოების ნაკრები ამბობს, როგორ ინახება სიმბოლოები. collation ამბობს, როგორ ედრება და ლაგდება ისინი: უდრის თუ არა a A-ს, უდრის თუ არა e é-ს, და სად მიდის ß. ყოველ ტექსტურ სვეტს ორივე აქვს. collation-ის სახელი მის ქცევას აკოდირებს:

Collationმნიშვნელობა
utf8mb4_0900_ai_ciUnicode 9.0-ის წესები, აქცენტისა და რეგისტრის მიმართ არამგრძნობიარე. 8.0+-ის ნაგულისხმევი
utf8mb4_0900_as_ciაქცენტის მიმართ მგრძნობიარე, რეგისტრის მიმართ არამგრძნობიარე
utf8mb4_0900_as_csაქცენტისა და რეგისტრის მიმართ მგრძნობიარე
utf8mb4_0900_bincode point-ებს ადარებს; სწრაფი, ენობრივი წესების გარეშე
utf8mb4_binბაიტების ბინარული შედარება, ბოლო ჰარეებით შევსებით
utf8mb4_unicode_ciძველი Unicode 4.0-ის წესები; გავრცელებულია 5.7-ის ეპოქის სქემებში
utf8mb4_general_ciძველი, გამარტივებული წესები; სწრაფი, მაგრამ ბევრი ენისთვის არასწორი
utf8mb4_de_pb_0900_ai_ciგერმანული სატელეფონო წიგნის რიგი; ბევრი ლოკალისთვის არსებობს ენობრივი ვარიანტი

0900 collation-ები Unicode Collation Algorithm-ის 9.0.0 ვერსიას ეფუძნება და MySQL 8-ში ძველ unicode_ci-ებზე უფრო სწორიც არის და უფრო სწრაფიც. ძველი collation-ებისგან ორი რამით განსხვავდება, რაც ღირს, რომ იცოდე:

  • BMP-ის გარეთ მყოფი სიმბოლოები სწორად ლაგდება და ედრება. utf8mb4_unicode_ci-სა და utf8mb4_general_ci-ში ყველა ოთხბაიტიანი სიმბოლო ერთმანეთის ტოლია - უნიკალური index-ის მქონე სვეტი ვერ დაიტევს ერთდროულად სუშის emoji-სა და ლუდის emoji-ს, რადგან collation-ისთვის ისინი ერთი და იგივე სიმბოლოა. 0900 collation-ები მათ განსხვავებულად თვლის.
  • ბოლო ჰარეები ითვლება. 0900 collation-ები NO PAD-ია: 'abc' და 'abc ' განსხვავებულია. ძველები PAD SPACE-ია და მათ ტოლად თვლის. ეს ცვლის შედარებებისა და უნიკალურობის შემოწმებების შედეგს მონაცემებზე, რომლებსაც შემთხვევითი ბოლო ჰარეები აქვს.

არჩევა

აპლიკაციების უმეტესობისთვის დატოვე ნაგულისხმევი utf8mb4_0900_ai_ci. რეგისტრისა და აქცენტის მიმართ არამგრძნობიარე დამთხვევა სწორედ ისაა, რასაც ხალხი ძებნის ველისა და შესვლის ფორმისგან ელის: Ana@Example.com პოულობს ana@example.com-ს, cafe პოულობს café-ს.

არამგრძნობიარობის ფასი უნიკალურ index-ებში ჩანს. ai_ci-ით resume და résumé ტოლია, ასე რომ username-ის სვეტზე უნიკალური index მეორეს უარყოფს. username-ებისთვის ეს ჩვეულებრივ სასურველია - აქცენტით სხვის თავად გასაღებას აჩერებს - და ზოგჯერ მოულოდნელი სხვა მონაცემებისთვის. სვეტებისთვის, რომლებსაც ზუსტი დამთხვევა სჭირდება (token-ები, hash-ები, რეგისტრის მიმართ მგრძნობიარე კოდები), გამოიყენე utf8mb4_0900_bin ან utf8mb4_0900_as_cs მხოლოდ იმ სვეტზე:

sql
CREATE TABLE api_tokens (  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,  token VARCHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,  name VARCHAR(100) NOT NULL,  UNIQUE KEY uq_token (token)) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

token-ები და hash-ები სუფთა ASCII-ია, ამიტომ ascii ascii_bin-ით მათ სიმბოლოზე ერთ ბაიტად ინახავს და ზუსტად ადარებს. ენაზე სპეციფიკური collation-ები ღირს, როცა დალაგების რიგი ერთი ენის მომხმარებლებისთვის მნიშვნელოვანია - თურქული წერტილიანი და უწერტილო i, შვედური å ä ö z-ის შემდეგ, ესპანური ñ.

სიმბოლოების ნაკრები ყველა დონეზე#

სიმბოლოების ნაკრები და collation ხუთ დონეზე შეიძლება დაყენდეს, და თითოეული, თუ მითითებული არ არის, ზედა დონიდან მემკვიდრეობით იღებს:

  1. სერვერი: character_set_server და collation_server, ნაგულისხმევი ახალი ბაზებისთვის.
  2. ბაზა: CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, ნაგულისხმევი ახალი ცხრილებისთვის.
  3. ცხრილი: DEFAULT CHARSET=..., ნაგულისხმევი ახალი სვეტებისთვის.
  4. სვეტი: ის, რაც შენახვისთვის რეალურად გამოიყენება.
  5. კავშირი: როგორ მოგზაურობს ტექსტი კლიენტსა და სერვერს შორის.

სვეტის დონე წყვეტს, რა ინახება. ბაზის ნაგულისხმევის შეცვლა ALTER DATABASE-ით არსებულ ცხრილებში არაფერს ცვლის; ის მხოლოდ შემდეგ შექმნილ ცხრილებზე მოქმედებს. ეს იჭერს ხალხს, ვინც ბაზა „გადაიყვანა“ და ისევ Incorrect string value შეცდომებს იღებს.

sql
-- Every text column in a database that is not utf8mb4SELECT table_name, column_name, character_set_name, collation_nameFROM information_schema.columnsWHERE table_schema = 'appdb'  AND character_set_name IS NOT NULL  AND character_set_name <> 'utf8mb4'ORDER BY table_name, ordinal_position;-- Tables whose default differsSELECT table_name, table_collationFROM information_schema.tablesWHERE table_schema = 'appdb' AND table_collation NOT LIKE 'utf8mb4%';

კავშირის სიმბოლოების ნაკრები#

სერვერი ბაიტებს სვეტის სიმბოლოების ნაკრებში ინახავს, მაგრამ უნდა იცოდეს, რა სიმბოლოების ნაკრებში აგზავნის კლიენტი. ამას სამი session ცვლადი აღწერს: character_set_client (რას აგზავნის კლიენტი), character_set_connection (რაში ინტერპრეტირდება ბრძანებები) და character_set_results (რა სახით ბრუნდება შედეგები). SET NAMES utf8mb4 სამივეს აყენებს, და ყველა დრაივერს აქვს ოფცია, რომელიც ამას დაკავშირებისას აკეთებს:

კლიენტიროგორ დავაყენოთ
mysql CLI--default-character-set=utf8mb4 (8.x კლიენტში ნაგულისხმევია)
PHP PDOcharset=utf8mb4 DSN-ში
PHP mysqli$mysqli->set_charset('utf8mb4')
Node mysql2charset ოფცია; utf8mb4 collation ნაგულისხმევია
Python PyMySQL / mysqlclientcharset='utf8mb4'
JDBCcharacterEncoding=UTF-8
.NET MySqlConnectorყოველთვის utf8mb4; დასაყენებელი არაფერია
sql
SHOW SESSION VARIABLES LIKE 'character_set_%';SHOW SESSION VARIABLES LIKE 'collation_connection';

კავშირი, რომელიც latin1-ს აცხადებს, მაშინ როცა აპლიკაცია სინამდვილეში UTF-8-ს აგზავნის, mojibake-ის უმეტესობის ძირეული მიზეზია: MySQL ერთგულად გარდაქმნის UTF-8 ტექსტის ყოველ ბაიტს, თითქოს ის Latin-1 სიმბოლო იყოს, და é (UTF-8-ში ორი ბაიტი) é-ად ჩადის. charset კავშირის სტრიქონში დააყენე და არა SET NAMES query-ით დაკავშირების შემდეგ, რომ ხელახლა დაკავშირებულმა pool-მა ის არ დაკარგოს. PHP PDO და MySQL და MySQL-ის დისტანციური კავშირები კავშირის სრულ დაყენებას თითოეული runtime-ისთვის აჩვენებს.

index-ის ზომა და VARCHAR(191)-ის ფოლკლორი#

utf8mb4 index-ის გასაღების სიგრძის გამოთვლისას სიმბოლოზე ოთხ ბაიტს იტოვებს. InnoDB-ის index-ის მაქსიმალური გასაღები 3072 ბაიტია DYNAMIC row format-ით, რომელიც 5.7-დან ნაგულისხმევია, და ეს VARCHAR(768)-ზე სრულ index-ს უშვებს. ძველი COMPACT და REDUNDANT ფორმატები, ისევე როგორც MySQL 5.6 ნაგულისხმევად, გასაღებებს 767 ბაიტით ზღუდავდა - utf8mb4-ის 191 სიმბოლო - და სწორედ ამიტომ იყენებს ამდენი framework და სახელმძღვანელო დღემდე VARCHAR(191)-ს index-ირებული სვეტებისთვის.

MySQL 8-ზე DYNAMIC ცხრილებით 191 არ გჭირდება. გამოიყენე ის სიგრძე, რაც შენს მონაცემებს სჭირდება. თუ ძველი ცხრილი index-ს უარყოფს შეცდომით Specified key was too long; max key length is 767 bytes, შეამოწმე მისი row format:

sql
SELECT table_name, row_format FROM information_schema.tablesWHERE table_schema = 'appdb' AND row_format IN ('Compact', 'Redundant');ALTER TABLE legacy_table ROW_FORMAT=DYNAMIC;

არსებული ბაზის კონვერტაცია#

ჯერ გაარკვიე, სინამდვილეში რა არის სვეტებში, რადგან ორი ძალიან განსხვავებული სიტუაცია არსებობს:

  • სწორად შენახული მონაცემები არასწორ charset-ში. latin1 სვეტი Latin-1 ტექსტით, ან utf8mb3 სვეტი ვალიდური ტექსტით. MySQL-მა იცის, რა სიმბოლოებია და შეუძლია მათი გარდაქმნა. გამოიყენე CONVERT TO.
  • არასწორად მონიშნული მონაცემები. latin1 სვეტი, რომელიც სინამდვილეში UTF-8 ბაიტებს შეიცავს, რადგან აპლიკაცია წლების განმავლობაში UTF-8-ს წერდა latin1 კავშირით. აპლიკაციაში ყველაფერი კარგად ჩანს (ის მონაცემებს იმავე არასწორი გზით კითხულობს უკან), ხოლო phpMyAdmin-ში ან dump-ში - არასწორად. CONVERT TO მას ორმაგად დააკოდირებდა. ამას ქვემოთ აღწერილი ბინარული წრე სჭირდება.

რომ გაიგო, რომელი გაქვს, შეხედე ცნობილ აქცენტიან მნიშვნელობას HEX()-ით:

sql
SELECT name, HEX(name) FROM customers WHERE id = 42;-- 'José' correctly stored in latin1:          4A6F73E9-- 'José' as UTF-8 bytes in a latin1 column:   4A6F73C3A9

E9 არის é Latin-1-ში. C3A9 არის é UTF-8-ში, რომელიც ზის სვეტში, რომელსაც ჰგონია, რომ ორ Latin-1 სიმბოლოს ინახავს.

სწორად შენახული: CONVERT TO

sql
ALTER DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;ALTER TABLE customers  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

CONVERT TO ცვლის ცხრილის ნაგულისხმევს და ყოველ ტექსტურ სვეტს, მონაცემების გარდაქმნით. ის ცხრილს copy ალგორითმით ხელახლა აგებს, ასე რომ ჩაწერები მთელი ამ დროის განმავლობაში დაბლოკილია და სრული ასლისთვის თავისუფალი ადგილი გჭირდება დისკზე. latin1-იდან გარდაქმნამ შეიძლება TEXT სვეტები MEDIUMTEXT-მდეც აწიოს, რომ იმავე რაოდენობის სიმბოლოს დატევა შეძლონ; შემდეგ სქემა შეამოწმე, თუ შენს ORM-ს ეს აინტერესებს. დააგენერირე ბრძანებები ყველა ცხრილისთვის:

sql
SELECT CONCAT('ALTER TABLE `', table_name, '` CONVERT TO CHARACTER SET utf8mb4 ',              'COLLATE utf8mb4_0900_ai_ci;') AS stmtFROM information_schema.tablesWHERE table_schema = 'appdb' AND table_type = 'BASE TABLE';

არასწორად მონიშნული: ბინარული წრე

რომ MySQL-ს უთხრა, ბაიტები გარდაქმნის გარეშე ხელახლა ინტერპრეტირება მოახდინოს, ბინარულ ტიპზე უნდა გაიარო, რომელსაც სიმბოლოების ნაკრები არ აქვს:

sql
ALTER TABLE customers MODIFY name VARBINARY(255);ALTER TABLE customers MODIFY name VARCHAR(255)  CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL;

VARCHAR გადის VARBINARY-ზე, TEXT - BLOB-ზე, MEDIUMTEXT - MEDIUMBLOB-ზე. უკან გზაზე სვეტის სრული განსაზღვრება ხელახლა მიუთითე, NOT NULL-ისა და ნაგულისხმევი მნიშვნელობების ჩათვლით, რადგან MODIFY მას ცვლის. სვეტზე არსებული index-ები გადარჩება. შემდეგ გაასწორე აპლიკაციის კავშირის charset, სანამ ის რამეს ჩაწერს, თორემ ახალი ხაზები საპირისპირო მიმართულებით იქნება არასწორი.

კონვერტაციის გეგმა მოქმედი აპლიკაციისთვის#

ALTER ბრძანებები მარტივი ნაწილია. რიგი მათ გარშემო ინარჩუნებს მოქმედ საიტს მუშა მდგომარეობაში.

  1. ინვენტარიზაცია. გაუშვი ზემოთ მოცემული information_schema query-ები და ჩამოწერე ყველა ცხრილი და სვეტი, რომელიც utf8mb4 არ არის, ზომებით. პატარა ცხრილები წამებში გარდაიქმნება; მრავალგიგაბაიტიან ცხრილს შეიძლება იმდენი დრო დასჭირდეს, რომ ტექნიკური სამუშაოების ფანჯარა გჭირდებოდეს, რადგან CONVERT TO კოპირებისას ჩაწერებს ბლოკავს.
  2. დიაგნოზი. არა-ASCII ტექსტის მქონე ყოველი ცხრილისთვის შეამოწმე რამდენიმე ცნობილი მნიშვნელობა HEX()-ით და გადაწყვიტე, სწორადაა შენახული თუ არასწორადაა მონიშნული. ერთ ბაზაში შეიძლება ორივე იყოს, თუ აპლიკაციის კავშირის პარამეტრები მის ისტორიაში რაღაც მომენტში შეიცვალა.
  3. ჯერ კავშირი გაასწორე, სადაც ეს უსაფრთხოა. თუ მონაცემები სწორადაა შენახული, აპლიკაციის კავშირის utf8mb4-ზე გადართვა ცხრილების კონვერტაციამდე უვნებელია: MySQL კავშირსა და სვეტს შორის გარდაქმნას თავად აკეთებს. თუ მონაცემები არასწორადაა მონიშნული, კავშირის ცვლილება და ბინარული წრე ერთად უნდა მოხდეს, შუაში შეჩერებული ჩაწერებით.
  4. გაიმეორე ასლზე. აღადგინე წუხანდელი dump სატესტო ბაზაში, გაუშვი სრული კონვერტაცია და შეამოწმე იგივე ცნობილი მნიშვნელობები, დალაგების რიგი და ძებნა. გაზომე დრო - ეს შენი ფანჯარაა.
  5. გაუშვი რეალურად, ცხრილ-ცხრილ, უდიდესი ბოლოს, უშუალოდ წინ აღებული ახალი backup-ით.
  6. დააყენე ნაგულისხმევები ბაზის დონეზე, რომ ახალი ცხრილები სწორად დაიბადოს, და დააფიქსირე charset და collation შენს migration-ებში, რომ framework-მა შემდეგი ცხრილი ჩუმად სხვა რამით არ შექმნას.
  7. მოძებნე ნარჩენები: შენახული პროცედურები და view-ები ინარჩუნებს იმ სიმბოლოების ნაკრებს, რომელიც მათი შექმნისას იყო მიმდინარე, და SHOW CREATE PROCEDURE მას აჩვენებს. კონვერტაციის შემდეგ ხელახლა შექმენი ისინი.

framework-ები ცალკე ყურადღებას იმსახურებს. Laravel-ის config/database.php აყენებს charset-სა და collation-ს კავშირისთვის და იმ ცხრილებისთვის, რომლებსაც მისი migration-ები ქმნის; ძველ პროექტებში ხშირად დაფიქსირებულია utf8mb4_unicode_ci, რაც კარგია, მაგრამ ყველა სხვა ცხრილს უნდა ემთხვეოდეს, რომ ქვემოთ აღწერილი შერეული collation-ის შეცდომა აიცილო. Django-ს MySQL backend იყენებს OPTIONS-ის charset გასაღებს. WordPress wp-config.php-ში აყენებს DB_CHARSET-სა და DB_COLLATE-ს და 4.2 ვერსიიდან utf8mb4-ს იყენებს; ძველ საიტს, რომელიც იმ განახლებამდე არსებობდა, შეიძლება ჯერ კიდევ ჰქონდეს utf8mb3-ში ცხრილები, რომლებიც განახლების პროცედურამ index-ის სიგრძის ლიმიტების გამო გამოტოვა. ყველა შემთხვევაში framework-ის პარამეტრი და ცხრილების რეალური განსაზღვრებები ერთმანეთს უნდა ემთხვეოდეს - პარამეტრი მხოლოდ იმაზე მოქმედებს, რასაც framework შემდეგ შექმნის.

Collation-ის შეცდომები და მათი გამოსწორება#

code
ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and(utf8mb4_0900_ai_ci,IMPLICIT) for operation '='

განსხვავებული collation-ის მქონე ორი სვეტი join-ში ან WHERE-ში ედრება. ეს ჩვეულებრივ ნაწილობრივი migration-ის შემდეგ ხდება: ძველი ცხრილები utf8mb4_unicode_ci-ში, ახლები 8.0-ის ნაგულისხმევში. დარჩენილი ცხრილების ერთ collation-ზე გადაყვანა ნამდვილი გამოსწორებაა; COLLATE utf8mb4_0900_ai_ci შედარების ერთ მხარეს სწრაფი გამოსწორებაა და იმ მხარეს index-ის გამოყენებას უშლის ხელს.

code
ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci'

MySQL 8-ის dump იტვირთება MySQL 5.7-ში ან სხვა ოჯახის სერვერში. 0900 collation-ები მხოლოდ MySQL 8-ში არსებობს. თუ შეგიძლია, MySQL 8-ში აღადგინე; სხვა შემთხვევაში collation-ის სახელი მთელ dump-ში ჩაანაცვლე. MySQL-ის გადატანა ახალ ჰოსტზე ვერსიების შეუსაბამობას ზოგადად განიხილავს.

FAQ#

utf8mb4_unicode_ci გამოვიყენო თუ utf8mb4_0900_ai_ci?

MySQL 8-ზე - utf8mb4_0900_ai_ci. ის Unicode-ის წესების უფრო ახალ ვერსიას მიჰყვება, ასხვავებს emoji-სა და სხვა ოთხბაიტიან სიმბოლოებს და MySQL 8-ის იმპლემენტაციაში უფრო სწრაფია. unicode_ci მხოლოდ იქ დატოვე, სადაც ბაზა MySQL 5.7-შიც ან სხვა ოჯახის სერვერშიც უნდა ჩაიტვირთოს, რომელსაც 0900 collation-ები არ აქვს.

utf8mb4 utf8-ზე მეტ ადგილს იკავებს?

იმავე ტექსტისთვის - არა. UTF-8 ყოველ სიმბოლოს იმდენ ბაიტში ინახავს, რამდენიც სჭირდება, ასე რომ ASCII ორივეში ერთი ბაიტია. განსხვავება მხოლოდ ის სიმბოლოებია, რომლებსაც utf8mb3 საერთოდ ვერ ინახავს. იზრდება index-ებისა და მეხსიერებაში მყოფი დროებითი ცხრილებისთვის დარეზერვებული ზომა, რომლებიც სიმბოლოზე ოთხ ბაიტს ვარაუდობს.

რატომ ვხედავ კითხვის ნიშნებს emoji-ს ნაცვლად?

ტექსტმა გაიარა რაღაც, რაც utf8mb4 არ არის - სვეტი, ცხრილი ან, ყველაზე ხშირად, კავშირი - და MySQL მკაცრ რეჟიმში არ იყო, ამიტომ სიმბოლოები უარყოფის ნაცვლად ჩაანაცვლა. შეამოწმე სვეტი SHOW CREATE TABLE-ით, კავშირი SHOW SESSION VARIABLES LIKE 'character_set_%'-ით და დააყენე charset=utf8mb4 დრაივერში.

შემიძლია ერთი query რეგისტრის მიმართ მგრძნობიარე გავხადო სვეტის შეცვლის გარეშე?

კი: WHERE code = 'AbC' COLLATE utf8mb4_0900_as_cs. მუშაობს, მაგრამ ვერ იყენებს სვეტის საკუთარი collation-ით აგებულ index-ს, ამიტომ scan-ს აკეთებს. სვეტისთვის, რომელიც ყოველთვის რეგისტრის გათვალისწინებით ედრება, მის ნაცვლად collation შეცვალე.

ALTER DATABASE ჩემს ცხრილებს გარდაქმნის?

არა. ის მხოლოდ შემდეგ შექმნილი ცხრილების ნაგულისხმევს ცვლის. არსებული ცხრილები და მათი სვეტები თავიანთ სიმბოლოების ნაკრებს ინარჩუნებს, სანამ თითოეულზე ALTER TABLE ... CONVERT TO-ს არ გაუშვებ.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000