2009년 12월 27일 일요일

MySQL - 모니터링7

Linux커널의 I/O스케줄러 변경

커널2.6에서는 다음처럼 I/O스케줄러를 변경할 수 있다.

#I/O스케줄러의 변경
root@shell# echo "anticipatory" > /sys/block/sda/queue/scheduler

하드디스크단위로 지정한다.
하드디스크의 인식명에 따라서 위 예의 sda부분이 바뀌게 된다.
또 boot할 때 커널의 파라미터에 디폴트 I/O스케줄러를 부여하는 것이 가능하다.

elevator=deadline

/sys/block/디스크명/queue/iosched/ 아래의 파일로 I/O스케줄러의 파라미터를 변경할 수 있다.

I/O스케줄러에는 다음과 같은 것이 있다. 커널의 config시에 디폴트를 지정할 수 있다.

  • Anticipatory
  • Deadline
  • CTQ
  • NOOP
커널의 config의 변수, CONFIG_DEFAULT_IOSCHED이던지 make config의 메뉴의
「Block layer」→ 「IO Schedulers」→ 「Default I/O scheduler」에 값을 부여한다.




2009년 12월 21일 월요일

MySQL - 모니터링6

운영체제 툴

MySQL본체이외에도 운영체제의 상태를 알고 싶을 때가 있을 것이다.
여기에서는 Linux를 기준으로 몇가지 툴과 수법을 소개해보자.

iostat

iostat는 디스크 드라이브 단위로 I/O통계정보를 얻을 수 있는 명령어이다. 구문은 다음과 같다.

iostat [옵션] [간격 [횟수] ]

간격에 초수를 지정하면 지정 초수마다 횟수에 지정된 횟수만큼 iostat를 실행하고 끝낸다.
이 때 최초의 레포트는 지금까지의 누적정보를 내고, 두번째부터는 전 레포트 보고시점부터의 통계를 나타낸다. 횟수를 지정하지 않으면 영원히 레포트를 출력한다 .


vmstat

vmstat는 VM의 통계정보를 얻을 수 있는 명령어이다. 구문은 다음과 같다.

vmstat [옵션] [간격 [횟수] ]

간격에 초수를 지정하면 초수마다 횟수에 지정된 횟수만큼 vmstat를 실행하고 끝낸다.
횟수를 지정하지 않으면 영원히 레포트를 출력한다


Linux프로파일러( oprofile)

어플리케이션 어느 부분이 어느 정도의 처리를 하고 있는지등의 정보를 얻을 수 있다.
oprofile에서 프로파일링을 하기 위해서는 커널이 oprofile을 지원하고 있을 필요가 있다.
커널의 config변수는 다음과 같다.

CONFIG_PROFILING  「y」
CONFIG_OPROFILE 「y」또는 「m」


커널의 config의 menu에서는 다음 항목을 유효로 해둔다.
Instrumentation Support -> Profiling support를 「y」
OProfile system profiling을 「y」또는 「m」

실제 조작은 다음과 같다.

oprofile실행예

opcontrol --shutdown <-- oprofile데몬 정지
opcontrol --reset <-- oprofile의 과거 데이터를 삭제
opcontrol --start <-- oprofile 데몬 기동

조사하고 싶은 명령어를 실행

opcontrol --shutdown <-- oprofile데몬 정지
opcontrol --save=test01 <-- 방금 취득한 데이터를 test01라는 이름으로 백업
opcontrol -1 session:test01 <-- test01의 레포트를 표시


oprofile의 데이터는 /var/lib/oprofile/에 기록된다.

2009년 12월 14일 월요일

MySQL - 모니터링5

옵티마이져의 동작을 확인(EXPLAIN SELECT)

EXPLAIN문으로 SELECT에 대한 옵티마이져의 정보를 아는 것이 가능하다.

구문은 다음과 같이 된다.

EXPLAIN [EXTENDED|PARTITIONS] SELECT문

EXPLAIN PARTITIONS는 파티셔닝된 테이블에 대한 쿼리를 검사한다.
EXPLAIN EXTENDED는 filtered정보가 추가적으로 얻을 수 있다. 또 계속해서 SHOW WARNINGS을 실행하면 컬럼명등 정보를 얻을 수 있다.

MySQL 5.1.12-beta에서 추가되었다.

mysql> explain select * from m_page where page_id > 5\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: m_page
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 120
Extra: Using where
1 row in set (0.00 sec)


각 컬럼의 의미는 다음과 같다.

  • id: 쿼리내의 SELECT순번
  • select_type: SIMPLE, PRIMARY, UNION, DEPENDENT UNION, UNION RESULT, SUBQUERY, DERIVED, DEPENDENT SUBQUERY, UNCACHEABLE SUBQUERY
  • table:대상이 되는 테이블
  • type: JOIN종류. system, const, eq_ref, ref, ref_or_null, index_merge, unique_subquery, index_subquery, range, index, ALL
  • possible_keys:어느 인덱스가 사용가능한지 나타냄. EXPLAIN에 표시되는 테이블 순서에 따라서 사용가능한 키가 바뀌는 경우가 있다. NULL이면 적절한 인덱스는 찾을 수 없었다는 것을 나타냄. 이 경우 퀄리 조건절의 기술을 수정할 것을 권함.
  • key: 사용하려고 결정된 키가 표시됨. NULL이면 인덱스는 사용되지 않고 있다는 것을 의미. MyISAM의 경우, ANALYZE TABLE문 실시로 개선되는 경우도 있음. 인덱스사용을 강제하는 문에는 다음과 같은 것이 있다. FORCE INdEX, USE INDEX, IGNORE INDEX
  • key_len: 사용하려고 결정된 키의 크기
  • ref: 어느 컬럼이나 정수가 인덱스하고 비교되는지를 나타냄.
  • filtered: MySQL 5.1.12-beta에서 추가되었다. 다음 관계가 있다. rows × filtered ÷100 = 전 테이블과 조인된 레코드수 . filtered는 조건에 따라서 취득되어야 하는 레코드가 레코드 전체의몇 %가 되는 지를 나타냄.
  • Extra:부가 설명이 제공됨. 어떤 처리를 수행하는지 나타냄. Distinct, Not exists, Range checked for each record(index map: N), Using filesort, Using index, Using temporary, Using where, Using sort_union(...), Using union(...), Using intersect(...), Using index for group-by, Using where with pushed condition





2009년 12월 2일 수요일

MySQL - 모니터링4

설정값을 알기(SHOW VARIABLES)

다음 문장과 명령어로 서버의 설정값( 변수값)을 확인할 수 있다.

mysql> SELECT * FROM information_schema.GLOBAL_VARIABLES;
mysql> SELECT * FROM information_schema.SESSION_VARIABLES;
mysql> SHOW VARIABLES;

shell$ mysqladmin variables

information_schema.GLOBAL_VARIABLES나 information_schema.SESSION_VARIABLES테이블은 Mysql 5.1.12-beta에서 추가되었다.

변수의 사용및 변수값의 변경(SET문, 옵션)에 대해서는 mysqld옵션과 서버변수를 참조하길 바란다.


2009년 11월 29일 일요일

MySQL - 모니터링3

서버의 통계정보를 확인하기(SHOW STATUS)

MySQL서버내의 통계정보를 확인하려면 다음과 같이 한다.

shell$ mysqadmin extened-status

mysql>SHOW STATUS;

mysql>SELECT * FROM information_schema.GLOBAL_STATUS;

mysql>SELECT * FROM information_schema.SESSION_STATUS;

information_schema를 SELECT하는 경우는 Variable_name은 전부 대문자로 표현된다.

- Variable_name 내용
  • Aborted_clients: 클라이언트가 정상적인 방법으로 통신을 끊지않은 수
  • Aborted_connects: MySQL서버에 접속에 실패한 수
  • Binlog_cache_disk_use: mysqld는 트랜잭션개시할 때에 binlog_cache_size 메모리를 확보하고 그곳에 트랜잭션 문을 일단 써놓는다.(COMMIT, ROLLBACK실행전) 만약 캐쉬에 실행문을 전부 기록하지 못할 경우는 문장은 디스크에 쓰여진다. Binlog_cache_disk_use는 이 디스크에 문장을 보존하게 된 트랜잭션 수. binlog_cache_size의 설정이 충분히 큰 경우는 이 수가 적어지게 된다.
  • Binlog_cache_use: mysqld는 트랜잭션개시할 때에 binlog_cache_size 메모리를 확보하고 그곳에 트랜잭션 문을 일단 써놓는다.(COMMIT, ROLLBACK실행전) Binlog_cache_use는 이 캐쉬를 사용한 트랜잭션 수
  • Bytes_received: 모든 클라이언트에서 받은 바이트수
  • Bytes_sent: 모든 클라이언트에 보낸 바이트수
  • Com_xxx: 각각 xxx문이 얼마나 실행되었나를 나타낸다. Com_stmt_xxx는 Prepared Statement관련 문이 있다는 것을 나타낸다. Com_stmt_xxx는 예를 들어 Prepared statement인수 에러로 실행되지 못했던 경우에도 계산된다. 즉 Prepared Statement의 리퀘스트 수라고 말할 수 있다.
  • Compression: 클라이언트 서버사이에 통신을 zlib(gzip)압축을 하고 있으면 ON
  • Connections: MySQL서버에 접속을 시도한 수. 성공, 실패하고는 관계없음.
  • Created_tmp_disk_tables: 쿼리 실행중에 디스크에 작성된 임시 테이블 수. tmp_table_size보다 큰 영역이 필요한 경우에 디스크에 작성된다. 임시테이블을 메모리에서 전부 처리하고 싶다면 tmp_table_size을 늘린다.
  • Created_tmp_files:mysqld가 작성한 임시 파일 수
  • Created_tmp_tables: 쿼리 실행중에 메모리내에 작성된 임시 테이블 수. 메모리 상에 작성된 임시 테이블의 최대 사이즈는 tmp_table_size로 결정된다.
  • Delayed_errors: INSERT DELAYED로 쓰여진 레코드중에 에러가 난 것들의 수(중복 키 에러 등 )
  • Delayed_insert_threads: 사용된 INSERT DELAYED 핸들러 스레드수
  • Delayed_writes: INSERT DELAYED로 쓰여진 레코드 수
  • Flush_commands: FLUSH문의 실행횟수
  • Handler_commit: 내부 커밋 실행횟수
  • Handler_delete: 테이블에서 삭제된 레코드 수
  • Handler_discover: 테이블에 대해서 NDB클러스터에 질의하는 것을 discovery라고 부른다. 얼마나 NDB클러스터에 질의해서 테이블이 찾아졌는지를 나타냄.
  • Handler_prepare: two phase commit의 prepare 구문의 횟수
  • Handler_read_first: 테이블의 최초의 행이 읽어들여진 횟수
  • Handler_read_key
  • Handler_read_next
  • Handler_read_prev
  • Handler_read_rnd
  • Handler_read_rnd_next
  • Handler_rollback: 롤백을 요구한 수
  • Handler_savepoint:SAVEPOINT 요청 수
  • Handler_savepoint_rollback
  • Handler_update
  • Handler_write
  • Innodb_buffer_pool_pages_data:데이터를 포함한 페이지 (dirty, clean) 수
  • Innodb_buffer_pool_pages_dirty
  • Innodb_buffer_pool_pages_flushed
  • Innodb_buffer_pool_pages_free
  • Innodb_buffer_pool_pages_latched: Innodb버퍼풀 안에 latched페이지 수. 현재 읽고 쓰여지고 있는 페이지는 플러쉬나 삭제가 되지않는데 이 것을 말한다.
  • Innodb_buffer_pool_pages_misc
  • Innodb_buffer_pool_pages_total
  • Innodb_buffer_pool_read_ahead_rnd
  • Innodb_buffer_pool_read_ahead_seq
  • Innodb_buffer_pool_read_requests
  • Innodb_buffer_pool_reads
  • Innodb_buffer_pool_wait_free
  • Innodb_buffer_pool_write_requests
  • Innodb_data_fsyncs
  • Innodb_data_pending_fsyncs
  • Innodb_data_pending_reads
  • Innodb_data_pending_writes
  • Innodb_data_read: 지금까지 데이터를 읽어들인 바이트의 합계
  • Innodb_data_reads: 데이터 취득 횟수
  • Innodb_data_writes: 데이터 작성 횟수
  • Innodb_data_written:지금까지 데이터를 쓴 바이트의 합계
[계속]

2009년 11월 24일 화요일

MySQL - 모니터링2

자식 쓰레드 확인(SHOW PROCESSLIST / KILL)

현재 접속중인 클라이언트(자식 쓰레드)를 KILL문이나 mysqladmin kill 을 사용해서 강제종료시킬 수 있다.

기동중에 있는 자식 쓰레드를 확인하기 위해서는 다음과 같은 명령어를 사용할 수 있다.

SHOW PROCESSLIST
또는
SELECT * FROM information_schema.PROCESSLIST
또는
mysqladmin processlist

실행하기 위해서는 PROCESS권한이 필요한다.

