2010년 8월 25일 수요일

파티셔닝2

파티셔닝 개요

파티셔닝에서는 데이터를 여러개의 기록영역에 나누어서 기록하는 것을 의미한다.
MySQL의 파티셔닝은 수평 파티셔닝(horizontal partitioning)이라고 불리우는 방법으로 수행한다.

이것은 어떤 컬럼의 값에 따라서  레코드를 기록하는 장소를 바꾸는 방법이다.
이외에도 수직형 파티셔닝(vertical partitioning)처럼 나누는 방법도 있지만 MySQL은 서포트하고 있지 않다. (현재는 잘 모름.. )

다시말하면 수직형 파티셔닝에서는  "이 컬럼은  이쪽 파티션에 기록하고 저컬럼은 저쪽 파티션에 기록한다" 처럼 컬럼에 착목한 분할이 된다.


파티셔닝기본동작

파티셔닝이 어떻게 동작하는지  사용해보면서 알아보자.

 MyISAM테이블  mycom의 작성 

mysql> CREATE TABLE mycom( a INT) ENGINE=MyISAM
     PARTITION BY RANGE(a) (
         PARTITION pt0 VALUES LESS THAN (1000) ENGINE=MyISAM, 
         PARTITION pt1 VALUES LESS THAN (2000) ENGINE=MyISAM,
        PARTITION pt2 VALUES LESS THAN  MAXVALUE  ENGINE=MyISAM) ;


 이 때 데이터베이스의 디렉토리에는 다음과 같은 파일이 작성된다.

데이터베이스 디렉토리의 내용(MyISAM테이블)
mycom#P#pt0.MYD
mycom#P#pt0.MYI
mycom#P#pt1.MYD
mycom#P#pt1.MYI
mycom#P#pt2.MYD
mycom#P#pt2.MYI
mycom.frm
mycom.par

다시 말하면,  어떤 MyISAM 테이블을 파티셔닝하면  다음과 같은 파일이 생성된다.

테이블.frm
테이블.par
테이블#P#파티션이름.MYD(데이터)
테이블#P#파티션이름.MYI(인덱스)

.par파일은 바이너리 파일로  파티셔닝 정보를 기록한다.

.par파일의 내용 (일부)
shell# hexdump -C mycom.par
00000000 08 00 00 00 7e 7d 3a 00 03 00 00 00 09 09 09 00 
00000010 0c 00 00 00 70 74 30 00 70 74 31 00 70 74 32 00 
00000020

 그럼, InnoDB의 경우는 어떻게 될까?   아까전에 만든 mycom테이블을 ALTER TABLE문으로 InnoDB로 변경해 보자.

데이터베이스디렉토리는 다음과 같은 파일이 생성된다.

mycom.frm
mycom.par

InnoDB  형식에 따라서  테이블의  데이터와 인덱스부분은  InnoDB의  테이블 영역으로 이동되었다.   그럼 InnoDB의 --innodb_file_per_table옵션을 사용했을 때에는 파티셔닝은 어떻게 될까?  실행해보면  파일은 다음과 같이 되었다.

mycom#P#pt0.ibd
mycom#P#pt1.ibd
mycom#P#pt2.ibd
mycom.frm
mycom.par


이론 그대로이다.

2010년 8월 17일 화요일

파티셔닝1

파티셔닝은  MySQL 5.1에서 추가된 기능이다.  이것은  한개의 테이블을 여러개로 나누어 사용하는 기능으로 I/O분산을 위한 것이다.

I/O를 분산시킨다는 의미로는 MySQL에서 다음과 같은 방법이 제공되었다.

  • 데이터베이스 디렉토리를 심볼릭 링크로 해서 분산 배치 
  • InnoDB에서는 테이블스페이스 파일(innodb_data_file_path)를 여러개의 파일로 분할 
  • InnoDB에서는 테이블단위로 파일을 작성(innodb_file_per_table)
  • MyISAM에서는 MERGE 테이블 
  • MyISAM에서는 RAID테이블( MySQL5.0에서 페지: 옛날 OS에서는 한개의 파일 사이즈가 4G제한이 있었지만 현재는 그런 제한이 없어졌으므로 자연스럽게 없어짐... )
  • MyISAM에서 파일단위로 심볼릭 링크를 사용해서 분산배치 
그러나, 이것은  어떤 특정 스토리지엔진에서만 가능하다던지 또 사용방법도 각각 다르므로 범용적이라고 할 수 없었다.   그중에는 서버의 설정작업등의 변경작업도 필요하므로 관리자는 별도로 지식을 익혀두어야 했다.

MySQL5.1에서 도입된 파티셔닝기능은 MyISAM과 InnoDB둘다 동작하는 공통의 인터페이스(사용방법)이어서 통일감도 있고,  조작은 SQL문의 실행만으로 완료할 수 있으므로 관리자도 이용자도 편하게 되어졌다. 

