কীভাবে সহজেই মাইএসকিউএল 5.5 তে utf8 টেবিলগুলি utf8mb4 এ রূপান্তর করতে হয়


71

আমার কাছে একটি ডাটাবেস রয়েছে যা এখন 4 বাইট অক্ষর (চীনা) সমর্থন করে। ভাগ্যক্রমে আমার উত্পাদন ইতিমধ্যে মাইএসকিউএল 5.5 আছে।

সুতরাং আমি কেবল সমস্ত কলেশন তৈরি করতে চাই যা utf8_bin থেকে utf8mb4_bin।

আমি বিশ্বাস করি কিছুটা স্টোরেজ ওভারহেড ব্যতীত এই পরিবর্তনটির সাথে কোনও কার্যকারিতা ক্ষতি / লাভ নেই।

উত্তর:


93

আমার গাইড থেকে মাইএসকিউএল ডাটাবেসে সম্পূর্ণ ইউনিকোডকে কীভাবে সমর্থন করা যায় , এখানে ডেটাবেস, একটি টেবিল বা কলামের চরসেট এবং কোলেশন আপডেট করতে আপনি যে প্রশ্নগুলি চালাতে পারেন তা এখানে রয়েছে:

প্রতিটি ডাটাবেসের জন্য:

ALTER DATABASE
    database_name
    CHARACTER SET = utf8mb4
    COLLATE = utf8mb4_unicode_ci;

প্রতিটি টেবিলের জন্য:

ALTER TABLE
    table_name
    CONVERT TO CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

প্রতিটি কলামের জন্য:

ALTER TABLE
    table_name
    CHANGE column_name column_name
    VARCHAR(191)
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

(অন্ধভাবে এটিকে অনুলিপি করে কপি-পেস্ট করবেন না! সঠিক বিবৃতিটি কলামের ধরণ, সর্বাধিক দৈর্ঘ্য এবং অন্যান্য বৈশিষ্ট্যের উপর নির্ভর করে line উপরের লাইনটি একটি VARCHARকলামের জন্য কেবল উদাহরণ ))

মনে রাখবেন, তবে, যে আপনি সম্পূর্ণরূপে থেকে রুপান্তরের স্বয়ংক্রিয় করতে পারবে না utf8করতে utf8mb4উপরে উল্লিখিত গাইডের 4 ধাপে বর্ণিত হিসাবে , আপনাকে কলাম এবং সূচি কীগুলির সর্বাধিক দৈর্ঘ্য পরীক্ষা করতে হবে, আপনি যে নম্বরটি নির্দিষ্ট করেছেন utf8mb4তার পরিবর্তে ব্যবহার করার সময় তার আলাদা অর্থ রয়েছে utf8

মাইএসকিউএল 5.5 রেফারেন্স ম্যানুয়ালের 10.1.11 সেকশন এ সম্পর্কে আরও কিছু তথ্য রয়েছে।


31

আমার একটি সমাধান রয়েছে যা কয়েকটি কমান্ড চালিয়ে ডাটাবেস এবং টেবিলগুলিকে রূপান্তর করবে। এছাড়া ধরনের সমস্ত কলাম পরিবর্তন করে varchar, text, tinytext, mediumtext, longtext, charআপনার কিছু ডাটা ব্রেক হয়ে গেলে আপনার ডাটাবেসটিও ব্যাকআপ করা উচিত ।

নিম্নলিখিত কোডটি এমন একটি ফাইলকে অনুলিপি করুন যার নাম এটি preAlterTables.sql:

