2016-05-20 4 views
0

У меня есть довольно большая база данных, которую я пытаюсь преобразовать из кодировки и сортировки latin1/latin1_swedish_ci в utf8mb4/utf8mb4_unicode_ci. Я надеюсь настроить репликацию на подчиненный, запустить преобразование, а затем продвигать ведомое устройство, когда оно завершено, чтобы избежать простоев.MySQL конвертировать в UTF8 без изменения структуры

я заметил, что при выполнении запроса ...

ALTER TABLE `sometable` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 

... MySQL автоматически преобразует text в mediumtext или mediumtext к longtext и т.д.

Есть ли способ, чтобы отключить эту функцию ? Приятно, что MySQL имеет эту функцию, но проблема в том, что она прерывает репликацию, потому что структура таблиц на ведомом отличается от основной.

+0

Я помню, как читал тему об этом здесь, и там была середина поворота символа, установленного в «BLOB' * then *, на набор символов« UTF8mb4 », но моя память является отрывочной. Кроме того, имеет значение, к чему это обращает? Это влияет только на длину данных, насколько мне известно, поэтому когда-то преобразован просто в таблицу ALTER, чтобы изменить средний текст на все, что вы хотите ... (?) – Martin

+0

Является ли это 'mediumtext' или' text', не имеет значения; важно то, что он не меняется. Если у вас есть настройка master-> slave-репликации и вы хотите сначала запустить преобразование на подчиненном устройстве, репликация будет нарушена, когда мастер попытается вставить новые данные в подчиненный. Структура двух таблиц не будет одинаковой. –

+1

Если я правильно помню, причина, по которой MySQL расширяет размеры текста, заключается в том, что 'utf8mb4' использует 4 байта на символ вместо 3, так что, если у вас есть максимальное количество символов в' latin1_', он будет переполнять и обрезать один и тот же размер байта в 'utf8mb4' – Martin

ответ

2

Как указано под ALTER TABLE Syntax:

Для столбца, имеющего тип данных VARCHAR или один из TEXT типов, CONVERT TO CHARACTER SET будет изменить тип данных, необходимую для обеспечения того, чтобы новый столбец достаточно долго хранить как можно больше символов, чем исходный столбец. Например, столбец TEXT имеет два байта длины, которые сохраняют байтовую длину значений в столбце, максимум до 65535. Для столбца latin1TEXT каждому символу требуется один байт, поэтому столбец может хранить до 65 535 символов. Если столбец преобразуется в utf8, каждому символу может потребоваться до трех байтов для максимально возможной длины 3 × 65 535 = 196 605 байт. Эта длина не будет соответствовать байтам длины столбца TEXT, поэтому MySQL преобразует тип данных в MEDIUMTEXT, что является наименьшим типом строки, для которого длина байтов может записывать значение 196 605. Аналогично, столбец VARCHAR может быть преобразован в MEDIUMTEXT.

Чтобы избежать изменений типа данных только что описанного типа, не используйте CONVERT TO CHARACTER SET. Вместо этого используйте MODIFY для изменения отдельных столбцов. Например:

ALTER TABLE t MODIFY latin1_text_col TEXT CHARACTER SET utf8; 
ALTER TABLE t MODIFY latin1_varchar_col VARCHAR(M) CHARACTER SET utf8;
0

Случай 1 (на самом деле не ответ, но некоторые иллюстративные примеры.): Текст правильно хранится как latin1 в latin1 колонке; использовать Преобразовать в

mysql>  CREATE TABLE alters (
    ->   c VARCHAR(11) CHARACTER SET latin1 NOT NULL 
    -> ); 

mysql>  INSERT INTO alters (c) VALUES ('aabc'), (UNHEX('61e06263')), (UNHEX('61e16263')); 

mysql>  SELECT c, HEX(c) from alters; 
+-------+----------+ 
| c  | HEX(c) | 
+-------+----------+ 
| aabc | 61616263 | 
| aàbc | 61E06263 | 
| aábc | 61E16263 | 
+-------+----------+ 

mysql>  ALTER TABLE alters CONVERT TO CHARACTER SET utf8; 

mysql>  SELECT c, HEX(c) from alters; 
+-------+------------+ 
| c  | HEX(c)  | 
+-------+------------+ 
| aabc | 61616263 | 
| aàbc | 61C3A06263 | 
| aábc | 61C3A16263 | 
+-------+------------+ 

mysql>  -- Observation: text was correctly converted to utf8. 

