웹 서버를 또 바꾸었다. 새 서버에는 MySQL 5.0이 설치되어 있었다. 덕분에 그동안 미뤄왔던 마이그레이션 작업을 해야 했다. 블로그 엔진 ExpressionEngine1과 웹 기반 RSS 리더 Gregarius2부터 마이그레이션해 봤다. 작업 과정을 간단히 정리해본다.

공통 작업

기존 MySQL 데이터를 내려 받아서 새 데이터베이스로 옮겨야 한다.
  1. 덤프 파일 내려받기

    mysqldump -u{username} -p{password} {dbname} --default-character-set latin1 > {dump}.sql
  2. 내려받은 덤프 파일의 텍스트 인코딩 변환하기

    Iconv 같은 변환 도구를 사용하기도 하지만, 파일이 아주 크지는 않아서 텍스트 편집기를 사용했다. Notepad++3로 덤프 파일을 열어서 UTF-8로 다시 인코딩했다.
  3. 덤프 파일 수정하기

    우선 덤프 파일 첫 줄에 SET character set utf8;을 추가했다. 그리고 CREATE TABLE 구문 끝을 TYPE=MyISAM에서 TYPE=MyISAM DEFAULT CHARSET=utf8;로 바꾸었다.
  4. 옮기기

    mysql -u{username} -p{password} {dbname} < {dump}.sql

ExpressionEngine

키워드 모듈 수정하기

웹 브라우저에 다음과 같은 메시지가 출력됐다.
  1. MySQL ERROR:   
  2.     Error Number: 1054   
  3.     Description: Unknown column wt.weblog_id in on clause   
  4.   
  5.     Query: SELECT DISTINCT wt.entry_id, SUM(if(keyword=test,1,0)) as threshold, title, url_title, ?? AS category_id FROM exp_weblog_titles wt, exp_keyword k LEFT JOIN exp_weblogs w ON wt.weblog_id = w.weblog_id LEFT JOIN exp_weblog_data wd ON wt.entry_id = wd.entry_id LEFT JOIN exp_members m ON m.member_id = wt.author_id LEFT JOIN exp_member_data md ON md.member_id = m.member_id LEFT JOIN exp_keyword_layers l ON l.layer_id = k.layer_id WHERE wt.entry_id=k.entry_id /* begin _build_where_query */ AND wt.entry_date < 1136085621 AND (wt.expiration_date = 0 || wt.expiration_date > 1136085621) AND w.is_user_blog = ?n? AND wt.status = ?open? /* end _build_where_query */ GROUP BY wt.entry_id HAVING threshold >= 1   
MySQL ERROR:
    Error Number: 1054
    Description: Unknown column wt.weblog_id in on clause

    Query: SELECT DISTINCT wt.entry_id, SUM(if(keyword=test,1,0)) as threshold, title, url_title, ?? AS category_id FROM exp_weblog_titles wt, exp_keyword k LEFT JOIN exp_weblogs w ON wt.weblog_id = w.weblog_id LEFT JOIN exp_weblog_data wd ON wt.entry_id = wd.entry_id LEFT JOIN exp_members m ON m.member_id = wt.author_id LEFT JOIN exp_member_data md ON md.member_id = m.member_id LEFT JOIN exp_keyword_layers l ON l.layer_id = k.layer_id WHERE wt.entry_id=k.entry_id /* begin _build_where_query */ AND wt.entry_date < 1136085621 AND (wt.expiration_date = 0 || wt.expiration_date > 1136085621) AND w.is_user_blog = ?n? AND wt.status = ?open? /* end _build_where_query */ GROUP BY wt.entry_id HAVING threshold >= 1 
원인과 해결책은 Keyword Module progress5에 잘 나와있다. MySQL 5.0에서는 FROM exp_weblog_titles wt, exp_keyword k과 같이 비명시적으로 조인하는 것을 허용하지 않으니 FROM exp_weblog_titles wt INNER JOIN exp_keyword k과 같이 수정해야 한다. {EE system dir}/{modules}/{keyword}/mod.keyword.php 파일을 열어서 위와 같이 코딩된 부분을 전부 바꿔주면 된다.

???로 표시되는 웹 페이지

한글이 모두 깨져서 보였다. 이 문제도 역시 소스 코드를 수정해야만 해결된다. {EE dir}/db/db.mysql.php 파일을 연다.
  1. // Execute the query   
  2. if ( ! $this->query_id = mysql_query($sql$this->conn_id))   
  3. {   
  4.     if ($this->debug)   
  5.     {   
  6.         return $this->db_error("MySQL ERROR:"$this->conn_id, $sql);   
  7.     }   
  8.   
  9.   return FALSE;   
  10. }  
// Execute the query
if ( ! $this->query_id = mysql_query($sql, $this->conn_id))
{
    if ($this->debug)
    {
        return $this->db_error("MySQL ERROR:", $this->conn_id, $sql);
    }

  return FALSE;
}
위의 코드에 한 줄만 추가하면 된다.
  1. mysql_query('SET NAMES utf8');   
  2.   
  3. // Execute the query   
  4. if ( ! $this->query_id = mysql_query($sql$this->conn_id))   
  5. {   
  6.     if ($this->debug)   
  7.     {   
  8.         return $this->db_error("MySQL ERROR:"$this->conn_id, $sql);   
  9.     }   
  10.   
  11.   return FALSE;   
  12. }  
mysql_query('SET NAMES utf8');

// Execute the query
if ( ! $this->query_id = mysql_query($sql, $this->conn_id))
{
    if ($this->debug)
    {
        return $this->db_error("MySQL ERROR:", $this->conn_id, $sql);
    }

  return FALSE;
}

Gregarius 이전하기

ExpressionEngine과 마찬가지로 한글이 ???로 표시됐다. 마찬가지로 소스 코드를 수정했다. {gregarius dir}/cls/db/db.mysql.php 파일을 열어서 mysql_query('SET NAMES utf8'); 한 줄을 추가하면 끝이다.
  1. function rss_query ($query$dieOnError=true, $preventRecursion=false) {   
  2.      mysql_query('SET NAMES utf8');   
  3.   
  4.      $ret =  mysql_query($query);   
  5.   
  6.      if ($error = $this -> rss_sql_error()) {   
  7.               $errorString = $this -> rss_sql_error_message();   
  8.      }  
function rss_query ($query, $dieOnError=true, $preventRecursion=false) {
     mysql_query('SET NAMES utf8');

     $ret =  mysql_query($query);

     if ($error = $this -> rss_sql_error()) {
              $errorString = $this -> rss_sql_error_message();
     }

참고 문헌

Links

  1. http://www.pmachine.com/
  2. http://gregarius.net/
  3. http://notepad-plus.sourceforge.net/
  4. http://kaistizen.net/EE/index.php/weblog/comments/migrate_mysql_40x_to_50/#
  5. http://www.pmachine.com/forums/viewthread/27030/P108/
  6. http://www.abcseo.com/papers/utf8-expression-engine.htm