use information_schema;
SELECT concat("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql 
FROM `TABLES` where table_schema like "yourDbName" group by table_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql  
FROM `TABLES` where table_schema like "yourDbName" group by table_schema, table_name;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type,"(",character_maximum_length,") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql 
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('varchar','char');
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type," CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql 
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('text','tinytext','mediumtext','longtext');

আপনি রূপান্তর করতে চান এমন ডাটাবেসটির সাথে "yourDbName" এর সমস্ত উপস্থিতি প্রতিস্থাপন করুন। তারপরে চালান:

mysql -uroot < preAlterTables.sql | egrep '^ALTER' > alterTables.sql

এটি আপনাকে ডাটাবেস রূপান্তর করতে হবে এমন সমস্ত প্রশ্নের সাথে alterTables.sql একটি নতুন ফাইল তৈরি করবে। রূপান্তর শুরু করতে নিম্নলিখিত কমান্ডটি চালান:

mysql -uroot < alterTables.sql

আপনি টেবিল_সেমার শর্তটি পরিবর্তন করে একাধিক ডাটাবেসগুলির মাধ্যমে চালানোর জন্য এটিকে মানিয়ে নিতে পারেন। উদাহরণস্বরূপ table_schema like "wiki_%"নাম উপসর্গ সহ সমস্ত ডাটাবেস রূপান্তরিত হবে wiki_। সমস্ত ডাটাবেস রূপান্তর করতে শর্তটি এর সাথে প্রতিস্থাপন করুন table_type!='SYSTEM VIEW'

একটি সমস্যা যে উত্থাপিত হতে পারে। মাইএসকিএল কীতে আমার কিছু বারচর (255) কলাম ছিল। এটি একটি ত্রুটি ঘটায়:

ERROR 1071 (42000) at line 2229: Specified key was too long; max key length is 767 bytes

যদি এটি ঘটে থাকে তবে আপনি কলামটি ভারচর (150) এর মতো ছোট আকারে পরিবর্তন করতে পারবেন এবং কমান্ডটি পুনরায় চালু করতে পারেন।

দয়া করে নোট করুন : প্রশ্নের উত্তরটিতে এই উত্তরটি ডাটাবেসকে utf8mb4_unicode_ciপরিবর্তে পরিবর্তিত করে utf8mb4_bin। তবে আপনি কেবল এটি প্রতিস্থাপন করতে পারেন।


দুর্দান্ত স্ক্রিপ্টিং, মাত্র কয়েকটি নোট; বর্তমান মিয়ারিয়াডিবি ইনস্টলগুলির জন্য পাসওয়ার্ড দেওয়ার প্রয়োজন হয়, তাই mysql -uroot -pThatrootPassWord < alterTables.sqlকাজ করে। এবং যেমনটি আপনি ইতিমধ্যে লক্ষ করেছেন, utf8mb4_bin হ'ল অন্যান্যদের মধ্যে পরের ক্লাউড প্রস্তাব দেয়।
জুলিয়াস

তবে utf8mb4_0900_ai_ci এখন ডিফল্ট, monolune.com/ কি-is- tut
জুলিয়াস

আমাকে "SET বিদেশী_কি_চেকস = 0;" ব্যবহার করতে হয়েছিল, তারপরে পরিবর্তনগুলি প্রয়োগ করুন, তারপরে "SET বিদেশী_কি_চেকস = 1;"।
dfrankow

আপনি মানুষ ধন্যবাদ. সবগুলি utf8mb4 এ পরিবর্তন করার জন্য এটি রেডমিনে সমাধান ছিল।
লুকিয়ানো ফ্যান্টুজি

5

আমি নিম্নলিখিত শেল স্ক্রিপ্ট ব্যবহার করেছি। এটি একটি প্যারামিটার হিসাবে ডাটাবেসের নাম নেয় এবং সমস্ত টেবিলকে অন্য একটি চরসেট এবং কোলেশনে রূপান্তর করে (স্ক্রিপ্টে সংজ্ঞায়িত অন্য পরামিতি বা ডিফল্ট মান দ্বারা দেওয়া)।

#!/bin/bash

# mycollate.sh <database> [<charset> <collation>]
# changes MySQL/MariaDB charset and collation for one database - all tables and
# all columns in all tables

DB="$1"
CHARSET="$2"
COLL="$3"

[ -n "$DB" ] || exit 1
[ -n "$CHARSET" ] || CHARSET="utf8mb4"
[ -n "$COLL" ] || COLL="utf8mb4_general_ci"

echo $DB
echo "ALTER DATABASE \`$DB\` CHARACTER SET $CHARSET COLLATE $COLL;" | mysql

echo "USE \`$DB\`; SHOW TABLES;" | mysql -s | (
    while read TABLE; do
        echo $DB.$TABLE
        echo "ALTER TABLE \`$TABLE\` CONVERT TO CHARACTER SET $CHARSET COLLATE $COLL;" | mysql $DB
    done
)

3

সমস্ত টেবিলের মধ্য দিয়ে চলার জন্য আমি ইনফরমেশন_সেমি (টেবিল এবং কলাম) ব্যবহার করার জন্য একটি স্ক্রিপ্ট লিখব (পার্ল বা অন্য যাই হোক না কেন), এবং প্রতিটি CHAR / VARCHAR / TEXT ক্ষেত্রে মোডেফাই কালামটি করব। আমি প্রতিটি টেবিলের জন্য সমস্ত মোডিফাইগুলি একক পরিবর্তে সংগ্রহ করব; এটি আরও দক্ষ হবে।

আমি মনে করি (তবে নিশ্চিত নই) রায়হানের পরামর্শটি কেবল টেবিলের জন্য ডিফল্ট পরিবর্তন করে ।


3

এই পরিস্থিতিতে দৌড়ে; আমি আমার ডাটাবেস রূপান্তর করতে ব্যবহার করা পদ্ধতির এখানে:

  1. প্রথমত, আপনাকে my.cnfডিফল্ট ডেটাবেস সংযোগ (অ্যাপ্লিকেশন এবং এমওয়াইএসকিউএল এর মধ্যে) utf8mb4_unicode_ci অনুগত করতে সম্পাদনা করতে হবে। ইমোজিসের মতো এই অক্ষরগুলি এবং আপনার অ্যাপ্লিকেশন দ্বারা জমা দেওয়া অনুরূপ অনুরোধগুলি ডান বাইট / এনকোডিংয়ে আপনার টেবিলগুলিতে তৈরি করবে না (যতক্ষণ না আপনার অ্যাপ্লিকেশনটির ডিবি সিএনএন প্যারাম একটি utf8mb4 সংযোগ নির্দিষ্ট করে না)।

    এখানে নির্দেশাবলী ।

  2. নিম্নলিখিত এসকিউএল কার্যকর করুন (স্বতন্ত্র কলাম পরিবর্তন করতে এসকিউএল প্রস্তুত করার দরকার নেই, ALTER TABLEবিবৃতিগুলি সেগুলি করবে)।

    আপনি নীচের কোডটি কার্যকর করার আগে "DbName" আপনার আসল ডিবি নামের সাথে প্রতিস্থাপন করুন।

    USE information_schema;
    
    SELECT concat("ALTER DATABASE `",table_schema,
                  "` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql
      FROM `TABLES`
     WHERE table_schema like "DbName"
     GROUP BY table_schema;
    
    SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,
                  "` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql
      FROM `TABLES`
     WHERE table_schema like "DbName"
     GROUP BY table_schema, table_name;
  3. উপরের এসকিউএল আউটপুট সংগ্রহ এবং সংরক্ষণ করুন একটি ডট স্কয়ার ফাইল এবং এটি সম্পাদন।

  4. যদি আপনি #1071 - Specified key was too long; max key length is 1000 bytes.সমস্যাযুক্ত টেবিলের নামের পাশাপাশি কোনও ত্রুটি পান তবে এর অর্থ সেই টেবিলের কিছু কলামে সূচি কী (যা এমবি 4 চর্চায় রূপান্তরিত হওয়ার কথা ছিল) খুব বড় হবে তাই বর্ণচর কলামটি <= 250 হওয়া উচিত সূচক কী সর্বোচ্চ 1000 বাইট হবে। আপনার যে কলামগুলিতে সূচী রয়েছে সেগুলি পরীক্ষা করুন এবং যদি সেগুলির একটির যদি ভারচার> 250 হয় (সম্ভবত 255) থাকে তবে

    • পদক্ষেপ 1: সেই কলামে সর্বোচ্চ স্ট্রিংয়ের আকার <= 250 হবে কিনা তা নিশ্চিত করতে সেই কলামটিতে ডেটা পরীক্ষা করুন।

      উদাহরণ ক্যোয়ারী:

      select `id`,`username`, `email`,
             length(`username`) as l1,
             char_length(`username`) as l2,
             length(`email`) as l3,
             char_length(`email`) as l4
        from jos_users
       order by l4 Desc;
    • পদক্ষেপ 2: যদি সূচিকৃত কলামের ডেটা সর্বাধিক দৈর্ঘ্য <= 250 হয় তবে কলটির দৈর্ঘ্য 250 এ পরিবর্তন করুন that যদি এটি সম্ভব না হয় তবে column কলামের সূচকটি সরিয়ে ফেলুন

    • পদক্ষেপ 3: তারপরে আবার সেই টেবিলের জন্য পরিবর্তিত টেবিল ক্যোয়ারীটি চালান এবং টেবিলটি এখন সফলভাবে utf8mb4 তে রূপান্তর করা উচিত।

চিয়ার্স!


দীর্ঘ 19 মার্চের চেয়ে বেশি অক্ষরের জন্য সূচক ব্যবহার করার উপায় রয়েছে। আপনার অবশ্যই ডিবিএ / সুপার ইউজার সুবিধাগুলি থাকতে হবে: ডাটাবেস প্যারামিটার সেট করা: ইনোডাব_লাজ_প্রিফিক্স: অন; ইনোডব_ফিল_ফর্ম্যাট: ব্যারাকুদা; ইনোডব_ফাই_ফর্ম্যাট_ম্যাক্স: ব্যারাকুদা;
চু হ্যাং লন

2

আমি এই গাইডটি লিখেছি: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-datedia-character-set-to-utf8mb4

আমার কাজ থেকে, আমি দেখেছি যে ডাটাবেস ও টেবিলগুলিতে ALTER করা যথেষ্ট নয়। আমাকে প্রতিটি টেবিলের মধ্যে যেতে হয়েছিল এবং প্রতিটি পাঠ্য / মিডিয়ামটেক্সট / বার্চার কলামগুলিকেও বদল করতে হয়েছিল।

ভাগ্যক্রমে আমি মাইএসকিউএল ডেটাবেসগুলির মেটাডেটা সনাক্ত করতে একটি স্ক্রিপ্ট লিখতে সক্ষম হয়েছি, যাতে এটি সারণী এবং কলামগুলির মধ্য দিয়ে লুপ হয়ে যায় এবং সেগুলি স্বয়ংক্রিয়ভাবে পাল্টে দেয়।

মাইএসকিউএল 5.6 এর জন্য দীর্ঘ সূচক:

আপনার অবশ্যই একটি কাজ করতে হবে ডিবিএ / সুপার ব্যবহারকারীর অধিকার: ডেটাবেস প্যারামিটার সেট করা:

ইনোডব_লাজ_প্রিফিক্স: চালু
ইনোডব_ফাই_ফর্ম্যাট: ব্যারাকুদা 
ইনোডব_ফাই_ফর্ম্যাট_ম্যাক্স: ব্যারাকুদা

এই প্রশ্নের উত্তরে, কীভাবে উপরের প্যারামিটারগুলি সেট করবেন সে সম্পর্কে নির্দেশনা রয়েছে: https://stackoverflow.com/questions/35847015/mysql-change-innodb-large-prefix

অবশ্যই, আমার নিবন্ধে, এটি করারও নির্দেশ রয়েছে।

মাইএসকিউএল সংস্করণ 5.7 বা তার থেকেও নতুনর জন্য, ইনোডাব_লাগ_প্রিফিক্স ডিফল্টরূপে চালু আছে, এবং ইননোডবি_ফিল_ফর্ম্যাটটি ডিফল্টরূপে বারাকুদাও।


2

এই সমস্যা থাকতে পারে এমন লোকদের জন্য সবচেয়ে ভাল সমাধান হ'ল এই টেবিল অনুসারে প্রথমে কলামগুলিকে বাইনারি টাইপে সংশোধন করা:

  1. চর => বিনারি
  2. পাঠ্য => ব্লগ
  3. TINYTEXT => TINYBLOB
  4. মিডিয়ামটেক্সট => মিডিয়ামব্লব
  5. লম্বটেক্সট => লংব্লব
  6. VARCHAR => VARBINARY

এবং তারপরে কলামটি তার পূর্বের প্রকারে এবং আপনার পছন্দসই চরসেটটি দিয়ে ফিরে করুন।

যেমন .:

ALTER TABLE [TABLE_SCHEMA].[TABLE_NAME] MODIFY [COLUMN_NAME] LONGBLOB;
ALTER TABLE [TABLE_SCHEMA].[TABLE_NAME] MODIFY [COLUMN_NAME] VARCHAR(140) CHARACTER SET utf8mb4;

আমি বেশ কয়েকটি লাতিন 1 টেবিলগুলিতে চেষ্টা করেছি এবং এটি সমস্ত ডায়াক্রিটিক্সকে রেখে দিয়েছে।

এটি করে সমস্ত কলামের জন্য আপনি এই ক্যোয়ারীটি বের করতে পারেন:

SELECT
CONCAT('ALTER TABLE ', TABLE_SCHEMA,'.', TABLE_NAME,' MODIFY ', COLUMN_NAME,' VARBINARY;'),
CONCAT('ALTER TABLE ', TABLE_SCHEMA,'.', TABLE_NAME,' MODIFY ', COLUMN_NAME,' ', COLUMN_TYPE,' CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;')
FROM information_schema.columns
WHERE TABLE_SCHEMA IN ('[TABLE_SCHEMA]')
AND COLUMN_TYPE LIKE 'varchar%'
AND (COLLATION_NAME IS NOT NULL AND COLLATION_NAME NOT LIKE 'utf%');

0

আমি একটি স্ক্রিপ্ট তৈরি করেছি যা এটি কম বেশি স্বয়ংক্রিয়ভাবে করে:

<?php
/**
 * Requires php >= 5.5
 * 
 * Use this script to convert utf-8 data in utf-8 mysql tables stored via latin1 connection
 * This is a PHP port from: https://gist.github.com/njvack/6113127
 *
 * BACKUP YOUR DATABASE BEFORE YOU RUN THIS SCRIPT!
 *
 * Once the script ran over your databases, change your database connection charset to utf8:
 *
 * $dsn = 'mysql:host=localhost;port=3306;charset=utf8';
 * 
 * DON'T RUN THIS SCRIPT MORE THAN ONCE!
 *
 * @author hollodotme
 *
 * @author derclops since 2019-07-01
 *
 *         I have taken the liberty to adapt this script to also do the following:
 *
 *         - convert the database to utf8mb4
 *         - convert all tables to utf8mb4
 *         - actually then also convert the data to utf8mb4
 *
 */

header('Content-Type: text/plain; charset=utf-8');

$dsn      = 'mysql:host=localhost;port=3306;charset=utf8';
$user     = 'root';
$password = 'root';
$options  = [
    \PDO::ATTR_CURSOR                   => \PDO::CURSOR_FWDONLY,
    \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
    \PDO::MYSQL_ATTR_INIT_COMMAND       => "SET CHARACTER SET latin1",
];


$dbManager = new \PDO( $dsn, $user, $password, $options );

$databasesToConvert = [ 'database1',/** database3, ... */ ];
$typesToConvert     = [ 'char', 'varchar', 'tinytext', 'mediumtext', 'text', 'longtext' ];

foreach ( $databasesToConvert as $database )
{
    echo $database, ":\n";
    echo str_repeat( '=', strlen( $database ) + 1 ), "\n";

    $dbManager->exec( "USE `{$database}`" );

    echo "converting database to correct locale too ... \n";

    $dbManager->exec("ALTER DATABASE `{$database}` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci");


    $tablesStatement = $dbManager->query( "SHOW TABLES" );
    while ( ($table = $tablesStatement->fetchColumn()) )
    {
        echo "Table: {$table}:\n";
        echo str_repeat( '-', strlen( $table ) + 8 ), "\n";

        $columnsToConvert = [ ];

        $columsStatement = $dbManager->query( "DESCRIBE `{$table}`" );

        while ( ($tableInfo = $columsStatement->fetch( \PDO::FETCH_ASSOC )) )
        {
            $column = $tableInfo['Field'];
            echo ' * ' . $column . ': ' . $tableInfo['Type'];

            $type = preg_replace( "#\(\d+\)#", '', $tableInfo['Type'] );

            if ( in_array( $type, $typesToConvert ) )
            {
                echo " => must be converted\n";

                $columnsToConvert[] = $column;
            }
            else
            {
                echo " => not relevant\n";
            }
        }


        //convert table also!!!
        $convert = "ALTER TABLE `{$table}` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";

        echo "\n", $convert, "\n";
        $dbManager->exec( $convert );
        $databaseErrors = $dbManager->errorInfo();
        if( !empty($databaseErrors[1]) ){
            echo "\n !!!!!!!!!!!!!!!!! ERROR OCCURED ".print_r($databaseErrors, true)." \n";
            exit;
        }


        if ( !empty($columnsToConvert) )
        {
            $converts = array_map(
                function ( $column )
                {
                    //return "`{$column}` = IFNULL(CONVERT(CAST(CONVERT(`{$column}` USING latin1) AS binary) USING utf8mb4),`{$column}`)";
                    return "`{$column}` = CONVERT(BINARY(CONVERT(`{$column}` USING latin1)) USING utf8mb4)";
                },
                $columnsToConvert
            );

            $query = "UPDATE IGNORE `{$table}` SET " . join( ', ', $converts );

            //alternative
            // UPDATE feedback SET reply = CONVERT(BINARY(CONVERT(reply USING latin1)) USING utf8mb4) WHERE feedback_id = 15015;


            echo "\n", $query, "\n";


            $dbManager->exec( $query );

            $databaseErrors = $dbManager->errorInfo();
            if( !empty($databaseErrors[1]) ){
                echo "\n !!!!!!!!!!!!!!!!! ERROR OCCURED ".print_r($databaseErrors, true)." \n";
                exit;
            }
        }

        echo "\n--\n";
    }

    echo "\n";
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.