본문 바로가기

3.구현/Database

MySQL 일반사용자에서 실행하기

MySQL을 사용하면서 보통 root 계정으로 실행하는 경우가 많다. 혹은 root 계정이 없어서 일반 계정으로 MySQL을 실행하고 싶을 때가 있다.
이를 위한 글이다.

작성: http://ospace.tistory.com/,2011.03.24 (ospace114@empal.com)

준비물

  • MySQL binary 혹은 source
  • 사용자 계정
  • cmake (빌드할때 필요함)

MySQL은 알아서 받으세요. 사이트에서 다운로드 속도가 느려서 빠른 곳이 있다면 그 곳에서 받으시고, 없다면 시간에 여유를 두고 다운로드 받으시면 됩니다.
root 계정이 없다면 rpm을 받으면 안되겠죠.

빌드하기

바로 실행하기 전제 MySQL을 빌드해보자. 필요없다면 건너뛰어도 좋다.

  1. 적당한 장소에 소스 압축을 푼다. mysql-5.x 디렉토리가 생긴다.
  2. 해당 디렉토리에서 cmake 명령을 실행한다. 필요에 따라 아래 옵션을 추가해서 실행한다.
    shell> cmake . [options]
    -DMYSQL_UNIX_ADDR=/path_to/mysql.sock
    -DCMAKE_INSTALL_PREFIX=/path_to_install
    -DBUILD_CONFIG=mysql_release
  3. 다른 옵션 목록을 보고 싶다면 cmake . -LAH
  4. 설치한다.
    shell> cmake . install
  5. cmake 환경설정을 처음부터 다시 하고 싶다면, 캐쉬파일을 제거한다.
    shell> del CMakeCache.txt

간단하다. ^^;

일반사용자로 실행하기

기본 실행

일단 MySQL이 설치되어 있다고 가정하겠다. 먼저 path와 library을 환경설정에 추가해야 한다.

#.bashrc 적당한 위치에
export PATH=$PATH:/path_to_mysql/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path_to_mysql/lib

실행하기 전에 반드시 체크해야할 부분이 있다. 이전에 root계정으로 mysql을 설치해서 실행했었다면, 찌꺼기 파일이 남아 있을 수 있다.

특히 /etc/mysql/my.cnf 파일을 주의해야 한다. 물론 설정은 현재 자신의 계정 설정이 우선이 되지만, 그외 옵션은 /etc/mysql/my.cnf에 것을 사용한다.

본 인의 경우 skip-bdb라는 옵션이 지원하지 않는다면 mysqld가 실행되지 않았다. 나의 설정에는 없었는데 그 원인을 찾을 수가 없었다. 결국 그 에러의 원인이 /etc/mysql/my.cnf에 있었다. 그래서 해당 파일을 root관리자에게 이름을 임시로 변경해달라고 요청해여 제대로 실행할 수 있었다.

그럼 mysql을 실행해보자.

  1. 자신 계정에 mysql 환경 설정 파일을 설정하자. (~/.my.cnf에 하면 된다)
    자세한 설정은 다음 항목에서.
  2. 처음 mysql을 실행한다면 DB를 초기화해줘야 한다. 이때 ~/.my.cnf을 사용하여 수행할 것이다. mysql의 script에 필요한 명령어가 있다.
    shell> ./script/mysql_install_db --user=user_id
  3. 일반 사용자로 mysql을 실행할 경우 mysqld_safe을 사용한다. 이전에는 safe_mysqld라는 명령어로 사용했었다. 끝에 "&"를 잊지 말자.(background process)
    shell> mysqld_safe --user=user_id&
  4. 자신의 mysql 환경설정이 제대로 되어 있다면 이상없이 실행된다.

mysql 환경설정

시스템 전체에 대한 mysql 환경설정은 /etc/mysql/my.cnf에 있다. 개인 사용자인 경우는 ~/.my.cnf에 있다.
물론 mysql이 실행시점에도 사용할 환경설정 파일을 지정할 수 있지만, 그닥 좋은 방법은 아니다.
아래는 본인이 일반 사용자 계정에서 설정한 환경 변수이다. path_to나 user_id는 적당한 값으로 변경하면 된다.

#mysql에 접속할 때 사용할 정보
[client] 
port = 3300 
#mysqld에 로커로 접속할 때 사용할 socket 정보 위치. 아래 mysqld의 socket과 일치하면 된다.
socket = /path_to/mysqld.sock 

