http://www.slideshare.net/techdude/how- ··· formance How to Kill Mysql Performance

작게 생각하기
- 조만간 규모가 커질거라면 MySQL ecosystem을 봐야된다.
- 그리고 캐싱 빡시게 안 하는 메이저 웹사이트는 없다.
- develooper.com의 Hansen PT랑 Ilia 튜토리얼 볼 것
- 처음부터 확장 가능하게 아키텍처 잘 쪼개놔야된다.
- 복제랑 파티셔닝 어떻게 할지 미리 계획 세워놔라.
- 파일 기반 세션 좀 쓰지마 -_-
- 그렇다고 너무 쓸데없이 크게 생각하지도 말 것
- 특히 성능하고 확장성 구분 못 하면 난감함

EXPLAIN 안 써보기
- SELECT 앞에 EXPLAIN 이라고 붙이기만 하면 되는 것을 (..)
- 실행 계획 확인
- 타입 컬럼에 index 써있는거랑 Extra 컬럼에 index 써있는거랑 "매우 큰" 차이 있음
 * 타입에 있으면 Full 인덱스 스캔 (안 좋다.)
 * Extra 컬럼에 있으면 Covering 인덱스 찾았다는 의미임 (좋다!)
- 5.0 이후부터는 index_merge 최적화도 한다.

잘못된 데이터 타입 선택
- 한 메모리 블럭 단위에 인덱스 레코드가 많이 들어갈수록 쿼리가 빨리 실행될 것이다. (중요)
- 아.. 정규화 좀 해 -_-... (이거 정말 충격과 공포인 듯)
- 가장 작은 데이터 타입을 써.. (진짜 BIGINT가 필요하냐고..)
- 인덱스 걸리는 필드는 정말 최소한으로 데이터 크기를 써야된다고.
- IP는 INT UNSIGNED로 저장해!! (아주 공감)
 * 이럴 때 쓰라고 INET_ATON 함수가 아예 내장되어 있음.

PHP에서 pconnect 쓰는 짓
- 아파치에서 좀비 프로세스라도 생기면 그 커넥션은 그냥 증발하는거야..
- 어차피 MySQL 접속 속도는 Oracle이나 PostgreSQL 보다 10~100배 빠르다고.

너무 과도한 DB 추상화 계층을 두는 것
- 어디 포팅 열심히 할 거 아니면 추상화 계층 쓰지마 (ADODB, MDB2, PearDB 등)
- scale out 가능한걸 쓰라고.

스토리지 엔진 이해 못 하는 것
- 단일 엔진만으로 전체 아키텍처를 결정했다면 대부분 최적이 아님
- 엔진 별 장단점을 공부할 것
- ARCHIVE : zlib으로 압축해주고 UPDATE 안 되고 로그 Bulk Insert에 유용함.
- MEMORY : 서버 재시작하면 증발. 인덱스가 HASH나 BTREE로 가능함. 임시, 요약 데이터에 사용.
 * 주간 top X 테이블 같은 것.
 * 하여튼 메모리에 박아넣고 싶은 데이터 있으면..

인덱스 레이아웃 이해 못 하는 것
- 제대로 인덱스랑 스토리지 엔진 선택하려면 공부 좀 해
- 엔진은 데이터와 인덱스 레코드를 메모리나 디스크에 레이아웃하는 걸 구현한 것
- clustered 구성은 데이터를 PK 순서에 따라 저장함.
- non-clustered 구성은 인덱스만 순서대로 저장하고 데이터는 순서 가정하지 않음.
- clustered에서는 인덱스만 타면 추가적인 조회 없이 바로 데이터 가져오는 것임.
- 그래서 clustered PK는 작은 놈으로 할 필요가 있다는거
 * 다른 인덱스는 각 레코드마다 PK를 앞에 더 붙이게 되니까.
 * PK 지정 안 하면 아무렇게나 해버림