실행결과에 표시되는 내용은 다음과 같다.

  • Id: 쓰레드 ID이다. MySQL서버가 작성한 클라이언트용 쓰레드에 고유 번호가 할당된다. KILL문을 사용해서 쓰레드를 죽일 경우에 이 번호를 지정한다.
  • User, Host: 접속유저, 클라이언트 호스트를 나타낸다.
  • db:현재 데이터베이스를 나타낸다.
  • Command:실행되고 있는 명령어 종류를 나타낸다. 다음과 같은 것이 있다. Binlog Dump, Change user, Close stmt, Connect Connect Out, Create DB, Daemon, Debug, Delayed insert, Drop DB, End, Error, Execute, Fetch, Field List, Init DB, Kill, Long Data, Ping, Prepare, Processlist, Query, Quit, Refresh, Register Slave, Reset stmt, Set option, Shutdown, Sleep, Statistics, Table Dump, Time
  • Time: 명령어의 실행시간(sec.)이다.
  • State:상태의 설명이다. 다음과 같은 것이 있다. After create, allocating local table, Analyzing, Changing master, Checking master version, Checking table, cleansing up, closing tables, Connecting to master, converting HEAP to MyISAM, copy to tmp table, Copying to group table, Copying to tmp table, Copying to tmp table on disk, Creating delayed handler, Creating sort index, creating table, Creating table from master dump, Creating tmp table, deleting from main table, deleting from reference tables, discard_or_import_tablespace, Execution of init_command, Finished reading one binlog; switching to next binlog, Flushing tables, freeing items, FULLTEXT initialization, got handler lock, got old table, Has read all relay log; waiting for the slave I/O thread to update it, Has sent all binlog to slave; waiting for binlog to be updated, init, insert, Killed, Killing slave, Locked, logging slow query, login, Making temp file, Opening master dump table, Opening table, Opening tables, preparing, Purging old relay logs, query end, Queueing master event to the relay log, Reading event from the relay log, Reading from net, Reading master dump table data, Rebuilding the index on master dump table, Reconnecting after a failed binlog dump request, Reconnecting after a failed master event read, Registering slave on master, Removing duplicates, removing tmp table, rename, rename result table, Reopen tables, Repair by sorting, Repair with keycache, Requesting binlog dump, reschedule, Searching rows for update, Sending binlog event to slave, Sending data, setup, Sorting for group, Sorting for order, Sorting result, starting slave, statistics, storing row into queue, System lock, Table lock, unauthenticated user, update, Updating, updating main table, updating reference tables, upgrading lock, User lock, waiting for delay_list, Waiting for event from ndbcluster, waiting for handler insert, waiting for handler lock, waiting for handler open, Waiting for INSERT, Waiting master to send event, Waiting for master update, Waiting for the slave SQL thread to free enough relay log space, Waiting for slave mutex on exit, Waiting for table, Waiting for tables, Waiting for the next event in relay log, Waiting on cond, Waiting to finalize termination, Waiting to reconnect after a failed binlog dump request, Waiting to reconnect after a failed master event read, Writing to net
  • Info: 쓰레드가 실행되고 있는 문장을 나타낸다. NULL인 경우는 문장을 실행하고 있지 않다는 뜻이다.



2009년 11월 19일 목요일

MySQL - 모니터링1

데이터베이스 목록을 표시

SHOW DATABASES
또는
SELECT * FROM information_schema.SCHEMATA [WHERE...]

테이블 목록을 표시

SHOW TABLES
또는
SHOW TABLE STATUS
또는
SELECT * FROM information_schema.TABLES [WHERE ...]

테이블정의를 표시

DESC 테이블명
DESCRIBE 테이블명
EXPLAIN 테이블명

테이블정보를 표시

SHOW CREATE TABLE 테이블명

컬럼정보를 표시

SHOW COLUMNS FROM 테이블명
SHOW FULL COLUMNS FROM 테이블명
SELECT * FROM information_schema.COLUMNS [WHERE ...]


인덱스정보를 표시

SHOW INDEX FROM 테이블명
SELECT * FROM information_schema.STATISTICS [WHERE ...]

2009년 11월 15일 일요일

MySQL 보안 - stone with SSL 2

stone작성

우선 OpenSSL대응의 stone을 작성한다. 소스를 풀고 안에 있는 Makefile을 편집한다.
다음 부분을 환경에 맞춰서 편집한다.

Makefile
SSL= /usr/local/ssl
SSL_FLAGS= -DUSE_SSL -I$(SSL)/include
SSL_LIBS= -L$(SSL)/lib -lssl -lcrypto

Linux의 경우, glibc-2.3.2에서는 EPOLLONESHOT이 정의되어 있지않기때문에 컴파일 에러가 난다.

Makefile안의 linux: 타켓에 적혀있는 -DUSE_EPOLL을 생략한다.
준비가 끝났으면 make를 실행한다.

make의 실행
shell$ make linux-ssl

생성된 stone을 원하는 디렉토리에 인스톨하면 된다.


stone실행

stone의 사용방법은 소스와 같이 있는 README.txt에 자세하게 적혀있다.

stone의 기본적인 구문은 다음과 같다.

stone 리모트호스트:리모트포트 로컬포트

stone은 Local포트에서 대기 , 수신한 것을 리모트 포트에 릴레이 전송하게 된다.

>클라이언트에서 실행하는 mysql
mysql -h 127.0.0.1 -P 3308

>클라이언트에서 실행하는 stone
stone remote.server.name:3307 3308

>서버에서 실행하는 stone
stone localhost:3306 3307

이것으로 패킷 리피트의 골격이 완성되었다.

그러나 SSL의 통신은 되지 않는다. 여기에서 SSL용 옵션을 지정한다.

전송포트, 대기포트의 뒤에 /ssl을 붙이게 되어 SSL통신을 하게 된다.

>클라이언트에서 실행하는 stone
stone remote.server.name:3307/ssl 3308
>서버에서 실행하는 stone
stone localhost:3306 3307/ssl

또, 개인 키나 CERTIFICATE 파일을 지정하고 픈 경우는 다음처럼 조작한다.

>클라이언트에서 실행하는 stone
stone -q key=key.pem -q cert=cert.pem remote.server.name:3307/ssl 3308
>서버에서 실행하는 stone
stone -z key=key.pem -z cert=cert.pem localhost:3306 3307/ssl

-z옵션은 SSL서버용 옵션이다.
stone이 서버로 동작할 때 사용한다. -q옵션은 SSL클라이언트로 stone이 동작할 때 사용한다.
MySQL의 SSL대응의 때와 마찬가지로 이 옵션을 사용하면 된다.

key=는 개인키, cert=는 CERTIFICATE파일로 자기가 서명한 것이던지 제3자 인증국이 싸인한 파일을 지정한다. 인증국이 서명한 경우 인증국의 CERTIFICATE파일이 필요로 하게된다.

그 경우는 -{z|q} CApath=, -{z|q}CAfile= 둘중에 하나를 사용하면 된다.
CApath=의 경우는 해쉬를 생성해서 파일명을 만들어야 한다.


2009년 11월 13일 금요일

MySQL 보안 - stone with SSL

stone은 심플한 패킷 리피터로 TCP나 UDP를 릴레이 하는 것이 가능하다.

작고 가볍기 때문에 간단한 벽에 구멍을 내거나 패킷 내용 취득등에 많이 사용되고 있다.

OpenSSL를 같이 쓸 수 있기때문에 SSL통신을 할 수 있다.

MySQL클라이언트나 서버를 SSL통신을 시킬려면 stone은 1개(또는 0개)여도 충분하지만 여기에서는 MySQL클라이언트와 서버 둘다 SSL가 설치되지 않았다고 가정하고 이야기한다.

stone사용예

[Local] ------------------------------------[Remoe]
mysql-> 3308(stone) ==(암호화)==> 3307(stone)->3306(mysqld)



2009년 11월 11일 수요일

MySQL 보안 - SSH port forwarding

SSH를 사용해서 통신경로를 암호화하는 방법도 있다.

단지, MySQL서버가 동작하고 있는 운영체제에 계정을 가지고 있을 필요가 있다.


[클라이언트]                                  [서버]
mysql-> 3307(ssh) ==(암호화)==> (sshd)->3306(mysqld)


클라이언트로 mysql명령어를 사용한다고 가정하자.
자기가 사용하고 있는 로컬 컴퓨터의 TCP/IP 의 3307번 포트를 ssh가 처리할 수 있도록 한다.
Local의 ssh는 포트 3307로 받아들인 내용을 리모트 컴퓨터의 sshd에 송신, remote의 포트 번호 3306으로 전송하도록 한다.

이 방식을 실현하기 위해서는 -L옵션을 사용해서 클라이언트 머신에서 다음과 같이 ssh를 실행한다.
ssh -L 3307:localhost:3306 remote-server

3307
local 장비에서의 포트 번호이다. mysql명령어나 ssh명령어를 실행하려고 하는 컴퓨터에서의 포트를 말한다.

localhost:3306
remote장비에서 볼 때 어느 호스트, 어느 포트인가 지정한다. 위 표기는 같은 장비 3306를 포워딩하게 된다.

Local에서 조작은 실제로 다음과 같이 될 것이다.

shell$ ssh -L 3307:localhost:3306 mycom@remote.server.name &
shell$ mysql -h 127.0.0.1 -P 3307


mysql명령어에는 -h 127.0.0.1로 TCP/IP를 이용한 접속을 지정하고 -P 3307로 포트 번호를 지정한다.

TCP/IP포트번호 1024이하는 root계정이 아니면 사용할 수 없으므로 주의한다.

MySQL서버(mysqld)에 접속하는 것은 MySQL서버와 같은 컴퓨터에서 동작하고 있는 sshd임으로 mysqld에서 보면 클라이언트는 '사용자명'@'127.0.0.1'이 된다. 따라서 GRANT에 주의해야한다.



2009년 11월 9일 월요일

MySQL 보안 - TCP Wrapper

MySQL에 TCP Wrapper가 되게 하려면 configure옵션에 --with-libwrap을 지정한다.

shell$ ./configure --with-libwrap=/usr

디렉토리가 지정된 경우, 지정된 디렉토리 밑에 TCP Wrapper 헤더파일과 라이브러리가 필요하다.

컴파일과 인스톨이 끝난 뒤는 다른 TCP Wrapper설정과 마찬가지로 hosts.allow와 hosts.deny파일을 편집해야한다.

hosts.{allow,deny}의 최초 컬럼은 프로그램이름이다. 보통은 mysqld이지만 만약 바이너리 파일의 이름을 변경했을 경우에는 그것으로 해야한다.

hosts.deny파일의 편집예

mysqld: .my.domain
mysqld-5.1: 192.168.0.0/255.255.255.240


libwrap를 추가하면 클라이언트가 접속할 때마다 서버는 TCP Wrapper를 이용해서 클라이언트의 접속의 허가, 거부를 수행한다.




2009년 11월 4일 수요일

MySQL 보안 - SSL통신7

SSL통신을 필수로 하기

어떤 유저의 통신에는 반드시 SSL을 사용하는 경우는 GRANT문에 REQUIRE를 지정한다.

mysql>GRANT .... TO 'mycom'@'192.168.0.1' REQUIRE SSL;

또한 어떤 유저는 반드시 올바른 인증을 받지 않으면 안되는 경우에는 GRANT문에 REQUIRE X509를 지정한다.

mysql>GRANT .... TO 'mycom'@'192.168.0.1' REQUIRE X509;


Subject고정

어떤 사용자의 Subject를 고정하고픈 경우는 GRANT문에 SUBJECT를 추가한다.
클라이언트 키의 Subject가 다른 경우, 서버는 접속을 거부한다.

mysql>GRANT .... TO 'mycom'@'192.168.0.1' REQUIRE SUBJECT '/C=KR/L=Basel/O=MYCOM/OU=DB Comms/CN=whatever'

키의 Subject를 표시하고 싶은 경우에는 다음과 같이 한다.

shell$ openssl x509 -text -in client-cert.pem


Issuer의 고정

어떤 유저의 Issuer를 고정하고픈 경우는 GRANT문에 ISSUER를 추가한다.
클라이언트 키의 Issuer가 다른 경우는 서버는 접속을 거부한다.

mysql>GRANT .... TO 'mycom'@'192.168.0.1' REQUIRE ISSUER '/C=KR/O=MYCOM/OU=Certificate Authority/CN=whatever';

Cipher의 고정

어떤 유저의 암호화방식을 고정하고픈 경우는 GRANT문에 CIPHER를 추가한다.

mysql> GRANT .... TO 'mycom'@'192.168.0.1' REQUIRE CIPHER 'DHE-RSA-AES256-SHA:AES128-SHA';

Cipher 리스트는 복수의 암호화를 「:」로 구분짓는다. 특별한 지정으로 「ALL」 하고 「-」이 있다.
예를 들어 , 다음처럼 한 경우 모든 암호화 방식에서 DHE-RSA-AES256-SHA:를 제거한 암호화 방식을 채용한다.
CIPHER 'ALL:DHE-RSA-AES256-SHA'

지원되는 Cipher확인하려면 다음과 같은 조작을 한다.

shell$ openssl ciphers

2009년 10월 30일 금요일

MySQL 보안 - SSL통신6

클라이언트에서 접속