[mysqld_safe] 
pid-file = /path_to/mysqld.pid 
err-log = /path_to/mysql.log 

# The MySQL server 
[mysqld] 
user=user_id 
port = 3300 
#로컬 소켓을 위한 소켓 정보
socket = /path_to/mysqld.sock 
#mysqld 프로세스를 관리 위한 정보
pid-file = /path_to/mysqld.pid 
#로그 저장 위치
general-log = /path_to/mysqld.log 
#log-error = /path_to/mysql.log
#내부에서 사용할 메시지 언어
lc-messages-dir = /path_to/mysql/share # mysql 설치된 곳에 share 
lc-messages = en_US

Troubleshooting

mysqld.sock을 찾을 수 없는 경우

mysql 을 사용하는 client 프로그램을 작성하는 경우 해당 socket을 찾을 수 없는 경우. 해당 프로그램 실행할 경우 사용할 환경설정 파일(my.cnf)위치를 입력 받아서 mysql을 사용할 때 옵션으로 넘겨주면 되지만, 매우 번거롭다. 다른 방법으로는 환경변수나 mysql 빌드할 때 위치 정보를 고정할 수 있다. 본인은 전자을 선호한다.

환경설정을 사용하는 방법

#.bashrc의 적당한 위치에 추가
export MYSQL_UNIX_PORT=/path_to/mysqld.sock 

빌드할때 고정하는 방법

cmake . -DMYSQL_UNIX_ADDR=/path_to/mysqld.sock

Windows에서 처음 mysqld를 그냥 실행

Windows에서 실행할 때에는 리눅스와 달리 사용자에 대한 특별한 지정은 필요없습니다.
일단 설정을 먼저해야하는데 mysql 디렉토리에 가면 my-default.ini 파일을 수정해서 my.ini로 저장해야합니다. 수정한 내용은 아래와 같이 basedir, datadir, port 입니다. 각각 mysql 설치된 디렉토리, DB가 있는 디렉토리, 수신 통신 포트이죠.

basedir = d:/mysql/
datadir = d:/mysql/data/
port = 3306

반드시 my.ini 파일로 저장해야 합니다.
다음으로 해야할 작업이 초기화입니다. 먼저 datadir 설정 처럼 data 디렉토리를 생성합니다. 이미 생성해서 mysqld를 실행했었다면 data 디렉토리를 삭제하시기 바랍니다. 다시 처음 부터 초기화가 필요합니다.
초기화는 아래처럼 수행하면 됩니다.

bin\mysqld --initialize

그러면 mysqld는 열심히 초기화하고 마지막에 root 사용자에 대한 기본 패스워드를 생성합니다. 만약 보지 못했거나, 사라졌다면 data 디렉토리에 WIN-7D2FNILSNIE.err 라는 파일이 있습니다. 이 파일이 로그 파일인데 " A temporary password is generated for root@localhost: xxxxxxxx"라는 문구가 있는 문장을 찾습니다. 뒤에 "xxxxxxxx"가 패워드입니다.
이제 다시 mysqld를 실행하면 제대 실행이 됩니다. 최종적으로 root 사용자 패스워드르 변경해주면 됩니다. mysql로 root사용자로 로그인해서 패스워드를 변경해줍니다. 이때 그냥 password를 사용해서 변경합니다.

d:\mysql>bin\mysql -uroot -p
Enter password: ************
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.11

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> set password = password('newpassword');
Query OK, 0 rows affected, 1 warning (0.12 sec)

만약 Windows의 서비스로 등록해서 사용하고 싶다면, "mysqld --install" 명령어를 관리자 권한으로 수행하면 서비스에 추가됩니다. 그리고, 서비스를 시작하면 mysqld가 알아서 실행합니다.

MySQL 사용 예제 코드

#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>

#define DMESG(m) {\ 
        fprintf(stderr, (m)); \ 
        fprintf(stderr, ", %s\n", mysql_error(conn)); \ 
        exit(1); \ 
                } 