쿼리 캐시 이해 못 하는 것
- 어플리케이션 read/write 비율은 알고 있어야지
- 쿼리 캐시 설계는 CPU 사용과 읽기 성능 간의 타협
- 쿼리 캐시 크기를 늘린다고 읽기 성능이 좋아지는게 아님. heavy read라도 마찬가지.
- 과도한 CPU 사용을 막기 위해 무효화 할 때는 캐시 항목들을 뭉텅이로 날려버림
- 한마디로 SELECT가 참조하는 테이블 데이터 하나라도 변경되면 그 테이블 캐시는 다 날라간다는 얘기임
- 수직 테이블 파티셔닝으로 처방
 * Product와 ProductCount를 쪼갠다든지..
 * 자주 변하는 것과 변하지 않는 것을 쪼개는게 중요하다 이 말임.

Stored Procedure를 쓰는 것
- 무조건 쓰면 안 된다는게 아니고..
- 컴파일 할 때 무슨 일이 일어나는지 이해 못 하고 쓰면 재앙이 된다 이 말.
- 다른 RDBMS랑 다르게 connection thread에서 실행 계획이 세워짐.
- 이게 뭔 얘기냐 하면 데이터 한 번 가져오고 연결 끊으면 그냥 CPU 낭비 (7~8% 정도)하는 꼴이라는 것.
- 웬만하면 Prepared 구문과 Dynamic SQL을 써라.. 아래 경우를 제외하고
 * ETL 타입 프로시저
 * 아주아주 복잡하지만 자주 실행되지는 않는 것
 * 한 번 요청할 때마다 여러번 실행되는 간단한 것 (연결한 상태로 여러번 써야 된다니까)

인덱스 컬럼에 함수 쓰는 것
- 함수에 인덱스 컬럼 넣어 호출하면 당연히 인덱스 못 탄다
- 함수를 먼저 계산해서 상수로 만든 다음에 = 로 연결해야 인덱스 탈 수 있다.
 * 여기 실행 계획 보면 LIKE도 range type 인덱스 타는 것 보임