파티셔닝을 이용하는 것으로 지금까지 보다 편하게  I/O분산배치를 시행할 수 있게 되었다.

다만,  파티셔닝이 지금까지의 수법을 완전히 대체할 수 있느냐라고는 할 수 없다.
예를 들어 innodb_data_file_path등은 DB셋업할 때 고려해야할 사항이다.

또 MERGE테이블에서는  myisampack으로 각각의 테이블을 작게 할 수 있으므로  이미 존재하는 테이블을 분할 할 때는 파이셔닝보다 편리할 때도 있다.

각각 때와 장소에 맞게 적절히 사용할 필요가 있다.

파티셔닝기능이 유효인지 확인하는 방법에는 SHOW VARIABLES로  have_partitioning의 값을 보면 알 수 있다.   이 값이 YES이면 파티셔닝기능이 들어있다라고 할 수 있다.

만약 값이 NO로 되어 있거나 원래 have_partitioning자체가 나타나지 않은 경우 사용하고 있는 mysqld 바이너리에 파티셔닝이 포함되어 있지 않는 것이다.

서버 소스를  configure할 때 --with-partition를 지정해서 컴파일하면 될 것이다.

2010년 8월 10일 화요일

Replication : 행 레벨 replication

MySQL 5.1.5-alpha에서 행 레벨 replication이 도입되었다.   구현 아이디어로는  바이너리 로그의 기술을 변경하자라는 것이다.

행 레벨 replication은 종래의 replication하고 비교해서  다음과 같은  잇점이 있다.

  • UDF나 FOUND_ROWS(), LOAD_FILE(), SYSDATE(), USER(), UUID()를 사용한 경우에도 replication이 가능
  • 복잡한 SQL문을 slave가  순서대로 실행처리하는 것보다도 빠를 것이다라고 생각되어짐. 
단점으로는 다음과 같은 것이 있다.

  • 로그양이 증가한다. 
  • 처리가 큰 경우 Rollback된 데이터도  로그되는 경우가 있다. 
  • 인간이 바이너리로그를 보아도 판별되지 않는다. 
  • Slave가 어떤 SQL문을 받아 처리하는 지 알 수가 없다. 
소스로 빌드하는 경우는 configure옵션에서 다음과 같이 지정하면 행 레벨 replication은 포함되지 않는다.

shell$ ./configure --without-row-based-replication 


행 레벨 replication의 도입(binlog_format) 

행 레벨  replication을 도입하려면 binlog_format변수에 바이너리로그 기술방법을 지정할 필요가 있다.  mysqld의 옵션처리하려면  --binlog-format이다.

mysqld --binlog-format={ROW|1|STATEMENT|2|MIXED|3}

SET문으로도 변경가능하다.


mysql>SET GLOBAL binlog_format=2;

다음과 같은 경우는 SET문으로 동적으로 포맷을 변경할 수 없다.

  • 스토어드 함수나 트리거 내부
  • NDB가 유효한 경우 
  • 세션이  ROW베이스로 되어있고  임시 테이블을 사용하고 있을 경우 
1이나 STATEMENT는  종래와 마찬가지로  바이너리 로그에는 SQL문으로 변경사항을 기록한다.    행 레벨 replication으로 될 수 없다.
다음과 같은경우 replication할 수 없다.

  • UDF를 사용했을 경우
  • 다음과 같은 함수를 사용했을 경우 FOUND_ROWS(), LOAD_FILE(), USER(), UUID()
  • SYSDATE() 를 --sysdate-is-now옵션이 없는 상태에서 사용한 경우 
2또는 ROW의 경우는 행레벨 replication이 가능하게 된다.  MySQL Cluster의 Replication을 수행할 경우에는  이 값으로 해야한다.  바이너리 로그에는 다음과 같이 기록된다.

BINLOG '
 3w0rRRMBAAAAJgAAACYAAAAAA4AAAAAAAAABHRlc3QAAWEAAQM=
';

값은 base64로  인코딩되어 있다.  이 값은  테이블 핸들러(스토리지엔진에 대한 핸들러)에 전달하는 값이다 ( handler::ha_write_row(), handler::ha_update_row(), handler::ha_delete_row()등) 

3또는  MIXED는 MySQL 5.1.8에서 추가되었다.  보통은 STATEMENT와 마찬가지로 동작한다.  다음과 같은 경우는 ROW와 마찬가지로 바이너리로그를 기록한다.

  • UDF나 UUID()를 사용한 경우 
  • NDB테이블에 대해서 INSERT, UPDATE, DELETE등의 데이터 조작 
  • INSERT DELAYED를 실행했을 경우