--ssl옵션을 사용해서 접속한다. 키는 ~/.bimil/에 보존지정한다고 가정한다.

shell$ mysql --ssl --ssl-key=~/.bimil/private.pem --ssl-cert=~/.bimil/cert.pem

보통은 만약 SSL의 handshake에 실패하면 평문대로 접속한다.

서버에 접속한 후 STATUS나 SHOW STATUS를 실행하면 SSL로 접속하고 있는지 그렇지 않은지 확인할 수 있다.

○SSL통신을 개시한 경우
mysql> SHOW STATUS LIKE 'Ssl_cipher';
------------------------------------------------
Variable_name | Value
------------------------------------------------
Ssl_cipher | DHE-RSA-AES256-SHA
------------------------------------------------

○SSL통신을 개시하지 못했을 경우
mysql> STATUS
(중략)
SSL: Not in use
(중략)




2009년 10월 18일 일요일

MySQL 보안 - SSL통신5

●Certificate Request 파일에 서명하기

각 Certificate Request 파일을 local CA로 서명한다.

root@shell# openssl ca -policy policy_anything -out signed-cert.pem -in dareka-csr.pem

local CA의 키를 사용해 인증하고픈 누군가의 Certificate Request파일에 서명을 한다.
-out로 지정된 파일이 서명이 끝난 파일이 된다.

policy_anything은 openssl.cnf섹션에 설정되어 있다. 그곳에서는 어느 항목이 필수인가 지정되어 있다. policy_anything은 commonName만이 필수항목으로 되어있다.


policy 섹션에서 키워드에 주어지는 값의 의미


match: 필수항목 그리고 내용은 인증국과 일치
supplied: 필수항목, 내용은 상관없음
optional:있거나 없거나 상관없음.

●MySQL옵션에 파일을 지정하기

서명된 signed-cert.pem파일을 MySQL옵션 --ssl-cert=에 지정하고 --ssl-ca나 --ssl-capath=에 CA의 CERTIFICATE 파일을 지정한다.

예를 들어 다음 예의 경우, 2가지 지정방법이 있다.

  • local CA의 CETIFICATE파일: local-ca-cert.pem
  • local CA에 사인된 파일 : signed-cert.pem
  • private key: private-key.pem
①--ssl-key=private-key.pem --ssl-cert=signed-cert.pem --ssl-ca=local-ca-cert.pem
②--ssl-key=private-key.pem --ssl-cert=signed-cert.pem --ssl-capath= {local-ca-cert.pem을 보존하는 디렉토리 }

local-ca-cert.pem을 보존하는 디렉토리에는 local-ca-cert.pem파일을 보존하는 것만으로는 부족하고 파일의 해쉬를 이름으로 한 파일을 작성할 필요가 있다.

local-ca-cert.pem해쉬
shell$ openssl x509 -hash -noout -in local-ca-cert.pem
a808a98b

local-ca-cert.pem의 해쉬를 붙인 파일을 작성하고 local-ca-cert.pem과 같은 디렉토리에 놓는다.
다음 처럼 조작한다.

local-ca-cert.pem 복사와 해쉬를 파일명으로 한 파일의 작성
shell# cp local-ca-cert.pem capath/
shell# cd capath/
shell# ln -s local-ca-cert.pem a808a98b.0

ln 대신 cp여도 상관없다.
파일명이 "해쉬.숫자"로 되어있다. 숫자는 0이상 정수를 자유로 붙이면 된다.
이것은 만에 하나 해쉬가 다른 파일의 해쉬하고 일치했을 경우에 구별을 두기위한 것이다.

2009년 10월 15일 목요일

MySQL 보안 - SSL통신4

● 자기의 CA섹션을 openssl.cnf에 추가한다.

OpenSSL설정파일, openssl.cnf파일의 [ CA_default ]를 참고로 자기의 CA섹션을 openssl.cnf에 추가한다. 이름은 적당히 붙인다.
ca_my여도 상관없다.
또, openssl.cnf파일을 복사한 다음, 표준인 [ CA_default ] 를 편집해도 상관없다.

● 자기 인증국 키를 작성한다.

자기 인증국(local CA)의 키를 작성한다. 이것은 서버 키를 작성하는 순서와 마찬가지이다.

자기인증국 키 작성
root@shell# openssl req -new -x509 -keyout local-ca-key.pem -out local-ca-cert.pem -days 10000

local CA용으로 추가한 이름이 ca_my인 경우, -name ca_my옵션을 추가한다.
여기에서 작성한 키 파일이름을 openssl.cnf파일에 지정해 둔다.
CA정의 섹션에서는 dir, certificate, private_key, serial, database 변수에 주의해야한다.

기본값은 openssl.cnf에 기재되어 있다.

OpenSSL에는 인증국 작성 작업을 한번에 수행하는( 키를 작성하거나 디렉토리나 파일을 작성하거나 한다. ) CA.sh 스크립트가 부속되어 있다.

CA.sh스크립트는 디렉토리명등이 고정되어 있기때문에 편한대로 맞춰서 편집해서 실행하면 될 듯 싶다.
편집할 때는 openssl.cnf의 local CA용 섹션 기술과 맞춰놓도록 한다.

예> root@shell# bash CA.sh -newca

2009년 10월 13일 화요일

MySQL 보안 - SSL통신3

자기 인증국을 세우기

데이터베이스 서버이기때문에 보통은 일반 대다수에게 무작위로 공개하지는 않을 것이다.

제 3자기관의 서명을 받을 것이 아니라 자기 스스로 인증국을 세워 그곳에서 인증하는 방법도 있다.


● 전제지식: OpenSSL 설정파일 또는 사용할 CA섹션을 지정한다.

OpenSSL은 표준 openssl.cnf파일(컴파일할 때 고정됨)을 읽어들여 동작한다.
자기 스스로 인증국으로 하는 경우는 이 파일을 편집하거나 바꿀 필요가 있다.

①별도 파일을 설정파일에 지정한다.
만약 설정파일을 별도의 파일로 했을 경우는 다음과 같이 설정파일을 앞으로 실행하는 모든 명령어 라인의 최초의 옵션에 추가하면 된다.

-config 설정파일

다른 옵션 후에 지정하면 무효가 될 수 있다.

②사용할 CA섹션을 지정한다.
각 CA섹션은 파일내에 [섹션명]으로 정의되어 있지만 [ ca ]섹션 안의 default_ca키워드가 표준으로 사용되는 CA섹션이라는 의미이다.
이것과는 다른 CA섹션을 읽어들이는 경우의 옵션은 다음과 같이 된다.

-name CA섹션명

이것을 각 명령에 추가하면 읽어들이는 섹션은 바뀌게 된다.





2009년 10월 11일 일요일

MySQL 보안 - SSL통신2

서버측 키 생성

■private key 파일 생성

MySQL서버가 사용하는 private key파일(server-key.pem), Certificate Request파일(server-csr.pem)을 작성한다. ( 파일명은 임의로 붙여도 된다. )

※private key파일과 Certificate Request파일 작성
root@shell# openssl req -new -nodes -keyout server-key.pem -out server-csr.pem -days 1000

--nodes를 빼면 pass phrase이 요구되는 키를 작성한다. Common Name ( ....)[] : 에는 서버의 FQDN을 입력해야한다.
또 다음처럼 조작하더라도 같은 결과를 얻을 수 있다.

※make PRIVATE KEY
root@shell# openssl genrsa -des3 -out server-key.pem 1024

※remove pass phrase
root@shell# openssl rsa -in server-key.pem -out server-key.pem

※make CERTIFICATE REQUEST
root@shell# openssl req -new -key server-key.pem -out server-csr.pem -days 1000

■자기 서명 파일 생성
X.509 CERTIFICATE 파일(server-cert.pem)을 작성한다. 스스로 사인(자기서명)을 해 둔다.

※서명
root@shell# openssl x509 -in server-csr.pem -out server-cert.pem -req -signkey server-key.pem -days 1000

■private key 파일과 자기서명 파일의 동시 작성
또, 지금까지의 순서를 정리해서 한번에 private key 파일과 자기서명 파일을 작성할 수 있다.

root@shell# openssl req -new -x509 -nodes -keyout server-key.pem -out server-cert.pem -days 1000

■my.cnf설정
키를 작성했으면 mysqld옵션에 지정해 둔다.

[mysqld]
ssl
ssl-key=/usr/local/mysql/secu/server-key.pem
ssl-cert=/usr/local/mysql/secu/server-cert.pem #주의: 서명한 파일.

#ssl-ca=/usr/local/mysql/secu/ca_cert.pem
#ssl-ca는 CA(Certificate Authority) 증명서이다.

제 3자 인증기관 증명이 필요한 경우에는 server-csr.pem파일( Certificate Request)을 해당 기관에 보낸다. 그리고 인증기관으로부터 받은 서명확인완료 파일을 ssl-cert옵션에 지정한다.
또, ssl-ca나 ssl-capath를 지정할 필요가 있다.


클라이언트 키 생성

클라이언트 키 생성도 서버에서와 마찬가지로 만드는 법은 같다.

2009년 10월 8일 목요일

MySQL 보안 - SSL통신


MySQL의 서버와 클라이언트 사이의 통신을 SSL암호화하는 것이 가능하다.
SSL통신을 실행하려면 서버와 클라이언트 양쪽에 SSL을 구성할 필요가 있다.

SSL구성의 확인
mysql>SHOW VARIABLES LIKE 'have_openssl';

결과가 YES 또는 DISABLED이면 서버에 SSL구성되어 있는 것이다.  DISABLED인 경우 SSL은 구성되어있지만 ssl옵션을 붙여서 서버가 기동되지 않았다라는 뜻이다. NO인 경우는 SSL가 포함되어있지 않으므로 소스에서 부터 MySQL을 빌드할 필요가 있다.

SSL구성

configure옵션에서는 --with-ssl를 지정한다.
다만, --with-openssl-includes, --with-openssl-libs, --with-yassl옵션은 5.1.11-beta에서 폐지되었으므로 주의해야한다.

SSL의 구성
shell$ ./configure --with-ssl [=OpenSSL 인스톨 디렉토리]

OpenSSL인스톨 디렉토리를 지정하면 지정된 디렉토리에 있는 OpenSSL라이브러리를 사용한다.
디렉토리지정을 생략하면 소스 부속의 yaSSL(extra/yassl/)를 사용한다.

현재 OpenSSL을 사용할 경우 핸드쉐이크할 때 miss가 적다고 한다.
디렉토리를 지정해서 OpenSSL을 사용하는 것이 좋을 듯 싶다.





2009년 10월 6일 화요일

MySQL 권한 5

Password Hashing

MySQL에서는 패스워드는 독자의 방법으로 암호화된다. (한방향)

MySQL 4.1에서 이 방식이 변경되었다.

mysql> select password('mycom');
+-------------------------------------------+
| password('mycom') |
+-------------------------------------------+
| *5BD79BBCCD59CEB5DC80FB46F393EC6FA414994D |
+-------------------------------------------+
1 row in set (0.00 sec)

mysql> select old_password('mycom');
+-----------------------+
| old_password('mycom') |
+-----------------------+
| 0425a28758eb7712 |
+-----------------------+
1 row in set (0.00 sec)

4.1이상의 패스워드는 PASSWORD() 함수에서 4.0이하의 패스워드는 OLD_PASSWORD()함수로 확인할 수 있다.

또 4.1이상에서 4.0까지의 암호화를 사용하려면 다음과 같은 방법이 있다.

①mysqld --old-passwords
②SQL문에서는 OLD_PASSWORD()함수를 사용한다.

old-passwords옵션을 지정하면 4.1이상의 PASSWORD()함수는 OLD_PASSWORD()함수와 같은 동작을 한다.


4.0이하의 클라이언트에서 4.1이상의 서버에 접속하려고 하면 다음과 같은 에러가 나올 때가 있다.

"Client does not support authentication protocol requested by server; consider upgrading MySQL client"

이것에 대처하기 위해서는 mysql.user.Password컬럼의 값을(패스워드) OLD_PASSWORD()함수로 세팅한다.



MySQL 권한 4

권한 계산

권한의 식을 간단하게 나타내면 다음과 같다.

글로벌권한
OR ( db권한 AND host권한 )
OR table권한
OR column권한
OR routine권한

이것을 테이블로 바꾸면 다음과 같다.

user
OR ( db AND host)
OR tables_priv
OR columns_priv
OR procs_priv

계산순서는 다음과 같다.

①user테이블 권한(글로벌 권한)을 확인
②db테이블 권한 확인
③db.Host == ''일 때, host테이블을 확인한다.
④순차로 tables_priv과 columns_priv, procs_priv테이블 설정을 확인한다.

db테이블과 host테이블 처리에 주의해야한다.


2009년 10월 5일 월요일

MySQL 권한 3

권한 테이블

권한은 "권한테이블"이라고 불리우는 테이블에 기록된다. 권한테이블에는 다음과 같은 것이 있다. 이것은 mysql데이터베이스의 테이블이다. 그리고 권한테이블은 MyISAM이지 않으면 안된다.

  • user
  • db
  • host
  • tables_priv
  • columns_priv
  • procs_priv