인덱스 빼먹거나 쓸모없는 인덱스 만들어 놓는 것
- 인덱스 분포도(selectivity)가 허접하면 안 쓴다.
- S = d/n
 * d = 서로 다른 값의 수 (# of distinct values)
 * n = 테이블의 전체 레코드 수
- 쓸모없는 인덱스는 INSERT/UPDATE/DELETE를 느리게 할 뿐..
- FK는 무조건 인덱스 걸어라. (물론 FK 제약 걸면 인덱스 자동으로 생긴다.)
- WHERE나 GROUP BY 표현식에서 쓰이는 컬럼은 인덱스 추가를 고려할 것
- covering index 사용을 고려할 것
- 인덱스 컬럼 순서에 유의할 것!

join 안 쓰는 짓
- 서브쿼리는 join으로 재작성해라
- 커서 제거해라
- 좋은 Mysql 성능을 내려면 기본
- 집합 기반으로 생각해야지 루프 돌리는거 생각하면 안 된다.

Deep Scan 고려하지 않는 것
- 검색엔진 크러울러가 쓸고 지나갈 수 있다.
- 이 경우 계속해서 전체 집합을 정렬한 다음 LIMIT로 가져와야 하니 무진장 느려진다.
- 어떻게든 집합을 작게 줄인 다음 거기서 LIMIT 걸어 가져올 것

InnoDB 테이블에서 WHERE 조건절 없이 SELECT COUNT(*) 하는 짓
- InnoDB 테이블에서는 조건절 없이 COUNT(*) 하는게 느리다.
- 각 레코드의 transaction isolation을 유지하는 MVCC 구현이 복잡해서 그렇다는..
- 트리거 걸어서 메모리 스토리지 엔진 쓰는 테이블에 통계를 별도로 유지하면 된다.

프로파일링이나 벤치마킹 안 하는 것
- 프로파일링 : 병목 찾아내기
- 벤치마킹 : 시간에 따른 성능 변화 추이 평가, 부하 견딜 수 있는지 테스트
- 프로파일링 할 때는 실제 데이터를 옮겨와서 할 것
- 어디가 병목이냐~ Memory? Disk I/O? CPU? Network I/O? OS?
- 느린 쿼리 로그로 남기기
 * log_slow_queries=/path/to/log
 * log_queries_not_using_indexes
- 벤치마킹 시에는 다 고정시키고 변수 하나만 바꿔가면서 해야 함. (쿼리 캐시는 끌 것.)
- 도구를 써라~~
 * EXPLAIN
 * SHOW PROFILE
 * MyTop/innotop
 * mysqlslap
 * MyBench
 * ApacheBench (ab)
 * super-smack
 * SysBench
 * JMeter/Ant
 * Slow Query Log

AUTO_INCREMENT 안 쓰는 것
- PK를 AUTO_INCREMENT로 쓰는건 무진장 최적화 되어 있음
 * 고속 병행 INSERT 가능
  * 잠금 안 걸리고 읽으면서 계속 할 수 있다는!
- 새 레코드를 근처에 놓음으로써 디스크와 페이지 단편화를 줄임
- 메모리와 디스크에 핫 스팟을 생성하고 스와핑을 줄임

ON DUPLICATE KEY UPDATE를 안 쓰는 것
- 레코드가 있으면 업데이트하고 없으면 인서트하고 이런 코드 필요없다!! 다 날려버려라!!
- 서버에 불필요하게 왔다갔다 할 필요가 없어짐
- 5-6% 정도 빠름
- 데이터 입력이 많다면 더 커질 수 있음

하지 말아야 할 것 총정리
  1. Thinking too small
  2. Not using EXPLAIN
  3. Choosing the wrong data types
  4. Using persistent connections in PHP
  5. Using a heavy DB abstraction layer
  6. Not understanding storage engines
  7. Not understanding index layouts
  8. Not understanding how the query cache works
  9. Using stored procedures improperly
  10. Operating on an indexed column with a function
  11. Having missing or useless indexes
  12. Not being a join-fu master
  13. Not accounting for deep scans
  14. Doing SELECT COUNT(*) without WHERE on an InnoDB table
  15. Not profiling or benchmarking
  16. Not using AUTO_INCREMENT
  17. Not using ON DUPLICATE KEY UPDATEK
출처: http://xeraph.egloos.com/4286421


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

MySQL Replication 복구

2005/07/12 15:04

순서

Maser 서버의 전체 MySQL 데이터 덤프

/usr/local/mysql/bin/mysqladmin -uroot -p flush-logs
/usr/local/mysql/bin/mysqladmin -uroot -p -C "flush tables read lock"
/usr/local/mysql/bin/mysqldump --single-transaction --all-databases --extended-insert=FALSE -c -uroot -p -R > all-databases.sql

약 30분 소요

2. Slave 서버에 복사
3. Slave 서버에 모든 데이타 베이스 삭제
아예 mysql 저장경로의 모든 파일을 삭제한후 mysql-install-db 명령으로 초기화하는 것이 좋음

Slave 서버에 MySQL Replication 설정이 되어 있는지 확인

/etc/my.cnf 파일에

server-id = 2
#
# The replication master for this slave - required
master-host = 61.100.5.12
#
# The username the slave will use for authentication when connecting
# to the master - required
master-user = <계정>
#
# The password the slave will authenticate with when connecting to
# the master - required
master-password = <비밀번호>

위 내용이 있는지 확인

Slave 서버의 MySQL 시작

시작 후 Replication 중지

mysql> stop slave;
mysql> reset slave;

복사한 Dump파일 Restore

mysql -uroot -p < all-databases.sql

약 2시간 10분 소요

Replication 시작

mysql> start slave;

Replicatrion 확인

mysql> show slave status;
mysql> mysql> show slave status;
+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+-------------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Slave_IO_State | Master_Host | Master_User | Master_Port | Connect_Retry | Master_Log_File | Read_Master_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Master_Log_File | Slave_IO_Running | Slave_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Master_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Master_SSL_Allowed | Master_SSL_CA_File | Master_SSL_CA_Path | Master_SSL_Cert | Master_SSL_Cipher | Master_SSL_Key | Seconds_Behind_Master |
+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+-------------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Waiting for master to send event | 61.100.5.12 | repl | 3306 | 60 | mysql-bin.000097 | 631426 | hsmdb2-relay-bin.000198 | 510603 | mysql-bin.000097 | Yes | Yes | | | | | | | 0 | | 0 | 631426 | 510603 | None | | 0 | No | | | | | | 0 |
+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+-------------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
1 row in set (0.00 sec)

Waiting for master to send event가 나오면 성공 다른 메시지가 나오면 위 과정 처음부터 다시 진행

Master 서버 Table Lock 해제

UNLOCK TABLES;

리플리케이션 성공

크리에이티브 커먼즈 라이센스
Creative Commons License
이올린에 북마크하기(0) 이올린에 추천하기(0)
2005/07/12 15:04 2005/07/12 15:04
Posted by 아르마다

mysqldump

mysqldump [옵션] db명 [table명] > 백업파일
mysqldump [옵션] --databases [옵션] db명1, db명2, .... > 백업파일
mysqldump [옵션] --all-databases [옵션] > 백업파일

- 옵션
-A, --all-databases : 모든 DB를 덤프
--add-locks : 덤프 전에 lock 덤프 후에 unlock
--add-drop-table : 덤프이후에 출력물의 앞에 drop table명령 추가
나중에 복구할 때 사용키 위해서
-B, --databases : 여러 DB를 동시에 덤프 할 때 사용
-f, --force : 에러를 무시
-h, --host : 지정한 호스트의 데이터를 덤프
-t : data만 덤프
-d : 데이터를 제외하고 스키마만 덤프
-p : 사용자의 암호를 지정
-P : 포트번호 지정
-u : 사용자명 지정

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

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 아르마다

MySQL Admin 개요

2004/08/01 23:59

1. 프로그램 개요

리눅스 웹호스팅을 사용하는 고객에게 보다 편리한 DB 접속이 가능하도록 웹페이지 상에서 DB의 상태를 확인하고 간단한 DB 명령이나 백업, SQL 쿼리가 가능하도록 해줍니다. 터미널 접속이 어렵거나 phpMyAdmin 등의 별도의 프로그램 설치 등이 어려운 고객을 대상으로 제공하는 서비스입니다. 현재 MyDirect에서 연동되어 실행이 가능합니다.

2. 제작 방법

PHP를 기반으로 MySQL 관련 함수를 이용하여 DB의 상태나 레코드 뷰, 몇가지 명령들이 가능하도록 제작하였습니다. phpMyAdmin 프로그램과 유사하게 운영되도록 제작하였으며, 필수적인 요소만 간결하게 작동 가능하도록 제작하였습니다.

3. 작동 환경

현재 서비스 중인 리눅스 웹호스팅 서버에 적합하도록 제작하였습니다. 특별한 사항은 없으며, php 4.x 이상과 mysql 3.x 이상의 일반적인 MySQL 호출 함수와 호환되며 기초적인 SQL문을 기반으로 합니다.

1. PHP의 설치 환경

'--with-apxs=/usr/local/apache/bin/apxs' '--with-apache-install=/usr/local/apache' '--prefix=/usr/local/php' '
--with-config-file-path=/usr/local/php/lib' '--disable-debug' '--enable-magic-quotes' '--with-gdbm' '--with-gd' '
--with-jpeg-dir=/usr/lib' '--with-mysql' '--with-iconv=/usr/local' '--with-dom=/usr/lib' '--with-zlib-dir=/usr/lib' '
--with-freetype-dir=/usr/lib' '--enable-module=so' '--enable-ftp' '--enable-exif' '--enable-xml'

2. MySQL의 설치 환경

www.mysql.com에서 공개하는 리눅스용 x86계열 RPM 프로그램을 배경으로 제작되었습니다.

2. 프로그램 구성

1. 프로그램 실행

MyDirect에서 실행할 경우 팝업 형태로 MySQL Admin이 실행됩니다. 이때 링크는 웹호스팅 서버의 /home/oozz/wwwhome/mysql_admin/first_page.php로 연결되며 전 리눅스 웹호스팅 서버에 동일하게 설치되어 현재 고객이 서비스를 제공받는 서버에 링크되도록 설정되어 있습니다.
또한 링크시 접속에 필요한 정보를 POST 방식으로 전송하도록 되어 있으며, QUERY STRING은 검색하여 오류로 처리하도록 되어있습니다. 전송되는 정보는 다음과 같습니다.

1 mysql_host : MySQL에 접속하기 위한 호스트 정보
2 mysql_id : MySQL에 접속하기 위한 고객의 접속 ID
3 mysql_passwd : MySQL에 접속하기 위한 고객의 접속 Password
4 mysql_db : MySQL에서 고객에게 할당된 DB 이름

2. 접속 정보 유효성

MyDirect로부터 POST 방식으로 전송 받은 고객의 정보들은 세션을 통해 저장됩니다. 이 세션은 웹페이지가 운영중인 동안에 계속 유지되며 페이지가 닫히는 순간에 파괴됩니다. 보다 정확한 정보 파괴를 위해 페이지가 unload 될때 logout.php가 로딩되며 session_destroy를 실행하도록 제작되어 있습니다.

3. 주요 프로그램 파일의 구성

1 first_page.php
처음 MySQL Admin이 실행되는 페이지입니다. 접속 정보를 정리하여 세션에 저장하며 쿼리스트링을 검색하여 오류로 처리해줍니다. 프레임을 구성하여 로그아웃 확인을 설정합니다.

2 table_structure.php
첫화면을 구성하는 페이지입니다. 사용중인 DB의 테이블을 리스트해주며, 기본적인 정보를 보여줍니다.

3 include_top.php
모든 페이지(first_page.php)에서 로딩하는 탑 페이지입니다. 사용중인 DB의 테이블 리스트를 보여주며, 공통되는 자바스크립트와 DB 접속 프로그램, 쿼리실행기 호출 등을 가지고 있습니다.

4 db_backup.php / db_restore.php / db_restore_ok.php
DB의 백업 및 복원에 관련된 페이지입니다. DB의 각각의 테이블과 레코드에 대해서 루프를 통해 SQL 형식에 따르는 텍스트로 추출하도록 되어 있으며, 복원시에도 각각의 레코들 분석하여 쿼리를 실행하도록 구성되어 있습니다.

5 record_*
개별적인 레코드에 대한 프로그램들이며, 레코드 입력, 레코드 수정, 그리고 레코드 보기의 페이지들로 구성되어 있습니다. 레코드 보기에서는 별도의 명령어가 실행될 수 있도록 제작되어있습니다.

6 table_*
테이블에 관련된 프로그램들입니다. 테이블 생성, 테이블 필드추가, 테이블 상세 설명, 테이블 수정들이 주요 프로그램입니다.

7 sql_query.php
사용자로부터 직접 입력 받은 쿼리를 실행해주는 프로그램입니다. 쿼리를 분석하여 오류나 잘못된 구문은 보여주며, SELECT 등의 명령어 실행시에는 화면에 실행 결과를 보여주도록 제작되었습니다.

8 auth.php / autthLib.php
MyDirect의 통합 인증을 위하여 Auth.Direct.co.kr의 통합 인증 서버를 통하여 사용자 인증 후 MySQL 서버의 접속 정보를 가져와 MySQL Admind의 Session을 통해 인증을 한다.

3. 프로그램 버전 정보

0.9 (2002년 12월)
베타 테스트 및 기본 프로그램 제작, 실 서비스 사용

1.0 (2003년 06월)
레코드 추가 프로그램 오류 수정 (특정 데이터 타입)

1.0.1 (2004년04월)
레코드 수정시 필드 사이즈 오류 수정, 레코드 보여주기에서 테이블 정렬 보완

1.0.2 (2006년06월)
1MyDirect의 통합 인증 서버 추가로 인한 Auth Page 작성

1.0.3 (2006년 06월)
다중 접속시 중복 인증오류 처리

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

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

공지사항

카테고리

전체 (352)
gossip (181)
music (21)
photo (150)

글 보관함

달력

«   2010/09   »
      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 30    
Total : 221802
Today : 15 Yesterday : 56