'tip'에 해당되는 글 1건

  1. 2004/08/05 MySQL Tip

MySQL Tip

2004/08/05 09:51


클라이언트의 문자셋에 상관없이 서버의 문자셋에 따르기

[service:mysqld]
default-character-set = utf8
character-set-client-handshake = FALSE

my.cnf 에 지정.

필드내의 특정문자 이후의 데이터를 비교하기

메일주소에서 같은 도메인을 가지는 필드끼리의 비교.

mysql> SELECT count(*) FROM mail_header WHERE \
SUBSTRING(from_address,POSITION('@' in from_address))= \
SUBSTRING(sender,POSITION('@' in sender)) AND from_address<>''

SUBSTRING('abc@sds.co.kr', POSITION('@' in 'abc@sds.co.kr')+1)

덤프시에 한줄로 덤프되는것을 조절하는 옵션 (default-character-set 주의)

--skip-opt 를 사용하면 한줄로 덤프되어서 insert 시에 곤란한것을 조절하는 옵션

--default-character-set=euckr --set-charset --skip-opt --add-drop-table --add-locks --disable-keys --create-options

기본설정된 DB 의 경우 문자셋은 --default-character-set=latin1 을 사용하면 정상적인 한글데이터를 받을수 있다.

--default-character-set=latin1 --set-charset --skip-opt --add-drop-table --add-locks --disable-keys --create-options

PHP 에서 문자셋이 맞지 않을 경우

mysql 스키마로는 정상적으로 보이지만, PHP 로 접속할 경우 제대로 나오지 않을 경우 다음과 같이 설정. (디폴트 테이블이 latin1 으로 되어 있는 경우)

$query = "SET CHARACTER SET 'latin1'";
if (!mysql_query ($query, $link)) die ($query.":".mysql_error($link));

  • 추정하건데 아파치-PHP 를 통하여 접속할 경우, 아파치의 문자셋 'euckr' 로 설정되는 것으로 보임.

Load data infile

1)MySQL 서버 내에 불러올 파일이 있을 경우

mysql> load data infile '파일명' into table 테이블명

2)Web서버에서 데이터가 있을때 원격으로 처리 할 경우

mysql> load data local infile '파일명' into table 테이블명

두 문장의 차이는 불러오려는 파일이 MySQL 서버에 있느냐? 아니면 원격에서 접속해서 처리하느냐이다.

local 명령어를 추가해서 사용할 경우에는 서버와 클라이언트 모두 local-infile옵션이 on으로 되어 있어야만 사용가능 하며 그에 따른 확인은 아래와 같이 할 수 있다.

mysql> show variables like 'local%';

위와 같은 명령어를 내렸을때 local-infile이 On 으로 되어 있으면 사용이 가능한거다.

클라이언트에서 연결할때 사용하는 명령어는 아래와 같다.

$> mysql -u 아이디 -p -h 서버명 DB명 --local-infile=1

C API 에서 접속된 커넥션의 문자셋 변경하는 함수.


보통 default 세팅은 latin1 이다. 다른 외부DB 서버에 접속할시에 로컬서버의 문자셋이 디폴트로 적용되는데, 서버에 따라서 문자셋을 변경해야 할 필요가 있을시에 필요한 함수이다. 보통 문자셋이 다를수 있는경우가 대부분이므로 기본으로 넣어주는것이 나중에 DB 나 클라이언트가 재설치 될경우에 다시 조정하는 문제를 없앨수 있다.

// 문자셋 지정
if (mysql_set_character_set (&mysql[0], "utf8") != 0)
{
PutLog (log_path, __FILE__, __LINE__, LOG_CRIT, 0,
"source database character set 'utf8' setting faild : %s", mysql_error (&mysql[0]));
mysql_close (&mysql[0]);
exit (-1);
}

MySQL DBMS 복구

  • DB 별로 복구
    # /usr/bin/mysqlcheck --auto-repair cacti
    cacti.L3host OK
    cacti.account OK
    cacti.cdef OK
    cacti.cdef_items OK
    cacti.colors OK
    cacti.data_input OK
    cacti.data_input_data OK
    cacti.data_input_fields OK
    cacti.data_local OK
    c
    ...
    cacti.snmp_query_graph_rrd OK
    cacti.snmp_query_graph_rrd_sv OK
    cacti.snmp_query_graph_sv OK
    cacti.tab
    warning : Found row where the auto_increment column has the value 0
    status : OK
    cacti.user_auth OK
    cacti.user_auth_perms OK
    cacti.user_auth_realm OK
    cacti.user_log OK
    cacti.version OK
    #

  • 테이블별로 복구 (테이블간의 영향으로 복구되지 않을수 있다. mysqlcheck 우선)
    # myisamchk -r -f *.MYI