●user테이블
글로벌 권한을 세팅한다. 따라서 user테이블의 권한 칼럼에 Y가 세팅되어있으면 다른 권한 테이블에서 N으로 해도 권한 계산 결과는 Y 그대로 이다. 그외에 패스워드나 최대접속횟수, SSL 접속정보등도 기록된다.

●db테이블
데이터베이스에 대한 권한을 부여한다. db.Host == ''의 경우 host테이블을 참조한다.
db.Host == '%'인 경우는 모든 호스트라는 의미가 된다.

●host테이블
host.Host == '' 나 host.Host == '%'의 경우 모든 호스트라는 의미가 된다.

●tables_priv테이블, columns_priv테이블, pros_priv테이블
Db, Table_name, Column_name칼럼에는 ''나 와일드카드는 사용할 수 없다. Host컬럼에는 와일드카드를 사용할 수 있다.
Host컬럼이 '%'또는 ''인 경우에는 모든 호스트라는 의미가 된다.
이 테이블들의 모든 Host, DB컬럼에는 와일드 카드 %, _ 를 사용할 수 있다.
User컬럼 == ''의 경우 Anonymous유저를 나타낸다.

2009년 10월 4일 일요일

MySQL 권한 2

GRANT문으로 지정가능한 권한

FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWN, SUPER권한은 글로벌권한만( ON *.*) 존재하므로 주의해야한다.
이것들은 데이터베이스 단위나 호스트단위로 권한을 바꾸는 것은 되지 않는다.


ALL, USAGE

일반
: ALTER, CREATE, CREATE TEMPORARY TABLES, DELETE, DROP, FILE, INDEX, INSERT, LOCK TABLES, SELECT, SHOW DATABASES, UPDATE

뷰, 스토어드 프로시져, 트리거
CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EXECUTE, TRIGGER

이벤트스케줄러
EVENT

관리자
CREATE USER, PROCESS, RELOAD, SHUTDOWN, SUPER

권한복사
GRANT OPTION

복제
REPLICATION SLAVE
REPLICATION CLIENT



2009년 10월 1일 목요일

MySQL 권한

MySQL권한에는 적용범위가 있다. 권한이 어느 범위에 부여되는지에 대해서 주의할 필요가 있다.

MySQL에서는 이것을 Scope라고 부른다. scope에는 다음과 같은 것이 있다.

글로벌
이 범위에 부여된 권한은 다른 scope에서 어떠한 설정을 하더라도 바뀌지 않는다.

호스트/DB/테이블/컬럼
글로벌권한보다도 적용범위가 좁게 된다. 각각 호스트나 DB단위로 권한을 설정하는 것이 가능하다.
글로벌 scope를 부여한 권한은 (글로벌 권한이라 부른다. ) 다른 scope에의한 설정을 무시한다.

다시말하면, 글로벌로 권한을 부여한 경우 아무리 호스트로 권한을 N으로 하더라도 권한은 부여된 상태이다.

2009년 9월 29일 화요일

MySQL 유저관리3

패스워드 세팅

사용자 패스워드를 세팅하는 경우, 다음과 같은 구문이 된다. 실행에 필요한 권한은 mysql권한테이블에 대해서 UPDATE권한이다.

SET PASSWORD FOR '유저명'@'호스트' = PASSWORD('평문패스워드')

패스워드 세팅은 mysqladmin명령어로도 가능하다.

mysqladmin -u 유저명 password "평문패스워드"
이때 mysqladmin명령어를 실행한 호스트가 MySQL서버위에 인식되어 '유저명'@'호스트' 형식으로 해석된다.


유저명 변경

유저명을 변경하는 데에는 다음 구문을 사용한다.
유저명을 변경하는 데에는 CREATE USER권한, 또는 권한테이블에 대한 UPDATE권한이 필요하다.

RENAME USER '지금 유저명'@'호스트' TO '새로운 유저명'@'호스트' [, old_user TO new_user] ...


권한정보를 다시 읽어들이기

권한테이블 내용을 다시 메모리에 읽어들이기 위해서는 다음과 같이 한다.

shell$ mysqladmin -uroot reload

mysql> FLUSH PRIVILEGES;


GRANT, REVOKE, CREATE USER, DROP USER, SET PASSWORD FOR문을 실행한 경우는 수동으로 다시 읽어들 일 필요는 없다.



2009년 9월 27일 일요일

MySQL 유저관리2

유저권한 확인

유저의 권한을 확인하는 경우 다음과 같은 구문이 된다.

SHOW GRANTS FOR '유저명'@'호스트'

MySQL에서는 유저는 호스트하고 한 쌍이라는 것을 잊지말아야한다.
"USAGE" 행만 표시되는 경우, "아무권한도 가지고 있지않다."라는 의미이다.

유저권한 삭제

유저권한을 삭제하는 경우는 REVOKE문을 사용한다. 실행하는 데에는 GRANT OPTION과 권리를 삭제하는 권한을 갖고 있을 필요가 있다.

유저명과 호스트명을 한 쌍이라는 것을 잊지말아야한다.

모든 권한을 삭제해도 유저 자체가 삭제되는 경우는 없다.

REVOKE 권한 [(필드명 [,필드명 ...] )] [,권한 [(필드명 [,필드명 ...] )] ] ...
ON {
[TABLE] {테이블명|*|*.*|데이터베이스명.*}
|PROCEDURE 데이터베이스명.스토어드프로시져명
|FUNCTION 데이터베이스명.FUNCTION명
}
FROM '유저명'@'호스트' [,'유저명'@'호스트' ]...

REVOKE예제
mysql>REVOKE DELETE ON test.* FROM 'user'@'localhost';


유저삭제
유저를 삭제하는 구문은 다음과 같이 된다. 유저를 삭제하려면 CREATE USER 또는 mysql권한 테이블에 대해서 DELETE권한이 필요하게 된다.
MySQL 4.1까지는 유저에 어떠한 권한이 있으면 삭제가 되지 않았다.

DROP USER '유저명'@'호스트'

2009년 9월 24일 목요일

MySQL 유저관리1: 유저추가

유저를 추가하는 경우 CREATE USER문이던지 GRANT문을 사용한다.

존재하지 않는 유저인 경우에는 자동적으로 추가된다.

1. CREATE USER '사용자명'@'호스트' [IDENTIFIED BY [PASSWORD] '평문 패스워드'] [, '사용자명'@'호스트' [IDENTIFIED BY [PASSWORD] '평문 패스워드']] ...

CREATE USER로 새로이 생성된 유저에는 권한은 없다.


2. GRANT 권한 [(필드명[,필드명...])] [,권한 [(필드명[,필드명...])] ] ...
ON {
[TABLE] {테이블명|*|*.*|데이터베이스명.*}
| PROCEDURE 데이터베이스명.스토어드프로시져명
| FUNCTION 데이터베이스명.FUNCTION명
}
TO '사용자명'@'호스트' [IDENTIFIED BY [PASSWORD] '평문 패스워드']
[, '사용자명'@'호스트' [IDENTIFIED BY [PASSWORD] '평문 패스워드']] ...

[REQUIRE
NONE |
[{SSL|X509}]
[CIPHER 'cipher' [AND]]
[ISSUER 'issuer' [AND]]
[SUBJECT 'subject' ]
]

[WITH 리소스* [리소스*] ...]

리소스*={
GRANT OPTION
| MAX_QUERIES_PER_HOUR 수
| MAX_UPDATES_PER_HOUR 수
| MAX_CONNECTIONS_PER_HOUR 수
| MAX_USER_CONNECTIONS 수
}


ON구절은 MySQL 5.0.6에서부터 사용할 수 있게 되었다. 부여하는 권한은 TABLE, PROCEDURE, FUNCTION가운데 지정한다. 또 REQUIRE구절은 SSL통신을 수행하고자 할 경우 사용한다. WITH구절은 리소스 제한을 하고 싶은 경우, GRANT문을 실행하고 있는 유저의 권한을 부여하고 싶을 경우 지정한다.

권한부여예
mysql>GRANT INSERT, SELECT, UPDATE, DELETE ON test.* TO 'user'@'localhost' IDENTIFIED BY 'pass';



2009년 9월 23일 수요일

MySQL 유저인증과 권한

MySQL에서는 유저명, 패스워드, 권한등은 전부 "mysql" 데이터베이스의 여러개의 테이블(권한 테이블이라고 불리움)에 기록된다.
유저명과 호스트명(IP address)이 셋트로 인증에 사용되고 유저명이 같아도 호스트가 다르면 다른 것으로 취급된다.

유저는 OS계정이나 데이터베이스, MySQL서버 프로세스하고는 전혀 관계가 없다.
또. "데이터베이스 소유자" 라는 개념도 없다.
부여된 권한에 따라서 데이터베이스나 테이블에 관한 조작이 제한되는 것뿐이다.
권한 정보는 기동시에 테이블에서 메모리로 로드된다.

초기 인스톨 상태에서는 모든 조작이 허용되는 'root'@'localhost'(패스워드 없음)가 존재한다.
운용전에 패스워드를 설정하는 것을 잊어버려서는 안된다.
또 'root'라는 유저명을 변경해도 상관없다.

유저명과 호스트

유저명과 호스트는 세트로 인증에 사용된다. 호스트에는 호스트명또는 IP주소, 네트워크지정이 가능하다. 네트워크 지정의 경우는 비트마스크 형식으로는 지정되지 않는 것을 주의해야한다.

유저명과 호스트 예
'user1'@'server1'
'user1'@'server1.domain.jp'
'user1'@'192.168.0.1'
'user1'@'192.168.0.0/255.255.255.192'
'user1'@'192.168.0.%'
'user1'@'%'
''@'127.0.0.1'

  • 127.0.0.1과 localhost
Unix계열 MySQL서버의 경우 MySQL은 "127.0.0.1"과 "localhost"를 다른 걸로 다룬다. 127.0.0.1는 서버에 TCP/IP를 사용해서 접속해온 클라이언트, localhost는 소켓파일을 사용해서 접속해온 클라이언트로 다루게 된다.

  • 와일드카드
호스트 부분의 "%"는 와일드카드로 어떠한 문자열에도 매치한다. 호스트에 지정한 경우는 "모든것"을 의미한다. "_"는 한 문자에 매치한다. 그리고 유저명에는 "%", "_"의 와일드카드는 지정할 수 없다.

  • Anonymous유저
유저부분을 공백으로 한 경우, 어떠한 유저라도 매치하게 된다. MySQL 초기 인스톨 상태의 경우, test데이터베이스에 대해서 이 Anonymous유저가 접근할 수 있도록 되어있다.
실제 운용으로 들어갈 때에는 시큐리티 홀이 되기쉽기때문에 Anonymous유저를 삭제할 것을 추천한다.
Anonymous유저의 경우 mysql.user.User컬럼,mysql.db.User 컬럼, mysql.tables_priv.User컬럼, mysql.columns_priv.User컬럼, mysql.procs_priv.User컬럼이 공문자로 되어있다.
이것에 해당되는 레코드를 삭제하고 FLUSH PRIVILEGES를 실행하면 Anonymous유저를 삭제할 수 있게된다.


Anonymous유저 확인예
mysql>SELECT * FROM mysql.user WHERE mysql.user.User = '';
mysql>SELECT * FROM mysql.db WHERE mysql.db.User = '';
mysql>SELECT * FROM mysql.tables_priv WHERE mysql.tables_priv.User = '';
mysql>SELECT * FROM mysql.columns_priv WHERE mysql.columns_priv.User = '';
mysql>SELECT * FROM mysql.procs_priv WHERE mysql.procs_priv.User = '';


Anonymous유저 삭제예
mysql>DELETE FROM mysql.user WHERE mysql.user.User = '';
mysql>DELETE FROM mysql.db WHERE mysql.db.User = '';
mysql>FLUSH PRIVILEGES;









2009년 9월 22일 화요일

테이블관리7 - InnoDB장애대응

InnoDB는 기동시에 자동적으로 리커버리를 수행한다.
대개의 경우 자동복구된다.
그러나 장애 발생 후에 InnoDB가 기동하지 않던지 "SELECT *"한 다음에 크래쉬되었을 경우 다음처럼 mysqld옵션을 시도해 볼 수 있다.

innodb_force_recovery = { 0|1|2|3|4|5|6 }


0: 기본값. 특수한 경우가 아닌 경우이외에는 값을 바꾸지 말 것.
1(SRV_FORCE_IGNORE_CORRUPT): 페이지파괴를 검출했어도 계속 진행. SELECT *로 덤프가능
2(SRV_FORCE_NO_BACKGROUND): purge조작(필요없는 로그를 지우는 조작)시에 일어나는 크래쉬를 방지
3(SRV_FORCE_NO_TRX_UNDO): 트랜잭션 롤백을 동작시키지 않음.
4(SRV_FORCE_NO_IBUF_MERGE): insert buffer merge조작을 수행하지 않음. 테이블 통계정보도 계산되지 않음.
5(SRV_FORCE_NO_UNDO_LOG_SCAN): UNDO로그를 록하지 않음. 불완전한 트랜잭션을 커밋한 것으로 처리.
6(SRV_FORCE_NO_LOG_REDO): 리커버리로 로그의 roll-forward를 수행하지 않음.