int main(int argc, char** argv) 
{ 
        MYSQL *conn = NULL; 
        MYSQL_RES *res = NULL; 
        MYSQL_ROW row; 

        char *server = "localhost"; 
        char *user = "root"; 
        char *password = "manager1"; 
        char *database = "myspace"; 

        conn = mysql_init(NULL); 

          if( !mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { 
                DMESG("fail connect2"); 
        } 

        mysql_query(conn, "CREATE TABLE ospace( id INTEGER NOT NULL PRIMARY KEY,  name VARCHAR(254), birth TIMESTAMP);"); 
        mysql_query(conn, "INSERT INTO ospace (id, name, birth) VALUES(1, 'ospace', DATE('now'));"); 
        mysql_query(conn, "SELECT * FROM ospace"); 
        res = mysql_store_result(conn); 

        while((row=mysql_fetch_row(res))!=NULL) { 
                fprintf(stdout, "%s, %s, %s\n", row[0], row[1], row[2]); 
        } 
        mysql_free_result(res); 
        mysql_query(conn, "DROP TABLE ospace"); 
        return 0; 
} 

Prepared statement을 사용하는 경우

MYSQL *conn;
MYSQL_STMT *stmt;
MYSQL_BIND binds[1];
char *query_template = "INSERT INTO datas (created_date, val)  VALUES (TIME('now'), ?);"

// connect mysql database
// ...

if( NULL == (stmt = mysql_stmt_init(conn))  ) {
    DMESG(conn, "fail stmt");
}

if( 0 != mysql_stmt_prepare(stmt, query_template, strlen(query_template)) ) {
    DMESG(conn, "fail prepare");
}

for(i=0; i < 10; ++i) {
    memset(binds, sizeof(binds), 0);
    binds[0].buffer_type = MYSQL_TYPE_SHORT;
    binds[0].buffer = (char*) &i;
    binds[0].is_null = 0;
    binds[0].length = 0;

    if( 0 != mysql_stmt_bind_param(stmt, binds) ) {
        DMESG(conn, "fail bind");
    }

    if( 0 != mysql_stmt_execute(stmt) ) {
        DMESG(conn, "fail inert");
    }
}

if(0!=mysql_stmt_close(stmt)) {
    DMESG(conn, "fail stmt2");
}

결론

앞의 일반 사용자게 MySQL을 뛰우는 경우는 보안 문제인 경우가 대부분일 것이다. 물론 root로 사용해도 되지만...
필자는 테스트용으로 임시로 사용하기 위해서 설치했다. 그래서 root 계정이 없기 때문에 기존에 있는 자료에서 /var이나 /etc에 대한 수정을 할 수 없었다.
즉, 불가능한 내용이 많았다. 나름대로 실행 착오를 거치면서 어느정도 정리가 되었다. 물론 이 내용만으로 이해안되는 분도 있을 것이다.
세 세한 내용까지 전부 다루기에 시간도 부족하고, 그다지 필요성을 느끼지 않아서 건너뛴 부분도 많다. 그래서 혹시, 궁금하거나 잘 안된다면 저에게 메일(ospace114@naver.com)을 주시면 가급적 빠른 시간내에 답변을 드리겠습니다. 좀 여유를 두고 질문을 해주시기 바랍니다. ^^;
여담으로..
MySQL 에서 메모리 DB 사용에 주의가 필요하다. varchar가 가변적으로 할당(variable-length column)이 안되고 최대 값으로 할당된다. 즉 varchar(1000) 이면 사용하지 않더라도도 1000 문자가 할당되어 사용된다. 물론 성능에 대해 일반 DB보다 빠르기 때문에 적당히 잘 활용하면 되리라 본다.
이에 대한 패치가 제공되고 있지만, 정식 버전은 아니다. 그리고 버전이 5.0대라서 최근 버전에 이상없이 적용하기 어려울 듯 하다. (

http://code.google.com/p/mysql-heap-dynamic-rows/ )

그리고 메모리 사용량이 늘어나기 때문에 heap 설정을 변경해줘야 한다. my.cnf에서 mysqld항목에 아래 설정을 하면 된다.
max_heap_table_size = 256M #필요하면 알맞게 수정하면 된다.
메모리 DB을 사용하면서 주의할 것은 BLOB와 TEXT column을 지원하지 않는다. 그렇기에 LONG도 안된다.

참조

http://mysql.com/
http://dev.mysql.com/doc/refman/5.5/en/source-configuration-options.html
http://dev.mysql.com/doc/refman/5.5/en/problems-with-mysql-sock.html

반응형

'3.구현 > Database' 카테고리의 다른 글

MS-SQL DB 제어  (0) 2012.08.02
Oracle에서 MS-SQL로 포팅  (0) 2007.12.11