TYPO3 med utf8-innehåll i latin1-MySQL

Olika characterset kan enkelt bli en riktig soppa om man inte ser till att ställa in allting rätt innan man börjar köra sin databas. Här är ett exempel på hur man kan fixa ett problem som jag råkade ut för.

Vid en flytt av en MySQL-databas mellan två maskiner blev plötsligt alla specialtecken fel. Det är enkelt att konstatera att det är ett utf8-relaterat problem när man ser att varje specialtecken blivit två ännu konstigare tecken, men inte fullt så enkelt att lösa.

Default characterset i databas och tabeller ser bra ut:

mysql> show create database www_example_com;
+-------------------+----------------------------------------------------------------------------+
| Database          | Create Database                                                            |
+-------------------+----------------------------------------------------------------------------+
| www_example_com   | CREATE DATABASE `www_example_com` /*!40100 DEFAULT CHARACTER SET utf8 */   | 
+-------------------+----------------------------------------------------------------------------+
1 row in set (0.00 sec)
    
mysql> show create table pages G
*************************** 1. row ***************************
   Table: pages
Create Table: CREATE TABLE `pages` (
  `uid` int(11) NOT NULL auto_increment,
  `pid` int(11) NOT NULL default '0',
  `t3ver_oid` int(11) NOT NULL default '0',
 
    ...etc...
    
  `backend_layout_next_level` int(10) NOT NULL default '0',
  `tx_realurl_pathoverride` int(1) NOT NULL default '0',
  `tx_realurl_nocache` int(1) NOT NULL default '0',
  PRIMARY KEY  (`uid`),
  KEY `t3ver_oid` (`t3ver_oid`,`t3ver_wsid`),
  KEY `alias` (`alias`),
  KEY `parent` (`pid`,`sorting`,`deleted`,`hidden`),
  KEY `dummy` (`tx_oelib_is_dummy_record`)
) ENGINE=MyISAM AUTO_INCREMENT=373 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

Inställningarna på servern ser lite mystiska ut:

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     | 
| character_set_connection | latin1                     | 
| character_set_database   | utf8                       | 
| character_set_filesystem | binary                     | 
| character_set_results    | latin1                     | 
| character_set_server     | latin1                     | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

En skön blandning av utf8 och latin1. En ren mysqldump av databasen blir fel, t.ex. Malmö blir Malmö. MySQL gör utf8 av latin1:s representation av utf8-tecken!

Eftersom systemet fungerar vill jag inte röra någon av inställningarna i servern.

Genom att lägga till –default-character-set=latin1 till mysqldump kan man tvinga MySQL att nöja sig med att skicka ut det som faktiskt står i databasen, vilket egentligen redan är i utf8-format.

mysqldump -r dump.sql --default-character-set=latin1 -u root -p www_example_com

Nu ser allting rätt ut i dumpfilen.

Se till att nya servern kör utf8 genom att lägga till följande i mysqls konfiguration:

[mysqld]
default_character_set = utf8
    
[mysql]
default_character_set = utf8

Kolla så att nya servern enbart kör utf8:

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

Jag var tvungen lägga till följande rad överst i dump-filen för att det skulle bli rätt vid inläsningen:

SET NAMES utf8;

Skillnaden efter importen syns direkt i mysql-klienten genom att köra select på en tabell med många specialtecken, t.ex:

SELECT title FROM pages;

Mer information om TYPO3 och utf8 finns här: http://wiki.typo3.org/UTF-8_support