테이블관리6- mysqlcheck옵션

  • 모드관련
--analyze, -a
--check, -c
--optimize, -o
--repair, -r

  • CHECK용 옵션
--auto-repair
--check-only-changed, -C
--extened, -e
--fast, -F
--medium-check, -m
--quick, -q
  • 5.1로 업그레이드체크용 옵션
--check-upgrade, -g
--fix-db-names
--fix-table-names
  • REPAIR용 옵션
--extended, -e
--use-frm
  • 접속용 옵션
--compress
--host=호스트명, -h호스트명
--password[=패스워드] -p[패스워드]
--port=포트번호, -P포트번호
--protocol={TCP|SOCKET|PIPE|MEMORY}
--socket=소켓파일명, -S소켓파일명
--user=유저명, -u유저명
  • 그외 옵션
--all-databases, -A
--all-in-1, -1
--character-sets-dir=디렉토리명
--databases, -B
--debug[=debug_options], -#[debug_options]
--default-character-set=캐릭터셋
--force, -f
--help, -h
--silent, -s
--tables
--verbose, -v
--version, -V


2009년 9월 20일 일요일

테이블관리5- mysqlcheck

mysqlcheck명령어에 의한 테이블 관리

mysqlcheck명령어로는 ANALYZE TABLE, CHECK TABLE, OPTIMIZE TABLE, REPAIR TABLE문을 실행한다.
기본적인 구문은 다음과 같다.

mysqlcheck [모드] [옵션] 데이터베이스명 [테이블명]
mysqlcheck [모드] [옵션] --tables 테이블명 [테이블...]
mysqlcheck [모드] [옵션] --databases 데이터베이스명 [데이터베이스명...]
mysqlcheck [모드] [옵션] --all-databases

myisamchk는 모드 지정에 따라서 동작을 바꾼다. mysqlcheck명령어 표준 동작은 --check(-c)이다.
mysqlcheck명령어 이름을 변경하면(mysqlcheck을 복사, 또는 심볼릭 링크를 사용) 기본 동작이 바뀜으로 주의해야한다.

mysqlrepair = myisamchk --repair
mysqlanalyze = myisamchk --analyze
mysqloptimize = myisamchk --optimize



테이블관리4- myisamchk

MySQL서버의 MyISAM테이블 관리에 관한 옵션

  • --myisam_repair_threads=#
:MyISAM 복구를 위해서 몇개의 쓰레드를 생성할 것인가를 지정한다.

  • --myisam_sort_buffer_size=#
:REPAIR, CREATE INDEX, ALTER INDEX 할 때의 취득되는 작업용 메모리. 인덱스 소트중에도 사용된다.

  • --myisam-recover[=option[,option..]] (option:DEFAULT, BACKUP, FORCE, QUICK)
:MySQL서버 기동후 처음으로 MyISAM 테이블을 열 때 그 테이블이 정상적으로 닫혀지지 않았을 때나 크래쉬한 마크가 있는 경우 자동적으로 그 테이블 복구를 수행한다.
옵션은 콤마로 복수 지정가능하다.

BACKUP: 복구하는 MYD파일의 백업을 작성한다. 파일명은 "테이블명-일시.BAK"이 된다.
FORCE: MYD파일에서 행이 삭제되던지 말던지 복구를 수행한다.
QUICK: MYD 각 행을 체크하지 않는다.
DEFAULT: 기본값. 위 3개를 지정하지 않는 것과 같다.



2009년 9월 15일 화요일

테이블관리3- myisamchk

myisamchk는 MyISAM테이블을 체크하고 복구하는 전용명령어이다.
서버가 테이블을 사용하지 않는 상태(갱신하지 않는, 열려있지 않은 상태)에서 myisamchk를 사용하지 않으면 안된다.
mysql명령어에서 --skip-external-locking 옵션을 사용했을 경우 MySQL 서버를 정지시키지 않아도 myisamchk를 사용할 수 있다.

사용전에는 FLUSH TABLES을 실행해서 일단 테이블을 닫아주어야한다.
또, 체크중에는 LOCK TABLES을 사용해서 클라이언트가 체크중에 있는 테이블에 접근할 수 없도록 해둘 필요가 있다.

기본적인 사용방법은 아래와 같다.
myisamchk [옵션] {테이블명|MYI파일명}

인수로는 테이블명 또는 MYI파일을 지정한다. 복수 지정가능하다.
myisamchk옵션은 my.cnf파일의 [myisamchk]그룹에 기술할 수 있다.

myisamchk는 작업용 파일을 TMPDIR환경변수에 있는 디렉토리밑에 작성한다. (없는 경우는 /tmp디렉토리)
만약 파티션에 여유가 없을 경우에는 out of memory가 나올 수 있다.
그럴 때에는 --tmpdir옵션으로 작업용 파일을 두는 디렉토리를 지정해야한다.

메모리사이즈관련 옵션
--sort_buffer_size, --key_buffer_size, --read_buffer_size, --write_buffer_size

체크관련 옵션
--fast ( -F ), --check-only-changed ( -C ), --medium-check( -m) , --extend-check( -e )
--check (-c), --force( -f), --information( -i ), --read-only( -T ) , --update-state ( -U)

복구관련 옵션
복구할 때 myisamchk는 일시 작업용 파일인 .TMM(인덱스), .TMD(데이터)를 사용한다.
--recover(-r), --safe-recover( -o)
--backup( -B), --character-sets-dir=디렉토리, --correct-checksum, --data-file-length=사이즈(-D 사이즈), --extend-check(-e), --force(-f), --keys-used=정수( -k 정수), --max-record-length=길이,--parallel-recover(-p), --quick(-q), --set-collation=collation명, --sort-recover(-n), --tmpdir=디렉토리(-t 디렉토리), --unpack(-u)

기타옵션
--analyze(-a), --block-search=옵셋(-b옵셋), --description(-d), --set-auto-increment[=정수](-A정수) , --sort-index( -S) , --sort-records=정수(-R 정수), -- verbose(-v), --silent(-s), --version(-V), --help(-h)


2009년 9월 14일 월요일

테이블관리3- 관리SQL

OPTIMIZE TABLE

OPTIMIZE TABLE은 테이블 최적화를 수행한다.

OPTIMIZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE 테이블명 [,테이블명] ..

동작테이블: MyISAM, InnoDB
실행에 필요한 권한: SELECT && INSERT

OPTIMIZE를 InnoDB에 실행하면 OPTIMIZE TABLE은 ALTER TABLE에 맵된다.
MyISAM의 경우는 분산되어 기록된 레코드를 정리해 인덱스페이지를 소트하고 테이블의 통계정보를 갱신한다.
NO_WRITE_TO_BINLOG키워드나 LOCAL키워드가 지정되지 않는한 OPTIMIZE TABLE은 바이너리 로그에 기록된다.
또, mysqld명령어 옵션으로 --skip-new나 --safe-mode가 지정된 경우 OPTIMIZE TABLE은 ALTER TABLE을 실행한다. 이때 모든 테이블형에 대해서 동작하게 된다.

REPAIR TABLE
REPAIR TABLE은 테이블 복구를 수행한다.

REPAIR [LOCAL|NO_WRITE_TO_BINLOG] TABLE 테이블명 [,테이블명] .. [QUICK] [EXTENDED] [USE_FRM]

동작테이블: MyISAM, ARCHIVE, CSV(5.1.9-beta이후)

실행에 필요한 권한: SELECT && INSERT
myisamchk옵션: --recover

옵션 QUICK: MYD파일을 변경하지 않는다. myisamchk명령어를 사용한 경우 myisamchk --recover --quick과 같은 결과를 얻을 수 있다.

옵션 EXTENDED: 레코드별로 인덱스를 생성한다. myisamchk --safe-recover와 같은 결과를 얻을 수 있다.

옵션 USE_FRM: MYI파일이 없는 경우에도 사용할 수 있는 옵션이다. .frm파일과 .MYD파일에서 .MYI파일을 작성한다.





2009년 9월 13일 일요일

테이블관리2- 관리SQL

ANALYZE TABLE

문법: ANALYZE [LOCAL| NO_WRITE_TO_BINLOG] TABLE 테이블명 [, 테이블명]
동작테이블: MyISAM, InnoDB
실행에 필요한 권한: SELECT && INSERT
myisamchk옵션: -a, -analyze
내용: ANALYZE TABLE은 테이블의 인덱스분포를 해석하고 그것을 기록한다.
ANALYZE을 MyISAM테이블에 적용시켰을 경우에는 read lock이 걸리고 InnoDB테이블에 적용시켰을 경우에는 write lock이 걸린다.
NO_WRITE_TO_BINLOG 키워드나 LOCAL키워드가 지정되지 않는 한 ANALYZE TABLE은 바이너리 로그에 기록된다.

사용예
mysql> ANALYZE TABLE tb1\G
*************************** 1. row ***************************
Table: test.tb1
Op: analyze
Msg_type: status
Msg_text: Table is already up to date
1 row in set (0.00 sec)

mysql> show index from tb1\G
*************************** 1. row ***************************
Table: tb1
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: user_id
Collation: A
Cardinality: 1
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:


1.InnoDB에서 ANALYZE TABLE

InnoDB경우 ANALYZE TABLE을 실행하면 SHOW INDEX에 표시되는 인덱스의 카디넬러티(cardinality :인덱스내 유일키의 수를 나타내는 항목)가 결정된다. 그러나 이것은 어디까지나 추정치로 각각의 인덱스 트리를 랜덤으로 조사해서 계산한다.
따라서 ANALYZE TABLE을 반복적으로 실행하면 다른 값이 나타날 수 있다.

2.JOIN과 ANALYZE TABLE

MySQL에서는 JOIN동작을 할때만 이 인덱스 카디넬러티값을 이용한다.
만약 JOIN할 때 확실히 최적화되어 있지 않다고 생각된다면 ANALYZE TABLE이나 OPTIMIZE TABLE을 실행하면 개선될지도 모른다.
그래도 해결되지 않는 경우는 FORCE INDEX구를 SQL문에 사용하는 방법도 있다.

JOIN할 때는 max_seek_for_key에 설정된 횟수이상은 키 스캔을 하지 않도록 옵티마이져에 알리지만 5.1.12-beta 표준치는 4294967295회이므로 보통은 키 스캔을 전부 수행하게된다.


2009년 9월 10일 목요일

테이블관리1 - 관리SQL

테이블 상태 체크나 최적화, 복구등을 수행하기 위한 SQL을 알아보자. 이것은 MySQL서버 기동중에 사용할 수 있다. 명령어 실행중에는 테이블 락이 걸린다. 테이블(스토리지엔진)에 따라서 동작하는 SQL문은 다르다. 적용범위나 세심한 동작, 제한은 버전이 다르면 변경될 수 있으니까 조심해야한다.

CHECK TABLE

문법: CHECK TABLE 테이블명 [,테이블명] ... [체크레벨]
동작테이블: MyISAM, InnoDB, ARCHIVE, CSV(5.1.9-beta이상)
실행에 필요한 권한 : 테이블 접근권한
myisamchk옵션: --check-upgrade, --quick, --fast, --check-only-changed, --medium-check, --extend-check
체크레벨내용:
FOR UPGRADE: 테이블이 MySQL서버에서 올바르게 동작하는지 체크한다. MySQL 5.1.7-beta에서 추가되었음.
QUICK: 부당한 링크체크. 레코드를 스킨하지는 않음.
FAST: 전에 확실히 닫혀지지않았을 것이라고 생각되어지는 테이블만 체크
CHANGED: 전 체크이후에 변경 또는 확실히 닫혀지지 않았을 것이라고 생각되어지는 테이블만 체크
MEDIUM: 기본값. 레코드를 스캔해서 삭제된 링크가 맞는지 그렇지 않은지 체크. 키의 체크섬을 계산해서 확인한다.
EXTENDED: 모든 레코드를 스캔해서 모든 키를 체크한다. 확실하지만 시간이 걸린다.

CHECKSUM TABLE

문법: CHECK TABLE 테이블명 [, 테이블명] ... [QUICK|EXTENDED]
동작테이블: MyISAM
실행에 필요한 권한: 테이블 접근권한
내용: 테이블 체크섬값을 리턴해준다.




2009년 9월 9일 수요일

로그파일감시3

3.FIFO 특수파일을 이용한 자작툴 제작

예를들어 General로그 파일의 옵션 --log=에 FIFO특수파일을 지정할 수 있다.
Unix계열에서는 문제없이 동작한다.

지정된 FIFO특수 파일을 읽어들이는 툴을 만들면 될 것이다.
자작툴이 FIFO를 읽어들이기 전용으로 오픈하는 것으로 해놓고 MySQL서버를 기동한다.

다음 코드는 FIFO파일을 읽어 그것을 표준출력에 보내는 단순한 C샘플코드이다.
인수처리, FIFO파일을 작성하는 처리, 에러처리, 시그날을 받았을 경우의 처리등 자세한 처리는 하지 않고 있으므로 본격적으로 사용하려면 수정을 해야할 것이다.

FIFO파일은 Linux에서는 mkfifo명령어로 간단히 작성가능하다.