MySQL 의 export / import 시의 문자셋

default-character-set 이란?

mysqldump 에서 문자셋이 의외로 까다로운 부분이 있다. 일단 서버의 문자셋은 /etc/my.cnf 에 지정된 default-character-set 에 따른다. defualt 세팅은 latin1 이며, 대부분 따로 설정해 두지 않기 때문에 latin1 으로 설정되는 것이 대부분이다. 이때부터 mysqldump 로 나온 데이터를 옮기는데, 난관에 봉착하게 되는것 같다.

일단 권장사항은, mysql 설치직후 /etc/my.conf 에 default-character-set 을 구체적으로 지정한다. utf8 또는 euckr 을 지정하는것이 좋을것이다. 그런데 이 default-character-set 어디까지나 default 문자셋 으로서, 테이블별로 개별로 문자셋을 지정할 수 있다. 지정 방법은 테이블 생성시의 끝에 DEFAULT CAHRSET=utf8 등으로 설정하는 것이다. 아래는 예제이다.

CREATE TABLE `g4_auth` (
`mb_id` varchar(85) NOT NULL default '',
`au_menu` varchar(6) NOT NULL default '',
`au_auth` set('r','w','d') NOT NULL default '',
PRIMARY KEY (`mb_id`,`au_menu`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

물론 문자셋을 지정하지 않으면, default-character-set 문자셋으로 테이블이 생성되게 된다.

mysqldump 로 export 시에 문자셋

mysqldump 로 데이터를 받을 경우를 비교해 본다.

우선 default 로 export 를 한 경우이다.

# mysqldump -u root -p server > default.sql
# more default.sql
-- MySQL dump 10.9
--
-- Host: localhost Database: serve
-- ------------------------------------------------------
-- Server version 4.1.22-standard

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `g4_auth`
--

DROP TABLE IF EXISTS `g4_auth`;
CREATE TABLE `g4_auth` (
`mb_id` varchar(85) NOT NULL default '',
`au_menu` varchar(6) NOT NULL default '',
`au_auth` set('r','w','d') NOT NULL default '',
PRIMARY KEY (`mb_id`,`au_menu`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

다음에는 문자셋을 지정해서 받은 경우이다.

# mysqldump -u root -p --default-character-set=latin1 serve > latin1.sql
# more latin1.sql
-- MySQL dump 10.9
--
-- Host: localhost Database: serve
-- ------------------------------------------------------
-- Server version 4.1.22-standard
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `g4_auth`
--

DROP TABLE IF EXISTS `g4_auth`;
CREATE TABLE `g4_auth` (
`mb_id` varchar(85) NOT NULL default '',
`au_menu` varchar(6) NOT NULL default '',
`au_auth` set('r','w','d') NOT NULL default '',
PRIMARY KEY (`mb_id`,`au_menu`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

무었이 다른지 구분할 수 있는가? 그렇다 헤더부분이 다르다.

/*!40101 SET NAMES utf8 */;

이것은 MySQL 매뉴얼에서 "SET NAMES indicates what character set the client will use to send SQL statements to the server." 라고 말하고 있다. 즉 접속클라이언트가 보내는 문자셋을 나타낸다는 것이다. 즉 mysqldump 가 디폴트 문자셋을 지정하지 않고, dump 했을 경우 문자셋을 지정하는 명령이 포함되어 있다. 대부분 이것을 커맨트로 생각하고, 무시하는 경향이 있는데, 다른말로 표현하면 import 시에 해당 데이터가 투입되는 문자셋를 지정하는 효과가 있다. 즉 데이터를 투입하는 클라이언트의 문자셋을 지정하는 것이다. default 로 dump 를 받았을 경우에 터미널에서는 문자가 보이는데, import 를 하게 되면 문자가 깨지는 경우에는 이 SET NAMES 문자셋이 클라이언트와 일치 하지 않은 경우이므로 이 문장을 지우고 import 하면 대부분 보이는대로 데이터가 들어간다.

정확하게 말하면

mysql 에서의 import

import 할때에 주의할것은 다음과 같다.

  • export 한 파일이 터미널 상에서 잘보이는가? (LANG 변수와 터미널 문자셋 - putty 의 경우: utf8 와 cp949 - euckr 의 확실한 구분)
  • export 한 파일의 헤더부분의 SET NAMES 가 터미널의 상태와 일치하는가?
  • export 한 파일의 테이블별로 지정되어 있는 DEFAULT CHARSET 가 일치하는가?

이 3가지 부분을 확인하고 import 하게 되면, 정상적으로 들어갈것 이다. mysql 스키마에서는 제대로 나오는데, PHP 에서 제대로 보여지지 않는다면, "PHP 에서 문자셋이 맞지 않을 경우" 를 참조한다.

데이터는 빼고 DUMP 받기

  • "-d" 옵션을 사용하면 데이터는 빼고 구조만 dump 받는다.
$ /usr/local/mysql/bin/mysqldump -u dbs -d -p dbs > dbs.sql
Enter password:

설치 후 보안
  • test db 삭제
  • db에서 test 관련부분 삭제
  • root 사용자 비밀번호 추가
    # mysqladmin drop test
    # mysql mysql
    mysql> delete from db where db like 'test%';
    mysql> grant all privileges on*.* to root@localhost identified by 'xxxxx';

utf8 설정

mysql 4.1 에서는 /etc/my.cnf 등에서

[service:mysqld], [service:mysqldump], [service:mysql]
에 utf8을 지정해준다.
default-character-set = utf8

mysql 팁

  • 스토어드 프로세져, 트리거 제한사항중 한가지
    mysql 5.0 버전에서 stored routines (stored procedures, stored fucntions)과 트리거에서의 제한사항이 있습니다. stored function 또는 트리거의 경우, function 이나 트리거를 호출한 명령문에서 사용한 테이블은 변경을 할 수 없습니다.

참고자료 http://dev.mysql.com/doc/refman/5.0/en/ ··· ons.html
I.1. Restrictions on Stored Routines and Triggers
Within a stored function or trigger, it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.

5.1 mysql (베타버전임) 매뉴얼에도 동일한 제한이 그대로 유지되고 있습니다.
http://dev.mysql.com/doc/refman/5.1/en/ ··· ons.html

mysql 5.0 rpm 설치시 주의사항

  • mysql.com 에서 5.0을 다운로드 받아 설치하였다. 초기설치시는 localhost 에서 root 권한으로만 접속을 할 수 있고 비밀번호 설정이 되어 있지 않은데도 접속이 거부가 되었다. 테스팅결과 비밀번호가 들어있지 않아도 -p 옵션을 요구하는 것이다. mysql 이 버전업을 하면서 보안때문에 일부러 그랬는지는 모르겠다.
  • 팁 : root 비밀번로 잃어버렸을때 http://dev.mysql.com/doc/refman/5.0/en/ ··· ons.html
[service:root@mytest log]# mysqladmin version
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: YES)'

[service:root@mytest log]# mysqladmin version -p
Enter password:

Server version 5.0.24a-standard
  • 참고로 mysql 의 rpm 설치과정은 다음과 같다. 설치스크립트에서 자동시작스크립트를 등록하고 mysql user, mysql group을 만들어준다음 /usr/bin/mysql_install_db --rpm --user=mysql 를 실행하여 초기 mysql 디렉토리의 db를 생성해주는 것이다. 만약 mysql 권한관련 디렉토리를 날렸다면 mysql_install_db 를 다시 실행해주면 mysql db, test db를 생성하여준다.
[service:root@mytest log]# rpm -q --scripts MySQL-server-standard

Mysql 5.1

1. Hash 파티션 지원

Range-Partition

데이터를 일정한 기간을 주기로 다른 물리적인 파티션에 나눌 수 있다.
예를 들면 파티션을 3개로 나눌 경우 첫 번째 파티션에는 1980년대 자료를 1990년대 자료는 두 번째 파티션에
나머지 자료(2000년대 포함)는 세 번째 파티션에 저장하게 할 수 있습니다.

List-Partition

데이터를 일정한 단위로 나눌 수 있습니다.
예를 들면 첫 번째 파티션에는 1월 자료를 두 번째 파티션에는 2월 자료를 세 번째 파티션에는
3월 자료를 나누어 보관할 수 있습니다.

여러 개의 테이블들을 모두 하나의 primary key로 묶을 수 있다.
또한 이 키는 시스템에서 생성된 hash 키로 지정될 수 있습니다.

Composite-Partition

Range와 List Partition을 합쳐서 사용 할 수 있습니다.

생각

이런 파티셔닝 기술은 오라클에서 hashing function을 사용하여 data를 분산하는 기능을 mysql에서 구현한 것입니다.
mysql이 점점 oracle을 닮아 간다고 할 수 있겠습니다.

그러나 table이 여러 개의 partition으로 구성된 경우
만일 range 나 list partition이라면 row의 partition key 값에 따라 해당 partition으로 data 가 들어갑니다. 이 경우 어떤 Data가 어떤 partition에 들어 있는지 쉽게 알 수 있으나 data가 특정 partition에 몰려 들어갈 수 있습니다.

예로 월별 partition된 table인 경우 특정 월에 해당하는 data가 많다면 (예로 3월) 3월을 담고 있는 partition의 크기가 커지게 되고 IO가 3월 partition 에 많이 발생하니깐 조치 않게 됩니다.

만약 data가 여러 partition에 고르게 들어가 있다면 3월 data가 어느 partition에 있는지는 모르지만 3월 data가 여러 partition에 걸쳐 들어가 있기 때문에 또 각 partition의 크기도 비교적 비슷하게 관리되므로 IO의 효과가 좋게 됩니다. 그래서 hash partition은 IO의 효과를 보기 위해 table을 partition할 때 씁니다.

좀더 말씀 드리면 range partition과 hash partition을 결합하여 composite partition 이라는 게 있는데 이는 range partition의 단점이 IO의 문제를 해결하기 위해 하나의 range partition을 또 hash partition으로 쪼개는 것입니다.

Full-Text Search 기능 향상

Full-Text Search란?

간단하게 검색 어를 "다리"로 검색했을 때
다리와 관련된 단어가 검색되게 되는데
보통 String Search는 다리와 연관 없는 단어(예: "기다리고", "다리미")같은 단어도 같이 검색되게 됩니다.
보다 정확한 검색을 위해 사용하는 것이 Full-Text 검색 방식입니다.

Mysql 5.1에서는 이 Full-Text Search 기능이 많은 부분 향상되었습니다.
아직 5.1 버전은 베타 판이며 아직 MyISAM은 시간이 조금 걸린다고 합니다.
5.1 정식 판이 발표되면 확실한 성능 향상을 기대할 수 있습니다.

Xpath 지원

XXML Path Language나 XML을 이용한 URIs를 용의하게 조작할 수 있게 됐습니다.

보통 DBMS는 String값으로 Mysql에 질의를 받게 됩니다.
Mysql 5.1에서는 XML값으로도 질의를 받을 수 있게 되었습니다.

Archive 엔진 향상

보다 빠르고 메모리는 덜 먹고 I/O는 줄어 들었습니다.

이 부분은 실제로 옵션으로 이루어 지는데 실제로 퍼포먼스 테스트를 하기 전까지는 알 수 없는 부분입니다.

저는 mysql 3.23 버전이 가장 빠르고 안정적이었다고 생각하고 있습니다.(MyISAM기준)
그래서 MySQL에서 제공하는 레퍼런스의 퍼포먼스값은 크게 믿지 않습니다.

High Availability

Mysql Cluster Support Disk-Based Data

Mysql 5.0에 선보였던 Mysql Cluster가 많은 부분 개량되었습니다.
물론 아직도 Mysql에서는 Shared-nothing을 고수 하고 있습니다.
그러나 스토리 지를 메모리로 사용하던 것을 이제 물리적인 장치(예: 하드)로 사용할 수 있게 되었습니다.

Mysql 5.0에서는 클러스터가 시작되면 디스크에 있던 데이터를 메모리에서 읽어와서 동작하게 됩니다.
물론 데이터를 물리적인 저장장치에 있지만 실제로 읽고,쓰이는 행위는 메모리에서 이루어 집니다.
문제는 Mysql이 가지고 있는 모든 데이터를 Cashing하기 때문에
1기가의 데이터를 가지고 있는 Mysql는 1기가 의 메모리가 필요 하게 됩니다.

Mysql 5.1에서는 이런 문제를 해결하기 위해 실제로 메모리와 저장장치가 유동적으로 자료를 교환하는 방식을 지원하고 있습니다.
물론 Shared-nothing이지만 이제 대 용량의 데이터를 클러스터링해서 사용할 수 있게 되었습니다.

한가지 아쉬운 점은 별도의 툴(설정 툴과 모니터링 툴)이 따로 제공되길 바랬으나 기존과 마찬가지로 mysql 명령어로 모든 작업이 이루어 집니다.


크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)
2004/08/05 09:51 2004/08/05 09:51
Posted by 아르마다

BLOG main image
Doing something over and over again , expecting different result. by 아르마다

공지사항

카테고리

전체 (355)
gossip (184)
music (20)
photo (151)

글 보관함

달력

«   2012/02   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      
Total : 253062
Today : 44 Yesterday : 42