mysql>  SHOW CREATE TABLE alters\G 
Create Table: CREATE TABLE `alters` (
    `c` varchar(11) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

Случай 2: Текст правильно хранится в виде latin1 в latin1 колонке; использовать "Двойной" ALTER

mysql>  CREATE TABLE alters (
    ->   c VARCHAR(11) CHARACTER SET latin1 NOT NULL 
    -> ); 

mysql>  INSERT INTO alters (c) VALUES ('aabc'), (UNHEX('61e06263')), (UNHEX('61e16263')); 

mysql>  ALTER TABLE alters MODIFY c VARBINARY(11) NOT NULL; 

mysql>  ALTER TABLE alters MODIFY c VARCHAR(11) CHARACTER SET utf8 NOT NULL; 
Query OK, 3 rows affected, 2 warnings (0.10 sec) 
Records: 3 Duplicates: 0 Warnings: 2 

mysql>  SHOW WARNINGS; 
+---------+------+----------------------------------------------------------+ 
| Level | Code | Message             | 
+---------+------+----------------------------------------------------------+ 
| Warning | 1366 | Incorrect string value: '\xE0bc' for column 'c' at row 2 | 
| Warning | 1366 | Incorrect string value: '\xE1bc' for column 'c' at row 3 | 
+---------+------+----------------------------------------------------------+ 

mysql>  SELECT c, HEX(c) from alters; 
+------+----------+ 
| c | HEX(c) | 
+------+----------+ 
| aabc | 61616263 | 
| a | 61  | 
| a | 61  | 
+------+----------+ 

mysql>  -- Observation: text was truncated ! BAD 

mysql>  SHOW CREATE TABLE alters\G 
Create Table: CREATE TABLE `alters` (
    `c` varchar(11) CHARACTER SET utf8 NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Случай 3: Текст был неправильно хранится в виде utf8 в latin1 колонке; использовать «Double ALTER исправить это

mysql>  CREATE TABLE alters (
    ->   c VARCHAR(11) CHARACTER SET latin1 NOT NULL 
    -> ); 

mysql>  INSERT INTO alters (c) VALUES ('aabc'), (UNHEX('61c3a06263')), (UNHEX('61c3a16263')); 

mysql>  ALTER TABLE alters MODIFY c VARBINARY(11) NOT NULL; 
mysql>  ALTER TABLE alters MODIFY c VARCHAR(11) CHARACTER SET utf8 NOT NULL; 

mysql>  SELECT c, HEX(c) from alters; 
+-------+------------+ 
| c  | HEX(c)  | 
+-------+------------+ 
| aabc | 61616263 | 
| aàbc | 61C3A06263 | 
| aábc | 61C3A16263 | 
+-------+------------+ 

mysql>  SHOW CREATE TABLE alters\G 
Create Table: CREATE TABLE `alters` (
    `c` varchar(11) CHARACTER SET utf8 NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Случай 4: Использование ALTER ...ИЗМЕНИТЬ; обратите внимание, длину и CHAR_LENGTH

mysql>  CREATE TABLE alters (
    ->   c VARCHAR(9) CHARACTER SET latin1 NOT NULL 
    -> ); 

mysql>  INSERT INTO alters (c) VALUES ('aabc'), (UNHEX('61e06263')), 
    ->     (UNHEX('61e16263')), 
    ->     (UNHEX('61e162633536373839')); 

mysql>  SELECT c, HEX(c), LENGTH(c), CHAR_LENGTH(c) from alters; 
+------------+--------------------+-----------+----------------+ 
| c   | HEX(c)    | LENGTH(c) | CHAR_LENGTH(c) | 
+------------+--------------------+-----------+----------------+ 
| aabc  | 61616263   |   4 |    4 | 
| aàbc  | 61E06263   |   4 |    4 | 
| aábc  | 61E16263   |   4 |    4 | 
| aábc56789 | 61E162633536373839 |   9 |    9 | 
+------------+--------------------+-----------+----------------+ 

mysql>  ALTER TABLE alters MODIFY c VARCHAR(9) CHARACTER SET utf8 NOT NULL; 

mysql>  SELECT c, HEX(c), LENGTH(c), CHAR_LENGTH(c) from alters; 
+------------+----------------------+-----------+----------------+ 
| c   | HEX(c)    | LENGTH(c) | CHAR_LENGTH(c) | 
+------------+----------------------+-----------+----------------+ 
| aabc  | 61616263    |   4 |    4 | 
| aàbc  | 61C3A06263   |   5 |    4 | 
| aábc  | 61C3A16263   |   5 |    4 | 
| aábc56789 | 61C3A162633536373839 |  10 |    9 | 
+------------+----------------------+-----------+----------------+ 

mysql>  SHOW CREATE TABLE alters\G 
Create Table: CREATE TABLE `alters` (
    `c` varchar(9) CHARACTER SET utf8 NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 
1 row in set (0.00 sec) 

Примечание:

  • Нет предупреждений для одного случая, когда я сделал ШОУ исключения.
  • Таблица по умолчанию CHARSET не была изменена, но это не проблема.
Смежные вопросы