FIFO특수파일 작성
shell$ mkfifo --mode=660 /tmp/mylog

/****샘플코드 ****/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#define LOGFIFO "/tmp/mylog"

int main(int argc, char **argv)
{
int fd;
char buf[256];
ssize_t st_rd;

fd=open(LOGFIFO, O_RDONLY|O_NONBLOCK);
if ( fd == -1 ){
printf("can't open FIFO file.¥n");
exit(1);
}
while(1) {
st_rd = read(fd, buf, sizeof(buf)-1);
if ( st_rd > 0 ) {
buf[st_rd] = '¥0';
fputs(buf, stdout);
}
else if ( st_rd == 0 ) {
}
}//while end
close(fd);
exit(0);
}







로그파일감시2

2.swatch, logsurfer, logcheck등의 로그감시 툴을 사용

파일에 로그가 써 졌을 경우, swatch나 logsurfer, logcheck등의 툴을 사용할 수 있다.
swatch와 logsurfer는 데몬으로 파일을 감시한다.
logsurfer는 C로 만들어져 있고 swatch는 Perl로 기술되어 있다.

한개의 파일당 한개의 데몬을 띄울 필요가 있다. logcheck는 쉘 스크립트로 만들어져서 cron으로 기동되는 것을 전제로 하고 있다.




로그파일감시

에러로그 파일, slow query 로그파일, General로그파일을 감시하고 싶다는 것은 당연한 요구 일 것이다.
현재 다음과 같은 방법을 사용할 수 있다.
  1. syslog에 보낸다.
  2. swatch, logsurfer, logcheck등의 로그 감시툴을 사용
  3. FIFO특수파일을 이용한 자작 툴을 제작

1.syslog에 보낸다.

mysqld_safe을 개조해서 mysqld에서 받은 에러 메세지를 syslog에 보내는 방법이다.
mysqld_safe안에서 에러 출력을 logger등의 명령어에 보내면 실현가능하다.

syslog에 보낸 경우 syslog감시 툴을 사용할 수 있다.

mysqld_safe가 생성하지 않는 로그파일을 감시하는 경우는 tail등으로 파일을 볼 필요가 있다.
이 때 주의점은 파일이 변경된 경우 예를 들어 tail -f 실행중에 로그파일을 이동하고 FLUSH LOGS를 실행할 때등이다.

이 같은 경우에는 tail은 이동된 쪽의 파일을 보고 있기때문에 (최초로 열린 파일 디스크립터를 보고 있다. ) 로테이트로 새로 생긴 파일은 보지 않는 것을 주의해야한다.

GNU tail에서는 tail --follow=name --retry /data/host.log처럼 이 상황에 대처할 수 있는 옵션이 제공되고 있다.





2009년 9월 8일 화요일

로그활용8 - 바이너리로그

mysqlbinlog을 사용한 데이터 복구

mysqlbinlog를 사용해서 데이터를 복구하는 데에는 파이프라인을 직접 이용하는 방법과
일단 파일로 출력한 다음에 그것을 사용하는 방법이 있다.

shell$ ./bin/mysqlbinlog ./data/host-bin.000001 | ./bin/mysql

shell$./bin/mysqlbinlog ./data/host-bin.000001 < bin.000001
shell$./bin/mysql > bin.000001

바이너리로그 이벤트 확인

SHOW BINLOG EVENTS를 실행하면 바이너리로그 이벤트를 확인할 수 있다.
LIMIT구문이 없으면 모든 이벤트가 나오므로 주의해야한다.

SHOW BINLOG EVENTS
[IN '로그파일명'] [FROM 위치] [LIMIT [오프셋,] 갯수]




로그활용7 - 바이너리로그

바이너리로그 목록표시

현재 존재하는 바이너리 로그 리스트를 출력하는 경우는 SHOW BINARY LOGS문, 또는 SHOW MASTER LOGS문을 사용합니다.

바이너리로그 리스트를 표시
mysql> SHOW BINARY LOGS;
또는
mysql>SHOW MASTER LOGS;

바이너리로그 삭제

바이너리로그 파일을 삭제하는 방법은 PURGE MASTER LOGS TO문을 사용한다.

바이너리로그 삭제
mysql>PURGE MASTER LOGS TO 'server-bin.000005';

PURGE MASTER LOGS TO문으로 바이너리로그 파일명을 지정한다. 지정된 바이너리로그 보다 작은 숫자 파일이 제거된다. 위 예를 보면 server-bin.000004까지의 번호 파일이 삭제되고 server-bin.000005은 삭제되지 않는다.

바이너리로그 변환

바이너리로그 파일을 에디터나 페이저로 보더라도 의미를 알 수 없다.
확실히 읽기 위해서 텍스트로 변환시켜주는 것이 mysqlbinlog명령어이다.
다음처럼 조작한다.

mysqlbinlog명령어 실행
shell$ ./bin/mysqlbinlog ./data/host-bin.000001
..
..

바이너리로그에는 오퍼레이터가 실행하지 않은 것도 기록된다.
mysqlbinlog를 실행하면 그 정보도 SQL문으로 출력된다.
그것이 주석이나 SET문이다.
주석은 # 이나 /* 로 시작한다.
mysqlbinlog로 생성된 SQL문을 원래대로 데이터를 복원하지 않으면 안되기때문에 SET문에서는 TIMESTAMP 나 AUTO_INCREMENT 값이 복원전과 복원후가 틀리지 않도록 지정한다.

또, SQL문 실행시에는 캐릭터셋도 문제가 되기 때문에 @@session.character_set_client등으로 지정한다.
[# at숫자]는 바이너리 로그 파일에 있어서 기술위치(바이트)이다.
[# at숫자]에서부터 [# at숫자]사이를 이벤트라고 부른다.


2009년 9월 7일 월요일

로그활용6 - 바이너리 로그

sync_binlog(--sync-binlog)

표준으로는 이 값은 0으로 바이너리 로그의 디스크로의 동기를 위한 기록은 실행되지 않는다.
바이너리로그를 동기처리 하기 위해서는 sync_binlog옵션으로 사용한다.

--sync_binlog[=숫자]

또 SET문으로 동적으로 유효로 하는 경우도 가능하다. 다음처럼 조작한다.

바이너리로그 동기를 유효로 하기
mysql> SET GLOBAL sync_binlog=1;

sync_binlog가 유효인 경우 MySQL서버는 바이너리로그 기록에 fdatasync()를 사용한다.
지정한 값이 1이고 트랜잭션인 경우 트랜잭션마다 fdatasync()를 실행하고 트랜잭션이지 않은 경우는 한문장마다 실행한다.
이것으로 트랜잭션 단위로 확실히 바이너리 로그에 기록된다.

값이 1이상인 경우는 지정된 회수의 이벤트가 발생한 후에 flush를 수행한다.

디스크 I/O는 늘어나지만 안전성을 요구하는 경우에는 1을 추천한다.

그외 바이너리로그에 관한 옵션

  • binlog-do-db=데이터베이스명 : 지정된 데이터베이스변경만을 바이너리 로그에 기록한다.
  • binlog-ignore-db=데이터베이스명 : 지정된 데이터베이스변경만 기록하지 않는다.
  • binlog-row-event-max-size=수: 표준값1024, binlog_format=ROW인 경우 1이벤트 최대사이즈(바이트수) 256배수를 지정한다.
  • log-bin-trust-function-creators: 표준값0(무효) 1로 지정하면 stored procedure나 트리거 작성은 SUPER권한을 가진 유저만 실행가능하게 되고 바이너리로그를 부시지않는 것만 작성이 허용된다. binlog_format=ROW의 경우는 항상 바이너리로그는 안전

로그활용5 - 바이너리 로그

바이너리 로그는 갱신쿼리를 기록한 것으로 리커버리및 replication에 사용되는 중요한 로그파일이다.
실행된 갱신계 쿼리문이 이 파일에 기록된다.

또, 기록순서는 트랜잭션도 고려하고 있다.

log-bin(--log-bin)
log-bin은 바이너리 로그를 유효로 했을 경우에 사용한다. 다음과 같이 지정한다.

log-bin[=파일명 접두어]

파일명이 생략된 경우는 datadir/호스트명-bin.NNNNNN이 된다.
NNNNNN는 6자리 숫자로 MySQL이 자동으로 부여하는 수치이다.

이것은 000000부터 시작된다.
바이너리로그는 표준으로는 1G바이트 크기에 도달하면 자동으로 로테이트한다.
이 때 파일의 숫자부분에 1이 더해진 파일이 생기고 꼿에 새로운 로그가 기록된다.
현재의 로그는 가장 숫자가 큰 파일에 기록되고 있다는 것이다

로테이트는 FLUSH LOG문으로 강제적으로 실행하는 것도 가능하다.

log-bin-index(--log-bin-index)
log-bin-index는 바이너리 로그 인덱스 파일의 파일명을 변경한다. 바이너리로그 인덱스파일은
바이너리 로그 파일의 목록을 가지고 있는 파일이다. 현재 어떤 바이너리 로그 파일이 있는지를 나타낸다. 표준으로는 datadir/호스트명-bin.index라는 파일에 보존된다.

FLUSH LOGS나 PURGE MASTER LOGS TO를 실행하면 이 파일도 자동으로 변경된다.
바이너리로그 인덱스파일의 파일명을 변경하는 경우는 다음처럼 지정한다.

log-bin-index=파일명

max_binlog_size(--max_binlog_size)
max_binlog_size는 한개의 바이너리로그 파일의 최대 사이즈(바이트)를 지정한다.
여기에서 지정된 사이즈보다 파일이 커지는 경우 자동으로 로테이트한다.
다음처럼 지정한다.

max_binlog_size=숫자

또 SET으로 MySQL서버 기동시에도 변경하는 것이 가능하다.

MySQL서버 기동중에 변경하기
mysql> SET GLOBAL max_binlog_size=104857600;

binlog_cache_size(--binlog-cache-size)
MySQL은 바이너리로그에 써 내리는 내용을 캐쉬하지만 그 캐쉬 사이즈(바이트)를 지정하는 경우는 binlog_cache_size옵션을 사용한다.

binlog_cache_size=1048576

SET문을 사용해서 MySQL기동시에 동적으로 변경하는 것이 가능하다.

캐쉬사이즈를 변경
mysql> SET GLOBAL binlog_cache_size=1048576;

binlog_format(--binlog-format)
MySQL 5.1.5에서 바이너리 로그 포맷에 행 기준 기술방법이 도입되었다.
종래 SQL문을 기록한 바이너리 로그에서는 replication을 실행할 때에 slave 서버도 순서대로 SQL문을 실행하지 않으면 안되었기때문에 시간이 걸리는 쿼리를 실행할 때에는 slave내용은 마스터에 대해서 매우 늦어지는 경우가 있었다.
그러나 행 기준 포맷 바이너리로그를 사용하면 replication할 때에는 행의 변경만이 전달되어지기 때문에 slave처리도 빠르게 된다.

바이너리 로그의 포맷 변경에는 binlog_format 옵션을 사용한다. 기본 포맷은 종래와 마찬가지로 SQL문을 저장한다. 버젼 5.1.8부터는 SQL문 포맷이나 행 기준 포맷, 모두 섞어서 기록할 수 있게도 되었다.

bin_format={ROW|STATEMENT|MIXED}

binlog_format에 주어지는 값은 다음과 같다.

1또는 STATMENT SQL문장을 기록
2또는 ROW 행 기준 바이너리로그를 기록
3또는 MIXED 보통은 STATEMENT와 같은 동작을 하지만 다음과 같은 경우 자동으로 ROW으로 전환된다.
UDF이나 UUID()를 사용했을 경우
Cluster리플리케이션을 사용했을 경우

2또는 ROW를 지정하면 텍스트로 변환한 바이너리로그는 다음과 같이 기재된다.
이것은 다른 SQL문과 마찬가지로 mysql명령어로 처리가능하다.

행기준 바이너리 로그 파일
BINLOG '
3w0rRRMBAAAAJgAAACYAAAAAAA4AAAAAAAABHR1c3QAAWEAAQM=
';
또 SET문으로 동적으로 변경하는 경우는 다음처럼 지정한다.

replication포맷을 SQL문 레벨로 변경
mysql> SET GLOBAL binlog_format="SATATEMENT";

다음과 같은 경우는 SET문으로 동적으로 포맷을 변경하는 것이 불가능하다.

1. stored procedure나 트리거 안
2.NDB가 유효한 경우
3.세션이 ROW기준으로 되어있고 일시 테이블을 사용하고 있는 경우




2009년 9월 3일 목요일

로그활용4 - slow query log

slow-query-log(--slow-query-log)

처리에 시간이 걸린 쿼리를 기록하기 위한 옵션이다.
쿼리 실행에 long_query_time에 세팅된 초수(표준 10초)이상 시간이 걸린 경우 기록된다.
기록장소는 mysql.slow_log테이블이던지 slow_query_log_file변수에 지정된 파일(--log-slow-quries옵션에 지정된 파일)이다.
로그의 출력위치를 테이블이나 파일로 할 것인지 하는 것은 log-output옵션에서 지정한다.

MySQL서버 기동중에 slow query log를 얻기위한 지시예
mysql> SET GLOBAL slow_query_log=1;
초수를 3초로 변경하는 예
mysql> SET GLOBAL long_query_time=3;

log-slow-queries(--log-slow-queries)
처리에 시간이 걸린 쿼리를 기록하는 로그파일이다. 이 파일은 FLUSH LOGS로는 로테이트할 수 없다. 또 서버 재기동시에도 로테이트 하지 않는다.
다음 처럼 지정한다.

log-slow-queires[=파일명]

파일명을 생략하면 datadir/호스트명-slow.log로 된다.
또, MySQL서버 기동중에도 slow query log를 기록할건지 말건지 지정하는 것이 가능하다.

MySQL서버 기동중에 slow query log를 유효로 하기
mysql> SET GLOBAL slow_query_log=1;

slow query log의 로그파일을 지정하는 경우는 다음 처럼 조작한다.
mysql> SET GLOBAL slow_query_log_file="/tmp/slow";

또한 SHOW VARIABLES로 봤을 때의 log_slow_queries는 slow query log가 기록되고 있는지에대한 여부를 나타내는 변수로 이것을 SET로 변경하는 것은 불가능하다.

log_queries_not_using_indexes(--log_queries_not_using_indexes)
log_queries_not_using_indexes를 지정하면 인덱스를 사용하지 않은 쿼리도 slow query log에 기록할 수 있다.

log_queries_not_using_indexes

다음처럼 서버기동중에는 SET로 변경하는 것이 가능하다.

MySQL서버기동중에 변경하기
mysql> SET GLOBAL log_queries_not_using_indexes=ON;

long-query-time(--long-query-time)
long-query-time에서는 지정한 초수보다 처리에 시간이 걸린 쿼리를 기록하게 된다.
다음 처럼 지정한다.

long-query-time=초수

또, SET에서 MySQL서버 기동시에도 변경가능하다.

MySQL서버 기동중에 변경하기
mysql> SET long_query_time=5;






2009년 8월 31일 월요일

로그활용3 - 일반로그

log(--log)
MySQL서버처리를 상세하게 기록하는 로그파일이다. 언제 어떤유저(포함하는 호스트)가 접속해서 어떤 쿼리를 실행했는가가 상세하게 기록된다.
기록은 MySQL서버가 접수한 순서대로 기록된다. 트랜잭션 상태는 고려하는 않는다.
어플리케이션과 연계 디버그나 보안감사에 사용할 수 있다.

이 옵션을 지정하면 general-log옵션이 자동적으로 ON이 된다.
다음처럼 지정한다.

log[=파일명]

파일이름을 생략하면 datadir/호스트명.log파일이 된다. 이 파일은 FLUSH LOGS로는 로테이트되지 않는다. 또 서버 재기동시에도 로테이트하지 않는다.
이 파일을 로테이트하려면 Unix계열에서는 다음처럼 한다.

log를 로테이트한다.
root@shell# mv hostname.log hostname.log.0
root@shell# mysqladmin flush-logs

general-log(--general-log)

general-log는 MySQL5.1이상에서의 기능이다. 이 옵션을 지정하면 mysql.general_log테이블에 General로그가 출력된다.
옵션은 다음처럼 지정한다.

general-log

또, MySQL서버 기동중에 SET문으로 값을 변경하면 유효로 할 수 있다.

MySQL서버기동중에 general-log를 유효로 세팅
mysql> SET GLOBAL general_log=1;

mysql.general_log테이블이 존재하지 않는 경우는 mysql_fix_privilege_tables스크립트를 실행하고 테이블을 작성해야한다. 이 테이블은 CSV스토리지엔진으로 작성되어 있다.
또, 이 옵션이 지정된 경우 보통 --log로 지정된 파일에는 로그를 기록하지 않는다.
주의점은 이 테이블의 캐릭터셋이다.

general_log
CREATE TABLE `general_log`(
...
중략
`command_type` varchar(64) DEFAULT NULL,
`argument` mediumtext
) ENGINE=CSV DEFAULT CHARSET=utf8

이 처럼 실행한 SQL문은 argument헤더에 utf8캐릭터셋으로 기록된다.
만약 UTF-8로 변환불능한 문자가 쿼리에 포함되어 있었을 경우는 이 부분 기록은 옳바르지 않게 된다.
덧붙여 말하면 mysql.general_log테이블에 대해서 DELETE/UPDATE/INSERT문은 실행할 수 없다. FLUSH LOGS를 실행해도 내용은 없어지지 않지만 TRUNCATE TABLE문을 사용해서 내용을 전부 제거하는 것은 가능하다. 또 이 옵션이 무효인 경우(general로그를 출력하지 않을 때)에는 ALTER TABLE문으로 스토리지엔진을 바꾸거나 DROP TABLES문으로 파기하는 것도 가능하다.

log-output(--log-output)

log-output는 general로그와 slow query로그 출력위치를 지정한다.

log-output=값[,값]

값에는 TABLE, FILE, NONE을 지정할 수 있다.

TABLE: mysql.general_log테이블에 쓴다.
FILE: --log옵션으로 지정된 파일에 쓴다.
NONE:로그를 출력하지 않는다. 다른 지정보다 우선도가 높다.

또 , 값을 "," 로 복수 지정하는 것도 가능하다.

log-output=FILE,TABLE

이 경우는 파일과 테이블 양쪽에 출력하게 된다.
log-output는 MySQL서버기동중에 SET문을 사용해서 변경하는 것도 가능하다.

MySQL서버 기동중에 출력위치를 변경
mysql>SET GLOBAL log_output="FILE,TABLE";



2009년 8월 27일 목요일

로그활용2 - 에러로그

log-error(--log-error)

log-error는 실행중의 에러정보와 기동,정지시의 시각을 기록한다.

Unix계의 mysqld는 에러를 표준에러에 출력한다.

출력된 에러는 mysqld_safe와 mysqlmanager가 받아 보존한다.

그러나 mysqld자신이 에러를 파일에 쓰는 옵션이 있다. 다음처럼 지정한다.

log-error[=파일명]

파일명이 생략된 경우 datadir/호스명.err파일이 된다.
FLUSH LOGS를 실행하면 로그는 로테이트가 되어 전에 있던 에러 파일은 로그파일명-old로 이름이 변경된다.

log-warnings(--log-warnings)
log-warnings를 지정하면 에러로그에 쓰여지는 정보가 늘어난다. Replication(복제)를 실행할 때에는 이 옵션을 사용하는 게 좋다.

log-warnings[=level]

[level]에 1이 넘는 숫자를 지정하면 접속이 정상적으로 끊어지지 않았다는 경고메세지 Aborted connections이 출력된다. 기본값은 1이다.




로그활용1

로그의 종류

MySQL로그에는 데이터베이스내에서 일어나는 여러가지 사건들이 기록되기때문에 로그를 읽는 것으로 데이터베이스서버 운용에 빠질 수 없는 중요한 정보를 얻는 것이 가능하게 된다.

MySQL 5.1.12-beta로그에는 다음과같은 것이 있다.
  • 에러로그(log-error/ log-warnings)
  • General로그(log/ general-log)
  • slow query로그(log-slow-queries / slow-query-log)
  • 바이너리 로그(log-bin)
  • ISAM로그(log-isam)
log-isam은 MyISAM 변경을 기록하는 파일이다.
개발자대상 디버그 정보가 기록되기때문에 보통은 사용하지 않는다.

MySQL은 기본적으로는 로그를 기록하지 않기때문에 로그를 기록할 경우는 mysqld 기동시에 기록하고픈 로그를 옵션으로 지정하던지 설정파일 my.cnf(또는 my.ini)의 [mysqld] 그룹에 기술한다.






2009년 8월 26일 수요일

로그의 활용

로그의 로테이트

로그를 로테이트하기위해서는 SQL문을 실행하던지 mysqladmin명령어를 실행한다.

로그의 로테이트
mysql> FLUSH LOGS;
또는
shell$ mysqladmin flush-logs
또는
shell$ mysqladmin refresh




2009년 8월 25일 화요일

MySQL 리커버리

바이너리로그로 리커버리

바이너리로그를 사용하면 point in time recovery(roll forward recovery)라고도 말할 수 있는 리커버리가 가능하다.

바이너리 로그는 mysqlbinlog로 SQL문으로 변환이 가능하다.

shell$ ./bin/mysqlbinlog ./data/host-bin.000001
...
...
shell$ ./bin/mysqlbinlog ./data/host-bin.000001 | mysql -uroot


리커버리를 위한 운용
운용에 있어서 리커버리를 전제로 백업을 생각해 둘 필요가 있다.
단순한 방법은 풀 백업을 작성할 때 한번 MySQL서버를 정지시키는 것이다.
그 다음 기동후부터 바이너리로그를 리커버리에 사용하면 되기 때문이다.

MySQL서버를 정지시키지 않은 상태에서 풀 백업을 실행하고 바이너리 로그를 순환생성(rotate)하고 풀백업후의 바이너리로그 위치를 알기 위해서는 다음과 같은 SQL문을 사용하면 될 것이다.

//리커버리를 고려한 풀 백업 준비
FLUSH TABLES WITH READ LOCK;
SHOW MASTER TABLES;
FLUSH LOGS;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSATION WITH CONSISTENT SNAPSHOT;


권한테이블 이외에 모든 InnoDB의 경우 mysqldump의 다음 옵션으로 실현가능하다.

[mysqldump]
flush-logs
master-data=2
single-transaction

또, 모든 테이블이 MyISAM테이블인 경우에는 mysqldump의 다음 옵션으로 가능하다.

[mysqldump]
flush-logs
master-data=2
lock-all-tables

이것으로 풀백업을 하고 바이너리로그의 위치를 아는 것이 가능하다.
다만 local-all-tables옵션의 경우 READ 록을 건다는 것을 잊지 말길 바란다.


2009년 8월 23일 일요일

MySQL 리스토어 (복구)

운영체제의 명령어로 복사
운영체제의 명령어로 파일 백업을 한 경우는 같은 형식으로 파일을 복사해서 되돌린다.
작업전에는 MySQL서버는 정지시켜둔다.

InnoDB의 경우는 데이터파일의 기술(파일 개수, 순번, 사이즈)를 백업과 동시에 할 필요가 있다.

innodb_data_file_path, innodb_log_files_in_group, innodb_log_files_size의 기술에 주의해야한다.

LOAD DATA, mysqlimport(mysqldump로 SQL문이 아닌 형태로 백업한 경우)
mysqldump의 다음 옵션을 사용해서 SQL문이 아닌 다른 형태(CSV등)로 데이터를 백업한 것을 리스토어하는 SQL문이 LOAD DATA이다.

--tab, --fields-terminated-by=, --fields-enclosed-by=, --fields-optionally-enclosed-by=, --fields-escaped-by=, --lines-terminated-by=

mysqlimport라는 명령어로도 리스토어 가능하다. mysqlimport는 내부에 LOAD DATA문을 실행하고 있다.

◎LOAD DATA
LOAD DATA를 사용할 때에는 다음을 주의해야한다.
  • 테이블은 별도 작성해둘 것
  • 실행에는 FILE권한이 필요.
◎mysqlimport명령어
mysqlimport는 LOAD DATA문을 사용해서 파일의 내용을 테이블에 흘려 넣는다.
필드구분자등의 옵션은 mysqldump을 실행했을 때와 일치시켜줘야한다.
구문은 다음과 같다.

mysqlimport [옵션] 데이터베이스명 파일명

mysqlimport는 my.cnf의 [mysqlimport] [client]그룹을 읽어들인다.

mysql명령어(mysqldump에서 SQL문으로 백업한 경우)
mysqldump로 출력된 내용은 보통 SQL문이다. SQL문이라면 mysql명령어로 리스토어가 가능하다.

mysql명령어로 리스토어
shell$ mysqldump --default-character-set=binary --hex-blob test > test_dump.sql
shell$ mysql --default-character-set=binary test < test_dump.sql

캐릭터셋 지정은 mysqldump, mysql명령어가 같아야한다.

RESTORE TABLE
BACKUP TABLE로 백업한 경우, 리스토어에는 RESTORE TABLE을 사용한다.
BACKUP TABLE과 마찬가지로 MySQL 5.2이후에는 없어질 예정이다. MyISAM테이블에서만 동작한다.
구문은 다음과 같다.

RESTORE TABLE 테이블명[,테이블명]... FROM '/저장될 디렉토리'

디렉토리는 풀 패스로 지정해야한다. 지정된 디렉토리에서 .frm과 .MYD파일을 복사해서 .MYI파일을 작성한다.


MySQL 백업4

InnoDB Hot Backup
InnoDB Hot Backup은 InnoDB개발회사인 Innobase Oy Inc(http://www.innodb.com/)에서 제공되는 유료 백업 툴이다.
이 툴은 서버를 정지하지 않고 InnoDB파일을 백업할 수 있다.
ibbackup이라는 명령어가 상품이다.

또 ibbackup은 /etc/my.cnf파일과 MyISAM테이블등은 백업하지 않는다.
ibbackup은 호출하는 innobackup이라는 Perl스크립트도 제공된다. 이것은 GPL v2이다.

innobackup은 frm파일과 MyISAM파일도 동시에 백업한다.

BACKUP TABLE
MySQL 5.2이후에는 없어질 예정이다. MyISAM테이블에서만 동작한다.

BACKUP TABLE 테이블명 [,테이블명] ... TO '저장할 디렉토리'

디렉토리는 풀 패스로 지정한다.
버퍼를 flush한 후 지정된 디렉토리에 .frm과 .MYD파일을 복사한다.
.MYI파일은 myisamchk 나 REPAIR TABLE USE_FRM으로 언제든지 재작성가능하다.
또, 백업중에는 테이블에 READ lock이 걸린다.


2009년 8월 18일 화요일

mysqldump를 이용한 백업

mysqldump는 논리 백업이다.

SQL문으로 데이터 내용을 얻는 것이 가능하다. 그렇지만 차분만 백업하는 것을 불가능하다.

사용방법은 다음과 같다.

mysqldump 옵션 데이터베이스명 [테이블명 [테이블명...] ]
mysqldump 옵션 --databases 데이터베이스명 [데이터베이스명..]
mysqldump 옵션 --all-databases

mysqldump는 my.cnf 의 [mysqldump] 그룹과 [client]그룹 설정을 읽어들인다.
옵션을 생략했을 경우는 다음과 같은 옵션이 지정된 것과 똑같다.

--opt --comments --tz-utc --set-charset --triggers

mysqldump와 데이터의 일관성
--single-transaction옵션은 InnoDB에 대해서 유효하다. 이 옵션은 다음 SQL를 실행한다.

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION WITH CONSISTENT SNAPSHOT;

이것으로 백업하는 모든 테이블이 InnoDB이면 데이터 일관성이 보증된다.
--master-data=2 옵션을 추가하면 바이너리 위치도 모순없이 기록된다.

InnoDB이외의 테이블 타입의 경우 일관성을 보증하고 싶다면 --lock-all-tables를 지정해서 테이블이 갱신되지 않게 록을 걸어 두어야 한다.

mysqldump와 캐릿터셋, 바이너리 데이터
mysqldump의 표준 캐릭터셋은 utf8이다.
만약 테이블 캐릭터셋이 utf8이 아니고 mysqldump에 --default-character-set=옵션을 지정하지 않으면 데이터의 문자코드 변환이 발생한다.

그러면 소실 혹은 다른 문자로 변환될 가능성이 있다. mysqldump를 사용할 때는 반드시 위 옵션을 지정해야한다.

데이터에 바이너리 컬럼이 포함되는 경우도 주의해야한다.
바이너리 컬럼이 포함되어있는 경우에는 다음과 같은 옵션을 지정한다.

--hex-blob

이것은 BLOB, BINARY필드값을 0xABCD같이 HEX리터널로 출력한다.
HEX리터널이기 때문에 리스토어할 때에 파괴될 걱정이 없어진다.

캐릭터셋은 데이터베이스 단위로 통일 시켜두는 게 좋다. 예를 들어 테이블 단위에 캐릭터셋을 변경한 경우 mysqldump를 실행해서 데이터베이스를 백업하면 다른 캐릭터셋이 혼재되어 출력된다.
SET NAMES의 구현은 불완전하기 때문에 안이하게 신용할 수도 없다.
따라서 캐릭터셋은 테이블 단위나 필드단위로 변경하지 않는 것이 좋다.




2009년 8월 17일 월요일

MySQL 백업3

mysqlhotcopy


1. 복사할 곳이 디렉토리인 경우
mkdir 복사할곳디렉토리/데이터베이스명
LOCK TABLES 테이블 READ;
FLUSH TABLES;
cp -p 테이블명.{frm, MYD, MYI} 복사할곳디렉토리/데이터베이스명/
UNLOCK TABLES;

2.복사할 곳이 데이터베이스인 경우
mkdir datadir/데이터베이스명
LOCK TABLES 테이블 READ;
FLUSH TABLES;
cp -p 테이블명.{frm, MYD, MYI} datadir/데이터베이스명/
UNLOCK TABLES;

3.복사할 곳이 지정이 없는 경우
mkdir datadir/데이터베이스명_copy
LOCK TABLES 테이블 READ;
FLUSH TABLES;
cp -p 테이블명.{frm, MYD, MYI} datadir/데이터베이스명_copy/
UNLOCK TABLES;

데이터베이스명은 복사하는 테이블이 포함되어있는 데이터베이스명이다.

4.옵션
--addtodest : 백업할 곳이 존재하는 경우 멈추지 않고 덮어 씌운다.
--allowold : 백업할 곳이 존재하는 경우 임시로 옮겨놓고 백업이 다 끝난 후 임시로 옮겨논 곳을 지운다.
--keepold : 백업한 곳이 존재하는 경우 임시로 옮겨놓고 백업을 진행한다.
--checkpoint 데이터베이스명.체크포인트테이블명 : 지정한 테이블에 작업기록을 남긴다. 테이블에는 다음과 같은 필드가 필요한다.
time_stamp timestamp not null
src varchar(32)
desc varchar(60)
msg varchar(255)
이 옵션을 지정하면 처음에 이 테이블에 대해서 SELECT가 실행된다.
--flushlog : 테이블 록을 건 다음 FLUSHLOGS를 실행한다.
--method={cp|scp}: scp는 아직 Alpha레벨
--noindices : 인덱스파일 전부를 복사하지 않는다. MYI파일 앞부분 2048바이트까지만 복사한다. myisamchk로 MYI는 작성가능
-q, --quit : 에러만 출력한다.
--record_log_pos 데이터베이스명.체크포인트테이블명 : 복사하기 전에 SHOW MASTER STATUS, SHOW SLAVE STATUS로 얻어진 로그 위치를 지정한 테이블에 기록한다. 테이블에는 다음과 같은 필드가 필요한다.
CREATE TABLE 테이블명 {
host varchar(60) NOT NULL,
time_stamp timestamp(14) NOT NULL,
log_file varchar(32) default NULL, -- SHOW MASTER STATUS의 File
log_pos int(11) default NULL, -- SHOW MASTER STATUS의 Position
master_host varchar(60) NULL, -- SHOW SLAVE STATUS의 master_host
master_log_file varchar(32) NULL, -- SHOW SLAVE STATUS의 master_log_file
master_log_pos int NULL, -- SHOW SLAVE STATUS의 master_log_pos
PRIMARY KEY(host)
}
이 옵션을 지정하면 처음에 이 테이블에 대해서 SELECT가 실행된다.
--resetmaster : 테이블 록을 건 후 복사하기 전에 RESET MASTER를 실행한다.
--resetslave: 테이블 록을 건후 복사하기 전에 RESET SLAVE를 실행한다.
--regexp 패턴 : 패턴에 맞는 데이터베이스를 복사한다.
--regexp /패턴1/./패턴2/ : 패턴1에 맞는 데이터베이스에 , 패턴2에 맞는 테이블을 복사한다.
--suffix= : 기본값은 --suffix=_copy 백업 이름의 접미사.

-u, --user= : 사용자명
-h, --host= : 호스트지정
-p, --password= : 패스워드 지정
-P, --port= : 포트번호 지정
-S, --socket= : 소켓파일지정

--debug : 상세한 정보를 표시
-n, --dryrun : 실제로는 실행하지 않음.




2009년 8월 11일 화요일

MySQL 백업2

mysqlhotcopy를 이용한 백업

mysqlhotcopy는 MyISAM, ARCHIVE테이블에서만 동작하는 Perl로 기술된 스크립트이다.
테이블에 록을 걸고 데이터를 복사한다.
사용하려면 DBD-mysql을 인스톨해야한다. mysqlhotcopy는 my.cnf의 [mysqlhotcopy]그룹과 [client]그룹을 읽어들인다.

사용방법은 다음과 같다.

mysqlhotcopy [옵션]
데이터베이스명[./정규표현/] [데이터베이스명[./정규표현/] ...]
[백업위치 데이터베이스명| 백업위치 디렉토리]

데이터베이스명./정규표현/은 테이블명을 지정하고 싶은 경우 사용한다. /정규표현/에는 테이블명을 선택하기 위한 패턴을 기술한다.

마지막 인수는 백업작성 장소이다 데이터베이스명이나 디렉토리명이나 상관없다. 디렉토리명인경우는 그이름에 [/]이나 [.]가 포함되게 해야한다.

백업위치 데이터베이스명을 생략한 경우에는 [데이터베이스명_copy]이라는 데이터베이스가 백업 데이터베이스 이름이 된다.

1. test데이터베이스를 test_copy데이터베이스에 백업
root@shell# mysqlhotcopy -u root test

2. test데이터베이스를 test_back데이터베이스로 백업
root@shell# mysqlhotcopy -u root test test_back

3. test데이터베이스를 /backup/10/test디렉토리로 백업
root@shell# mysqlhotcopy -u root test /backup/10/test


2009년 8월 6일 목요일

MySQL 백업

백업의 종류는 일반적으로 다음과 같이 분류된다.

  • 물리 백업
  • 논리 백업
  • 콜드(오프라인) 백업
  • 핫(온라인) 백업
MySQL에서는 모든 방법을 지원한다.

운영체제 명령어로 복사
데이터베이스가 사용하고 있는 파일과 파일 시스템을 운영체제 명령어(cp, tar, cpio, dd, dump등)로 복사하는 방법이다. 이 경우 MySQL서버가 작업도중으로 전혀 변경작업이 없는 것을 전제로 한다.

MySQL서버를 멈춰놓고 작업하면 모순없이 복사가능하다. InnoDB경우는 데이터파일이외에도 로그파일과 my.cnf파일도 복사해 놓는다.

MySQL서버운용중에 복사하려면 FLUSH TABLES WITH READ LOCK을 거는 방법도 있다.
모든 테이블이 한번 flush되어 LOCK TABLES READ가 걸린다. lock중에는 테이블변경은 기다려진다.

REPLICATION로 백업
replication을 사용하면 slave서버에는 항상 master의 복사(백업)가 되어있다. 더더욱 백업전용 slave서버를 작성해두면 서버스를 정지시키지 않은채 풀 백업을 slave에 보존할 수 있게 된다.

MySQL slave서버는 멈추든지, 기동하는지 master에는 영향을 끼치지 않는다.
이 성징을 이용해서 slave서버를 멈추게한 다음 mysqldump나 cp등을 이용해서 전체 백업이 가능하다. 이것은 세대관리도 되게 된다.

slave서버를 멈추는데는 STOP SLAVE를 실행한다. 그 다음에 SHOW SLAVE STATUS로 현재의 바이너리 로그 위치를 확인해 두고 FLUSH TABLES WITH READ LOCK등을 실행해 풀 백업을 해두면 좋을 것이다.

slave 서버를 셧다운하는 방법도 있지만 셧다운하는 경우에는 주의가 필요하다.
왜냐하면 임시 테이블(CREATE TEMPORARY TABLE), 메모리 테이블( CREATE TABLE ... ENGINE=MEMORY) 내용은 셧다운하면 전부 없어지지 때문이다.

이런 메모리타입 테이블을 이용하는 SQL이 있으면 셧다운 한 다음 slave 를 재개했을 때 데이터가 이상해지게 된다.





2009년 8월 3일 월요일

Windows에 있어서 mysqlmanager

mysqlmanager를 SCM에 추가
c:\mysql\bin>mysqlmanager --install

SCM등록명은 MySqlManager이다. Windows서비스 표시명은 MySQL Manager로 되어있으나 정식서비스명은 어디까지나 MySqlManager이다.

5.1.12-beta, 5.1.22-rc에서 --install할 때에 서비스명을 지정할 수 없다.
또 --defaults-file=옵션도 지정할 수 없다. 서비스명은 그렇다치더라도 --defaults-file=옵션조차도 지정할 수 없는 것은 사용감이 나쁘고 곤란한 점이다.

mysqlmanager를 SCM에서 삭제
c:\mysql\bin>mysqlmanager --remove


mysqlmanager를 SCM를 이용해서 기동/정지
mysqlmanager를 SCM에 등록한 뒤라면 NET명령어를 이용해서 mysqlmanager의 기동과 정지가 가능하다.

기동예
c:\mysql\bin> NET START MySqlManager

정지예
c:\mysql\bin> NET START MySqlManager


Windows의 mysqlmanager가 읽어들이는 파일
Windows용 mysqlmanager가 읽어들이는 my.cnf파일은 다음 파일뿐이다.
이것도 다른 명령어와는 다르기때문에 혼란을 일으키는 원인이 되고 있다.

  • mysqlmanager.exe파일이 존재하는 디렉토리에 있는 my.ini파일
  • --defaults-file=옵션에서 지정된 파일
또 , mysqlmanager용 패스워드파일은 표준에서는 다음과 같다.

  • mysqlmanager.exe파일이 존재하는 디렉토리에 있는 mysqlmanager.passwd파일

mysqlmanager정지

kill로 정지
root@shell# kill `cat /usr/local/mysql/data/mysqlmanager.pid`

pid파일은 mysqlmanager --help에서 보관위치를 확인할 수 있다.

mysql.server로 정지
만약 mysql.server init스크립트를 use-manager로 동작시키고 있다면 다음처럼 정지한다.
root@shell# mysql.server stop