1. 사용자 추가 [root][ use mysql ] > GRANT ALL ON <DATABASE 명 혹은 테이블명> TO <사용자명>@<호스트명> IDENTIFIED BY '비밀번호'; 2. 사용자 로긴이 안될수 있다. 비밀번호의 해슁때문인데 이땐 암호를 한번더 변경시켜준다. > update user set password=password('<password>') where user='<user>'; 3. 데이터베이스 권한 설정 > insert into db values ('localhost', '<DATABASE 명>', '<사용자명>', 'y', 'y' ...); 4. 시스템에 적용 > flush privileges;
ALTER [IGNORE] TABLE tbl_name
alter_specification [, alter_specification] ...
alter_specification:
ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
| ADD [COLUMN] (column_definition,...)
| ADD INDEX [index_name] [index_type] (index_col_name,...)
| ADD [CONSTRAINT [symbol]]
PRIMARY KEY [index_type] (index_col_name,...)
| ADD [CONSTRAINT [symbol]]
UNIQUE [index_name] [index_type] (index_col_name,...)
| ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...)
| ADD [CONSTRAINT [symbol]]
FOREIGN KEY [index_name] (index_col_name,...)
[reference_definition]
| ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
| CHANGE [COLUMN] old_col_name column_definition
[FIRST|AFTER col_name]
| MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
| DROP [COLUMN] col_name
| DROP PRIMARY KEY
| DROP INDEX index_name
| DROP FOREIGN KEY fk_symbol
| DISABLE KEYS
| ENABLE KEYS
| RENAME [TO] new_tbl_name
| ORDER BY col_name
| CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
| [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
| DISCARD TABLESPACE
| IMPORT TABLESPACE
| table_options
ALTER TABLE allows you to change the structure of an existing table. For example, you can add or delete columns, create or destroy indexes, change the type of existing columns, or rename columns or the table itself. You can also change the comment for the table and type of the table.
The syntax for many of the allowable alterations is similar to clauses of the CREATE TABLE statement. See section 14.2.5 CREATE TABLE Syntax.
If you use ALTER TABLE to change a column specification but DESCRIBE tbl_name indicates that your column was not changed, it is possible that MySQL ignored your modification for one of the reasons described in section 14.2.5.1 Silent Column Specification Changes. For example, if you try to change a VARCHAR column to CHAR, MySQL will still use VARCHAR if the table contains other variable-length columns.
ALTER TABLE works by making a temporary copy of the original table. The alteration is performed on the copy, then the original table is deleted and the new one is renamed. While ALTER TABLE is executing, the original table is readable by other clients. Updates and writes to the table are stalled until the new table is ready, then are automatically redirected to the new table without any failed updates.
Note that if you use any other option to ALTER TABLE than RENAME, MySQL always creates a temporary table, even if the data wouldn't strictly need to be copied (such as when you change the name of a column). We plan to fix this in the future, but because ALTER TABLE is not a statement that is normally used frequently, this isn't high on our TODO list. For MyISAM tables, you can speed up the index re-creation operation (which is the slowest part of the alteration process) by setting the myisam_sort_buffer_size system variable to a high value.
To use ALTER TABLE, you need ALTER, INSERT, and CREATE privileges for the table.
IGNORE is a MySQL extension to standard SQL. It controls how ALTER TABLE works if there are duplicates on unique keys in the new table. If IGNORE isn't specified, the copy is aborted and rolled back if duplicate-key errors occur. If IGNORE is specified, then for rows with duplicates on a unique key, only the first row is used. The others are deleted.
You can issue multiple ADD, ALTER, DROP, and CHANGE clauses in a single ALTER TABLE statement. This is a MySQL extension to standard SQL, which allows only one of each clause per ALTER TABLE statement. For example, to drop multiple columns in a single statement:
mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
CHANGE col_name, DROP col_name, and DROP INDEX are MySQL extensions to standard SQL.
MODIFY is an Oracle extension to ALTER TABLE.
The word COLUMN is purely optional and can be omitted.
If you use ALTER TABLE tbl_name RENAME TO new_tbl_name without any other options, MySQL simply renames any files that correspond to the table tbl_name. There is no need to create a temporary table. (You can also use the RENAME TABLE statement to rename tables. See section 14.2.9 RENAME TABLE Syntax.)
column_definition clauses use the same syntax for ADD and CHANGE as for CREATE TABLE. Note that this syntax includes the column name, not just the column type. See section 14.2.5 CREATE TABLE Syntax.
You can rename a column using a CHANGE old_col_name column_definition clause. To do so, specify the old and new column names and the type that the column currently has. For example, to rename an INTEGER column from a to b, you can do this:
mysql> ALTER TABLE t1 CHANGE a b INTEGER;
If you want to change a column's type but not the name, CHANGE syntax still requires an old and new column name, even if they are the same. For example:
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
However, as of MySQL 3.22.16a, you can also use MODIFY to change a column's type without renaming it:
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
If you use CHANGE or MODIFY to shorten a column for which an index exists on part of the column (for example, if you have an index on the first 10 characters of a VARCHAR column), you cannot make the column shorter than the number of characters that are indexed.
When you change a column type using CHANGE or MODIFY, MySQL tries to convert existing column values to the new type as well as possible.
In MySQL 3.22 or later, you can use FIRST or AFTER col_name to add a column at a specific position within a table row. The default is to add the column last. From MySQL 4.0.1 on, you can also use FIRST and AFTER in CHANGE or MODIFY operations.
ALTER COLUMN specifies a new default value for a column or removes the old default value. If the old default is removed and the column can be NULL, the new default is NULL. If the column cannot be NULL, MySQL assigns a default value, as described in section 14.2.5 CREATE TABLE Syntax.
DROP INDEX removes an index. This is a MySQL extension to standard SQL. See section 14.2.7 DROP INDEX Syntax.
If columns are dropped from a table, the columns are also removed from any index of which they are a part. If all columns that make up an index are dropped, the index is dropped as well.
If a table contains only one column, the column cannot be dropped. If what you intend is to remove the table, use DROP TABLE instead.
DROP PRIMARY KEY drops the primary index. (Prior to MySQL 4.1.2, if no primary index exists, DROP PRIMARY KEY drops the first UNIQUE index in the table. MySQL marks the first UNIQUE key as the PRIMARY KEY if no PRIMARY KEY was specified explicitly.) If you add a UNIQUE INDEX or PRIMARY KEY to a table, it is stored before any non-unique index so that MySQL can detect duplicate keys as early as possible.
ORDER BY allows you to create the new table with the rows in a specific order. Note that the table will not remain in this order after inserts and deletes. This option is mainly useful when you know that you are mostly going to query the rows in a certain order; by using this option after big changes to the table, you might be able to get higher performance. In some cases, it might make sorting easier for MySQL if the table is in order by the column that you want to order it by later.
If you use ALTER TABLE on a MyISAM table, all non-unique indexes are created in a separate batch (as for REPAIR TABLE). This should make ALTER TABLE much faster when you have many indexes. As of MySQL 4.0, this feature can be activated explicitly. ALTER TABLE ... DISABLE KEYS tells MySQL to stop updating non-unique indexes for a MyISAM table. ALTER TABLE ... ENABLE KEYS then should be used to re-create missing indexes. MySQL does this with a special algorithm that is much faster than inserting keys one by one, so disabling keys before performing bulk insert operations should give a considerable speedup. Using ALTER TABLE ... DISABLE KEYS will require the INDEX privilege in addition to the privileges mentioned earlier.
The FOREIGN KEY and REFERENCES clauses are supported by the InnoDB storage engine, which implements ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...). See section 16.7.4 FOREIGN KEY Constraints. For other storage engines, the clauses are parsed but ignored. The CHECK clause is parsed but ignored by all storage engines. See section 14.2.5 CREATE TABLE Syntax. The reason for accepting but ignoring syntax clauses is for compatibility, to make it easier to port code from other SQL servers, and to run applications that create tables with references. See section 1.8.5 MySQL Differences from Standard SQL.
Starting from MySQL 4.0.13, InnoDB supports the use of ALTER TABLE to drop foreign keys:
ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;
ALTER TABLE ignores the DATA DIRECTORY and INDEX DIRECTORY table options.
From MySQL 4.1.2 on, if you want to change all character columns (CHAR, VARCHAR, TEXT) to a new character set, use a statement like this:
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
This is useful, for example, after upgrading from MySQL 4.0.x to 4.1.x. See section 11.10 Upgrading Character Sets from MySQL 4.0. Warning: The preceding operation will convert column values between the character sets. This is not what you want if you have a column in one character set (like latin1) but the stored values actually use some other, incompatible character set (like utf8). In this case, you have to do the following for each such column:
ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
The reason this works is that there is no conversion when you convert to or from BLOB columns. To change only the default character set for a table, use this statement:
ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;
The word DEFAULT is optional. The default character set is the character set that is used if you don't specify the character set for a new column you add to a table (for example, with ALTER TABLE ... ADD column). Warning: From MySQL 4.1.2 and up, ALTER TABLE ... DEFAULT CHARACTER SET and ALTER TABLE ... CHARACTER SET are equivalent and change only the default table character set. In MySQL 4.1 releases before 4.1.2, ALTER TABLE ... DEFAULT CHARACTER SET changes the default character set, but ALTER TABLE ... CHARACTER SET (without DEFAULT) changes the default character set and also converts all columns to the new character set.
For an InnoDB table that is created with its own tablespace in an `.ibd' file, that file can be discarded and imported. To discard the `.ibd' file, use this statement:
ALTER TABLE tbl_name DISCARD TABLESPACE;
This deletes the current `.ibd' file, so be sure that you have a backup first. Attempting to access the table while the tablespace file is discarded results in an error. To import the backup `.ibd' file back into the table, copy it into the database directory, then issue this statement:
With the mysql_info() C API function, you can find out how many records were copied, and (when IGNORE is used) how many records were deleted due to duplication of unique key values. See section 21.2.3.30 mysql_info().
Here are some examples that show uses of ALTER TABLE. Begin with a table t1 that is created as shown here:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
To rename the table from t1 to t2:
mysql> ALTER TABLE t1 RENAME t2;
To change column a from INTEGER to TINYINT NOT NULL (leaving the name the same), and to change column b from CHAR(10) to CHAR(20) as well as renaming it from b to c:
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
To add a new TIMESTAMP column named d:
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
To add indexes on column d and on column a:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);
To remove column c:
mysql> ALTER TABLE t2 DROP COLUMN c;
To add a new AUTO_INCREMENT integer column named c:
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
-> ADD PRIMARY KEY (c);
Note that we indexed c (as a PRIMARY KEY), because AUTO_INCREMENT columns must be indexed, and also that we declare c as NOT NULL, because primary key columns cannot be NULL.
When you add an AUTO_INCREMENT column, column values are filled in with sequence numbers for you automatically. For MyISAM tables, you can set the first sequence number by executing SET INSERT_ID=value before ALTER TABLE or by using the AUTO_INCREMENT=value table option. See section 14.5.3.1 SET Syntax.
With MyISAM tables, if you don't change the AUTO_INCREMENT column, the sequence number will not be affected. If you drop an AUTO_INCREMENT column and then add another AUTO_INCREMENT column, the numbers are resequenced beginning with 1.
IF you want to change a SET or ENUM column you may not want to use the ALTER TABLE ... MODIFY syntax. It tries to keep the actual string values and not the integer representation of the values, even though they are stored as integers. For example, if you just want to make a change in spelling of the values in your enum column or your set column, consider doing it like this: ALTER TABLE table ADD new_column ...; UPDATE table SET new_column = old_column + 0; ALTER TABLE table DROP old_column;
You can use Alter Table to optimise a table without locking out selects (only writes), by altering a column to be the same as it's current definition. This is better than using repair table which obtains a read/write lock.
E.g. mysql> describe Temp_Table;
+-------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+-------+ | ID | int(10) unsigned | YES | | NULL | | +-------+------------------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> alter table Temp_Table change column ID ID int unsigned;
This will cause mysql to re-create the table and thus remove any deleted space.
This is useful for 24/7 databases where you don't want to completely lock a table.
Posted by Radhakrishnan Ayyappanaicker on April 13 2004 2:41am
while adding primary key constraint on null allowable integer column, mysql assigns default value 0 iff one NULL value exists on that column else alter table will fail with error "Duplicate entry '0' for key 1"
숫자형은 가장 기본적인 자료형으로서 말 그래도 숫자들을 저장하는 자료형입다. 숫자형의 기본적인 자료형은 정수형과 소수형 두가지로 나눌수있다. 정수형의 자료는 SIGNED 와 UNSIGNED 로 나눌수있다 SINGED는 부호를 가질수있는 수를 나타내고, UNSINGED는 부호가 없는 수를 나타낸다.
mysql> select * from zzz; +-----+------------+ | num | count | +-----+------------+ | 55 | 0000000055 | +-----+------------+ 1 row in set (0.00 sec)
ZEROFILL 로 정의된 필드에 값이 어떻게 입력되는지 확인하면 이 정의의 필요성을 알수 있을거라 생각됩니다.
2. 문자형 데이터
문자형은 의미상으론 문자열을 저장하는 자료형이지만 문자열 외에도 이미지,동여상등의 바이너리 파일을 보관할수이다.
* 종류 및 설명
------------------------------------------------------------------------------------ [자료형] [설명] ------------------------------------------------------------------------------------ CHAR(M) M만큼의 문자를 저장할수있다,최대 255 문자 ------------------------------------------------------------------------------------ VARCHAR(M) CHAR 와 같이 M 만큼의 문자를 저장할수있다. 최대 255 문자 ------------------------------------------------------------------------------------ TINYTEXT 255개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ TINYBLOB 255개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ TEXT 65535 개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ BLOB 65535 개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ MEDIUMTEXT 16777215 개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ MEDIUMBLOB 16777215 개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ LONGBLOB 4294967295 (4G) 개의 문자를 저장할수있다. ------------------------------------------------------------------------------------ LONGTEXT 4294967295 (4G) 개의 문자를 저장할수있다 ------------------------------------------------------------------------------------ ENUM('value1','value2'...) 문자를 숫자형으로 보관할때 사용 ------------------------------------------------------------------------------------ SET('value1','value2'....) 문자를 숫자형으로 보관할때 사용 ------------------------------------------------------------------------------------
* CHAR 와 VARCHAR 의 장단점
둘다 최대 255 문자를 가진다는 점에서는 동일하다. 만약 CHAR(10), VARCHAR(10) 이렇게 테이블을 생성하였다면 둘다 최대 10 BYTE 를 저 장할수있다.
만약 둘다 5 개의 문자를 저장한다면 어떻게 될까.
CHAR - 비록 5 개의 문자를 저장하지만 10 BYTE 를 다 사용한다. VARCHAR - 5 BYTE만 사용한다.
VARCHAR 이 훨씬 저장장치를 효율적으로 사용할수있다. 그러나 CHAR 이 검색에서는 훨씬 좋은 효과를 발휘한다.
* 검색시 대소문자 구별하기
일반적으로 CHAR / VARCHAR는 검색시 대,소문자를 구별하지 않는다. SOMA 를 찾으나 soma 를 찾으나 둘다 출력이된다. 이렇게 검색시 대소문자를 별하기 위해서는 테이블 생성시 이를 정의해야한다.
BINARY 속성이 그것이다.
mysql> create table ppp ( -> -> num int(10) not null auto_increment, -> name varchar(50) BINARY, -> primary key(num) -> ); Query OK, 0 rows affected (0.00 sec)
mysql> desc ppp; +-------+--------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------------+------+-----+---------+----------------+ | num | int(10) | | PRI | NULL | auto_increment | | name | varchar(50) binary | YES | | NULL | | +-------+--------------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
* TEXT 와 BLOB 의 차이
TEXT 는 아주긴 CHAR 라고 생각하면 된다. TEXT 는 문자열을 저장할때 사용.
BLOB 는 아주긴 BINARY CHAR 라고 생각하면 된다. BLOB 는 동영상이나 이미지를 저장할때 사용.
* ENUM / SET 사용하기
ENUM 과 SET 은 MYSQL 내에서 문자열을 숫자로 저장할때 사용된다.
mysql> create table qqq ( -> -> num int(10) not null auto_increment, -> sex ENUM('남자','여자'), -> primary key(num) -> ); Query OK, 0 rows affected (0.00 sec)
mysql> desc qqq; +-------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------------+------+-----+---------+----------------+ | num | int(10) | | PRI | NULL | auto_increment | | sex | enum('남자','여자') | YES | | NULL | | +-------+---------------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
mysql> select * from qqq; +-----+------+ | num | sex | +-----+------+ | 1 | 남자 | | 2 | 여자 | | 3 | 남자 | +-----+------+ 3 rows in set (0.00 sec)
위에서 처럼 ENUM 으로 정의된 필드는 SELECT 에서는 문자열로 출력되지만 실질적으로 저장장치에는 숫자로 저장된다..
* ENUM 의 장점
1. 공간을 절약할수있다. 2. 검색속도를 향상 시킨다.
3. 날짜와 시간 데이터
* 종류 및 설명 ------------------------------------------------------------------------------------ [자료형] [설명] ------------------------------------------------------------------------------------ DATETIME 날짜와 시간을 저장,YYYY-MM-DD HH:MM:SS 형식으로 저장 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 까지 저장 ------------------------------------------------------------------------------------ DATE DATETIME 형 자료로서 날짜 부분만 저장 1000-01-01 ~ 9999-12-31 까지 저장 ------------------------------------------------------------------------------------ TIMESTAMP(M) M 에따라 다양한 형태의 날짜를 저장할수 있다. ------------------------------------------------------------------------------------ TIME DATETIME 에서 TIME 부분에 해당하는 시간 형식의 자료를 저장 ------------------------------------------------------------------------------------ YEAR 연도만을 저장하는 자료형 ------------------------------------------------------------------------------------
결과는 어떨지.. 천만건의 데이터에 인덱스를 설정했는데... 근데 그렇다고 데이터가 많이 흩어져 있던것도 아니고...
디비 고수들은 무슨 명령어를 써서 데이터 상태보고 인덱스 건다는데.. 난.. 일단 해보고 속도 빠르면 장땡!
... ... 했더니 속도 겁나 빨라졌다. @.@~! 147초가 걸리던 작업이 0.016초 로 줄었네..
1. 인덱스 걸기 ALTER TABLE test ADD INDEX index_id (id)
2. 인덱스 다시 정렬하기 데이터가 많이 쌓이면 인덱스가 항상 최상의 상태로 정렬되어있지 않다. 그땐 아래 명령어를 통해서 다시 정렬을 해준다면 체감상(?) 성능이 샹항됨을 느낄수 있다고 한다. (내말이 아님) mysql/var/디비명 에 들어가서 myisamchk -R1 *
3. 깨진 인덱스 복구하기
// mysql 프로세스 종료
# mysql.server stop ( # Killall mysqld )
// 디비 데이터가 있는 폴더로 이동 # cd /usr/local/mysql/var
// 모든 디비 테이블의 인덱스를 복구 # myisamchk -r *.MYI
// mysql 백그라운드 실행 (Linux, Unix) /user/local/mysql/bin/safe_mysq &
[다음은 내가 한장 JSP 에 빠져있을때 웹상으로 항상 동경하던 kkaok 님의 글이다]
INDEX 사용하기
by kkaok 2003-06-24
인덱스의 활용
만약 우리가 집을 짓는데 제일 먼저 해야 할 일이 뭘까? 그것은 아마도 설계일 것이다. 기초가 되는 기본 설계를 잘 해야만이 그 후 작업이 원활하고 최적화가 되는 것이다. 프로그래머는 java, servlet, jsp뿐 아니라 최소한의 데이터베이스에 대해서도 알아야 한다. 게시판, 카운터, 일정관리 등을 만드는데 DB 설계를 다른 사람이 해줄 수도 있겠지만 대부분이 개발자가 설계하고 만들기 때문이다. 여기서는 DB에 대해 심도 깊은 공부를 할 수는 없지만 최소한의 지식에 대해 배우기로 한다.
인덱스란 무엇인가?
SQL서버에서 테이블을 만들고 데이터를 추가, 수정, 삭제 할 때 데이터의 레코드는 내부적으로 아무런 순서 없이 저장된다. 이때 데이터 저장영역을 Heap이라고 한다. Heap에서는 인덱스가 없는 테이블의 데이터를 찾을 때 무조건 전체 데이터 페이지의 처음 레코드부터 끝 페이지의 마지막 레코드까지 다 읽어서 검색조건과 비교하게 된다. 이런 식의 데이터 검색방법을 테이블 스캔(table scan) 또는 풀 스캔(full scan)이라고 한다. 이럴 경우 양이 많은 테이블에서 일부분의 데이터만 불러 올 때 풀 스캔을 하면 처리 성능이 떨어진다. 즉 인덱스는 데이터를 select 할 때 빨리 찾기 위해 사용된다.
인덱스 생성 시 고려할 점
인덱스를 생성 시에는 where 절과 join, order by 등과 관련된 칼럼중 사용 빈도가 높고 키 값의 선별도가 좋은 칼럼에 사용해야 한다. 반대로 사용 빈도가 낮고 칼럼의 선별도가 나쁜, 예를 들어 한 칼럼의 값이 true/false, 성별(M/F) 등에는 인덱스를 사용하지 않는 것이 좋다 또 테이블이 작거나 자주 갱신 될 때도 사용하지 않는 것이 좋다.
인덱스의 생성
인덱스에는 크게 clustered와 nonclustered 인덱스로 나눌 수 있다. clustered 인덱스는 물리적 정렬로 DB에 데이터를 입력 시 이것을 기준으로 입력이 된다. 따라서 한 테이블에 오직 하나만 존재 할 수 있으며 table을 열었을 때 order by를 사용하지 않아도 데이터가 clustered 인덱스에 따라 정렬이 되어 있는 것을 확인 할 수 있다. 물리적으로 정렬이 되어 있는 만큼 가장 빠른 처리를 한다. nonclustered 인덱스는 clustered 인덱스와는 달리 중복된 값을 가지면 한 테이블에 여러 개를 생성 할 수 있다. 이 외에 unique에 대해 알아보겠다. unique는 말 그대로 중복을 허용하지 않는 값을 보호 할 때 사용한다. 예를 들어 회원 관리 프로그램에서 아이디가 중복되는 것을 막고자 한다면 이 옵션을 사용하면 된다. 우리가 자주 사용하는 primary key의 경우에는 clustered와 unique 특성을 갖게 하는 제약키이다.
create clustered index ix_kkaok on kkaok(seq)
width DROP_EXISTING, FILLFACTOR = 80
kkaok 테이블에서 seq 칼럼에 대해 ix_kkaok라는 클러스터드 인덱스를 생성하라는 명령문이다.
DROP_EXISTING 옵션은 기존에 같은 이름의 인덱스가 존재한다면 삭제하고 생성하라는 의미이며 Fillfactor 값은 명시하지 않으면 기본적으로 100% 페이지에 채워 넣으라는 뜻이다. 지금은 80% 채워 넣고 20% 여유공간을 가지라는 의미이다.
결합 인덱스의 생성 예제
create index ix_kkaok2 on kkaok(seq,re_step)
seq와 re_step 두 개의 칼럼에 인덱스를 생성하였다. 각각의 칼럼에 대해 내림차순 정렬과 오름차순 정렬 옵션을 줄 수 있지만 mssql 7.0에서는 내림차순 정렬을 지원하지 않는다.
인덱스 보기
exec sp_helpindex '테이블이름'
인덱스 제거
drop index 'table.index'[,...n]
인덱스의 삭제 예제
drop index kkaok.ix_kkaok
제약키의 변경
primary key는 인덱스가 아니고 제약키이다. 따라서 인덱스를 삭제하는 방법으로 삭제 할 수는 없다. 제약키는 다음의 방법으로 삭제 또는 변경 할 수 있다.
제약키의 삭제
alter table kkaok drop constraint PK_kkaok
제약키의 추가변경
alter table kkaok add constraint PK_kkaok primary key(seq)
② oracle
인덱스생성 문법
CREATE [BITMAP | UNIQUE]
INDEX index_name ON table (column[, column]...) ;
인덱스의 생성 예제
create unique index ix_kkaok_indx on kkaok(seq);
kkaok 테이블에서 unique 한 값으로 seq 칼럼에 대해 ix_kkaok_indx라는 인덱스를 생성하라는 명령문이다.
결합 인덱스의 생성 예제
create index ix_kkaok_indx2 on kkaok(seq,re_step);
seq 와 re_step 두 개의 칼럼에 인덱스를 생성한다. 각각의 칼럼에 대해 내림차순과 오름차순 정렬 옵션을 줄 수 있으나 hint를 사용시 정렬이 안되는 경우가 있어서 정렬과 관련된 것은 hint에서 처리를 하면 된다.
인덱스 보기
select index_name, index_type from user_indexes;
인덱스 제거
drop index 인덱명
인덱스의 삭제 예제
drop index ix_kkaok_indx;
제약키의 삭제 예제
alter table kkaok drop constraint kkaok_pk_re_step;
제약키의 추가 예제
alter table kkaok add constraint kkaok_pk_indx2 unique(seq);
③ mysql
인덱스생성 문법
BLOB과 TEXT 타입을 제외한 모든 mysql의 칼럼 타입은 인덱스로 사용될 수 있다. 한 테이블에는 16개의 인덱스를 생성할 수 있으며 최대 인덱스의 길이는 256바이트이다. 또한 인덱스에 사용되는 칼럼은 NOT NULL이어야 한다. 인덱스의 생성은 테이블을 생성할 때 다음처럼 생성하면 된다.
KEY [인덱스명] (col1(length),col2(length),...)
인덱스의 생성 예제
CREATE TABLE test (
id CHAR(20) NOT NULL,
name CHAR(200) NOT NULL,
PRIMARY KEY (id),KEY index_name (name(200)));
MySQL Database의 경우 Oracle 이나 MS SQL Server에 비해서 대용량의 자료를 처리하는 경우가 적기에 튜닝에 필요성이 적은 것 같습니다. 그러나 웹이라는 환경은 많은 사용자가 동시에 접속을 할 수 있기에 항상 모니터링과 최적화는 기본이라고 생각합니다.
본 강좌에서는 기본적인 모니터링 방법과 Connection과 Memory 부분에 대한 튜닝 방법을 소개하도록 하겠습니다.
가. 모니터링 및 초기화 명령어
show status - MySQL 데이타베이스의 현재 상황
show Processlist - MySQL 프로세스 목록
show variables - 설정 가능한 모든 변수 목록
flush logs - MySQL의 로그파일 초기화
flush status - MySQL 상태정보 초기화
flush thread - 쓰레드 캐시에 저장된 쓰레드 초기화
flush tables - MySQL에 캐싱된 테이블 초기화
flush privileges - 권한정보 재 설정
나. Connection 튜닝
1. status
Aborted_clients - 클라이언트 프로그램이 비 정상적으로 종료된 수
Aborted_connects - MySQL 서버에 접속이 실패된 수
Max_used_connections - 최대로 동시에 접속한 수
Threads_cached - Thread Cache의 Thread 수
Threads_connected - 현재 연결된 Thread 수
Threads_created - 접속을 위해 생성된 Thread 수
Threads_running - Sleeping 되어 있지 않은 Thread 수
2. system variables
wait_timeout - 종료전까지 요청이 없이 기다리는 시간 ( TCP/IP 연결, Shell 상의 접속이 아닌 경우 )
thread_cache_size - thread 재 사용을 위한 Thread Cache 수로써, Cache 에 있는 Thread 수보다 접속이 많으면 새롭게 Thread를 생성한다.
max_connections - 최대 동시 접속 가능 수
그외에 status 또는 system variables 값은 참고의 Mysql 메뉴얼을 참조해 주십시요.
mysql> show variables like '%max_connection%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 100 | +-----------------+-------+ 1 row in set (0.00 sec)
mysql> show status like '%connect%'; +----------------------+---------+ | Variable_name | Value | +----------------------+---------+ | Aborted_connects | 3782 | | Connections | 2961108 | | Max_used_connections | 90 | | Threads_connected | 1 | +----------------------+---------+ 4 rows in set (0.01 sec)
mysql> show status like '%clients%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | Aborted_clients | 2160 | +-----------------+-------+ 1 row in set (0.00 sec)
mysql> show status like '%thread%'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | Delayed_insert_threads | 0 | | Slow_launch_threads | 0 | | Threads_cached | 7 | | Threads_connected | 1 | | Threads_created | 1364 | | Threads_running | 1 | +------------------------+-------+ 6 rows in set (0.00 sec)
위의 경우는 Cache Miss Rate(%) = 0.05%, Connection Miss Rate(%) = 0.12%, Connection Usage(%) = 1%
3. 튜닝
Connection Usage(%)가 100% 라면 max_connections 수를 증가시켜 주십시요. Connection 수가 부족할 경우 Too Many Connection Error 가 발생합니다.
DB 서버의 접속이 많은 경우는 wait_timeout 을 최대한 적게 (10~20 정도를 추천) 설정하여 불필요한 연결을 빨리 정리하는 것이 좋습니다. 그러나 Connection Miss Rate(%) 가 1% 이상이 된다면 wait_timeout 을 좀 더 길게 잡는 것이 좋습니다.
Cache Miss Rate(%) 가 높다면 thread_cache_size를 기본값인 8 보다 높게 설정하는 것이 좋습니다. 일반적으로 threads_connected 가 Peak-time 시 보다 약간 낮은 수치로 설정하는 것이 좋습니다.
MySQL 서버는 외부로 부터 접속 요청을 받을 경우 인증을 위해 IP 주소를 호스트네임으로 바꾸는 과정을 수행하여 접속시에 불필요한 부하가 발생하게 됩니다. skip-name-resolve를 설정하시고 접속시에 IP 기반으로 접속을 하게 되면 hostname lookup 과정을 생략하게 되어 좀 더 빠르게 접속을 하실 수 있습니다.
다. Memory 튜닝
1. status
key_block_unused - Key Cache에서 사용되고 있지 않은 Block 수
key_reads - Key Block 읽기 요청시 Disk을 읽은 수
key_read_requests - Key Block 읽기 요청수
2. system variables
key_buffer_size - 인덱스를 메모리에 저장하는 버퍼의 크기
table_cache - 전체 쓰레드가 사용할 오픈 가능한 테이블 수
myisam_sort_buffer_size - 테이블 repair,Alter table,load data에 사용되는 버퍼 메모리 크기
join_buffer_size - 조인을 위한 메모리 버퍼 크기
record_buffer - 순차적인 검색을 위해 사용되는 메모리 버퍼 크기
record_rnd_buffer - order by 절을 사용할 경우 디스크 사용을 피하기 위하여 사용하는 메모리 버퍼 크기
sort_buffer - order by 와 group by에 사용되는 메모리 버퍼 크기
tmp_table_size - group by 시 디스크를 사용하지 않고 임시 테이블을 만들기 위해 사용되는 메모리 크기
key_cache_block_size - block 의 크기(bytes, 기본값 1024)
* ^Key_Reads = Current Key_Rreads - Previous Key_Reads
3. 튜닝
key_buffer_size는 총 메모리 크기의 25% 정도의 크기로 설정하는 것이 좋습니다.
Key_reads/Key_read_requests Rate(%)은 일반적으로 1%보다 적습니다. 1% 보다 높다면 Key Cache가 아닌 디스크를 읽은 경우가 많다고 판단할 수 있습니다. 또한 Key_reads/Key_reads_requests Relative Rate(%) 값이 지속적으로 90% 이상일 경우는 key_buffer_size가 효율적으로 설정되어 있다고 생각하시면 됩니다. 하지만 데이터베이스가 엄청나게 크거나 여러 데이터를 골고루 많이 읽는 데이터베이스라면 아무리 많은 양의 키 캐시를 설정해도 90% 이상의 적중률을 얻을 수는 없습니다.
라. 적용
system variables은 my.cnf 또는 my.ini 파일을 수정 후 MySQL Server 를 재시작 해 주십시요.
[www@smson www]$ vi /etc/my.cnf
# The MySQL server [mysqld] port = 3306 socket = /tmp/mysql.sock skip-locking skip-name-resolve key_buffer = 256M max_allowed_packet = 1M table_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M thread_cache = 8 query_cache_size= 16M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 wait_timeout = 120
Unix 시스템에서 라이브러리를 공부합니다. 어쩌다 윈도우 시스템쪽 프로그래밍을 하게 되었지만 원래는 유닉스나 리눅스쪽이 더 친했었죠. 그 이유는 명확하기 때문입니다. M$ 의 윈도우 프로그램은 너무 숨기는것도 많고 명확하지 않은게 많으니... 아무튼 라이브러리에 대해 잘 설명해둔 문서를 긁어왔습니다.
이 문서는 library 의 사용방법에 대한 내용을 담고 있다. 왜 라이브러리가 필요한지, 라이브러리는 어떤 종류가 있으며, 어떻게 작성할수 있는지, 그리고 어떻게 사용하는지에 대해서 얘기하도록 할것이다. 그리고 중간중간에 이해를 돕기 위한 실제 코딩역시 들어갈 것이다.
라이브러리에 대한 이러저러한 세부적인 내용까지 다루진 않을것이다. 좀더 이론적인 내용을 필요로 한다면 Program Library HOWTO 를 참고하기 바란다. 이 문서에서는 라이브러리를 만들고 활용하는 면에 중점을 둘것이다. 그러므로 위의 문서는 이문서를 읽기전에 대충이라도 한번 읽어보도록 한다.
정적 라이브러리와 공유라이브러리는 일반적인 내용임으로 간단한 설명과 일반적인 예제를 드는 정도로 넘어갈 것이다. 그러나 동적라이브러리에 대해서는 몇가지 다루어야할 이슈들이 있음으로 다른 것들에 비해서 좀더 비중있게 다루게 될것이다.
라이브러리에도 그 쓰임새에 따라서 여러가지 종류가 있다(크게 3가지). 가장 흔하게 쓰일수 있는 "정적라이브러리"와 "공유라이브러리", "동적라이브러리" 가 있다.
이들 라이브러리가 서로 구분되어지는 특징은 적재 시간이 될것이다.
정적라이브러리
정적라이브러리는 object file(.o로 끝나는) 의 단순한 모음이다. 정적라이브러린느 보통 .a 의 확장자를 가진다. 간단히 사용할수 있다. 컴파일시 적재되므로 유연성이 떨어진다. 최근에는 정적라이브러리는 지양되고 있는 추세이다. 컴파일시 적재되므로 아무래도 바이너리크기가 약간 커지는 문제가 있을것이다.
공유라이브러리
공유라이브러리는 프로그램이 시작될때 적재된다. 만약 하나의 프로그램이 실행되어서 공유라이브러리를 사용했다면, 그뒤에 공유라이브러리를 사용하는 모든 프로그램은 자동적으로 만들어져 있는 공유라이브러리를 사용하게 된다. 그럼으로써 우리는 좀더 유연한 프로그램을 만들수 잇게 된다.
정적라이브러리와 달리 라이브러리가 컴파일시 적재되지 않으므로 프로그램의 사이즈 자체는 작아지지만 이론상으로 봤을때, 라이브러리를 적재하는 시간이 필요할것이므로 정적라이브러리를 사용한 프로그램보다는 1-5% 정도 느려질수 있다. 하지만 보통은 이러한 느림을 느낄수는 없을것이다.
동적라이브러리
공유라이브러리가 프로그램이 시작될때 적재되는 반면 이것은 프로그램시작중 특정한때에 적재되는 라이브러리이다. 플러그인 모듈등을 구현할때 적합하다. 설정파일등에 읽어들인 라이브러리를 등록시키고 원하는 라이브러리를 실행시키게 하는등의 매우 유연하게 작동하는 프로그램을 만들고자 할때 유용하다.
예전에 libz 라는 라이브러리에 보안 문제가 생겨서 한창 시끄러웠던적이 있다. libz 라이브러리는 각종 서버프로그램에 매우 널리 사용되는 라이브러리였는데, 실제 문제가 되었던 이유는 많은 libz 를 사용하는 프로그램들이 "정적라이브러리" 형식으로 라이브러리를 사용했기 때문에, 버그픽스(bug fix)를 위해서는 문제가 되는 libz 를 사용하는 프로그램들을 다시 컴파일 시켜야 했기 때문이다. 한마디로 버그픽스 자체가 어려웠던게 큰 문제였었다. 도대체 이 프로그램들이 libz 를 사용하고 있는지 그렇지 않은지를 완전하게 알기도 힘들뿐더러, 언제 그많은 프로그램을 다시 컴파일 한단 말인가.
만약 libz 를 정적으로 사용하지 않고 "공유라이브러리" 형태로 사용한다면 bug fix 가 훨씬 쉬웠을것이다. 왜냐면 libz 공유라이브러리는 하나만 있을 것이므로 이것만 업그레이드 시켜주면 되기 때문이다.
아뭏든 이렇게 유연성이 지나치게 떨어진다는 측면이 정적라이브러리를 사용하지 않는 가장 큰 이유가 될것이다. 프로그램들의 덩치가 커지는 문제는 유연성 문제에 비하면 그리큰문제가 되지는 않을것이다.
라이브러리의 이름은 libmysum 이 될것이며, 여기에는 2개의 함수가 들어갈 것이다. 하나는 덧셈을 할 함수로 "ysum" 또 하나는 뺄셈을 위한 함수로 "ydiff" 으로 할것이다. 이 라이브러리를 만들기 위해서 mysum.h 와 mysum.c 2개의 파일이 만들어질것이다.
아주아주 간단하다. 단지 ar 에 몇가지 옵션만을 이용해서 libmysum 이란 라이 브러리를 만들었다. 'r' 은 libmysum.a 라는 라이브러리 아카이브에 새로운 오브젝트를 추가할것이라는 옵션이다. 'c' 는 아카이브가 존재하지 않을경우 생성하라는 옵션이다.
이제 라이브러리가 실제로 사용가능한지 테스트해보도록 하자.
예제 : print_sum.c
#include "mysum.h"
#include <stdio.h>
#include <string.h>
int main()
{
char oper[5];
char left[11];
char right[11];
int result;
memset(left, 0x00, 11);
memset(right, 0x00, 11);
// 표준입력(키보드)으로 부터 문자를 입력받는다.
// 100+20, 100-20 과 같이 연산자와 피연산자 사이에 공백을 두지 않아야 한다.
fscanf(stdin, "%[0-9]%[^0-9]%[0-9]", left, oper, right);
if (oper[0] == '-')
{
printf("%s %s %s = %d\n", left, oper, right,
ydiff(atoi(left), atoi(right)));
}
if (oper[0] == '+')
{
printf("%s %s %s = %d\n", left, oper, right,
ysum(atoi(left), atoi(right)));
}
}
위의 프로그램을 컴파일 하기 위해서는 라이브러리의 위치와 어떤 라이브러리를 사용할것인지를 알려줘야 한다. 라이브러리의 위치는 '-L' 옵션을 이용해서 알려줄수 있으며, '-l' 옵션을 이용해서 어떤 라이브러리를 사용할것인지를 알려줄수 있다. -l 뒤에 사용될 라이브러리 이름은 라이브러리의 이름에서 "lib"와 확장자 "a"를 제외한 나머지 이름이다. 즉 libmysum.a 를 사용할 것이라면 "-lmysum" 이 될것이다.
공유라이브러리는 실행시에 라이브러리를 적재함으로 프로그램을 배포할때는 공유라이브러리도 함께 배포되어야 한다. 그렇지 않을경우 다음과 같이 공유라이브러리를 찾을수 없다는 메시지를 출력하면서 프로그램 실행이 중단될 것이다.
[root@coco library]# ./print_sum
./print_sum: error while loading shared libraries: libmysub.so: cannot open shared object file: No such file or directory
위와 같은 오류메시지를 발견했다면 libmysub.so 가 시스템에 존재하는지 확인해 보자. 만약 존재하는데도 위와 같은 오류가 발생한다면 이는 LD_LIBRARY_PATH 나 /etc/ld.so.conf 에 라이브러리 패스가 지정되어 있지 않을 경우이다. 이럴때는 LD_LIBRARY_PATH 환경변수에 libmysub.so 가 있는 디렉토리를 명시해주거나, /etc/ld.so.conf 에 디렉토리를 추가시켜주면 된다.
만약 libmysub.so 가 /usr/my/lib 에 복사되어 있고 환경변수를 통해서 라이브러리의 위치를 알려주고자 할때는 아래와 같이 하면된다.
동적라이브러리라고 해서 동적라이브러리를 만들기 위한 어떤 특별한 방법이 있는것은 아니다. 일반 공유라이브러리를 그대로 쓰며, 단지 실행시간에 동적라이브러리를 호출하기 위한 방법상의 차이만 존재할 뿐이다.
정적/공유 라이브러리가 라이브러리의 생성방법과 컴파일방법에 약간의 차이만 있고 코드는 동일하게 사용되었던것과는 달리 동적라이브러리는 코드자체에 차이가 있다. 그럴수밖에 없는게, 동적라이브러리는 프로그램이 샐행되는 중에 특정한 시점에서 부르고 싶을때 라이브러리를 적재해야 하므로, 라이브러리를 적재하고, 사용하고 해제(free) 하기 위한 코드를 생성해야 하기 때문이다.
linux 에서는 이러한 라이브러리를 호출하기 위한 아래와 같은 함수들을 제공한다. 아래의 함수들은 solaris 에서 동일하게 사용될수 있다.
#include <dlfcn.h>
void *dlopen (const char *filename, int flag);
const char *dlerror(void);
void *dlsym(void *handle, char *symbol);
int dlclose(void *handle);
dlopen 은 동적라이브러리를 적재하기 위해서 사용된다. 첫번째 아규먼트인 filename 은 /usr/my/lib/libmysum.so 와 같이 적재하기 원하는 라이브러리의 이름이다. 만약 적재시킬 라이브러리의 이름이 절대경로로 지정되어 있지 않을경우에는 LD_LIBRARY_PATH 에 등록된 디렉토리에서 찾고, 여기에서도 찾지 못할경우 /etc/ld.so.cache 에 등록된 디렉토리 리스트에서 찾게 된다. dlopen 이 성공적으로 호출되면 해당 라이브러리에 대한 handle 값을 넘겨 준다. flag 는 RTLD_LAZY와 RTLD_NOW 중 하나를 정의할수 있다. RTLD_LAZY는 라이브러리의 코드가 실행시간에 정의되지 않은 심볼을 해결하며, RTLD_NOW 는 dlopen 의 실행이 끝나기전에(return 전에) 라이브러리에 정의되지 않은 심볼을 해결한다.
dlerror 는 dl 관련함수들이 제대로 작동을 수행하지 않았을경우 에러메시지를 되돌려준다. dleooro(), dlsym(), dlclose(), dlopen()중 마지막 호출된 함수의 에러메시지를 되돌려준다.
dlsym 은 dlopen 을 통해서 열린라이브러리를 사용할수 있도록 심볼값을 찾아준다. 심볼이라고 하면 좀 애매한데, 심볼값은 즉 열린라이브러리에서 여러분이 실제로 호출할 함수의이름이라고 생각하면 된다. handle 는 dlopen 에 의해서 반환된 값이다. symbol 은 열린라이브러리에서 여러분이 실제로 부르게될 함수의 이름이다. dlsym 의 리턴값은 dlopen 으로 열린 라이브러리의 호출함수를 가르키게 된다. 리턴값을 보면 void * 형으로 되어 있는데, void 형을 사용하지 말고 호출함수가 리턴하는 형을 직접명시하도록 하자. 이렇게 함으로써 나중에 프로그램을 유지보수가 좀더 수월해진다.
동적라이브러리는 실행시간에 필요한 라이브러리를 호출할수 있음으로 조금만(사실은 아주 많이겠지만 T.T) 신경쓴다면 매우 확장성높고 유연한 프로그램을 만들수 있다.
동적라이브러리의 가장 대표적인 예가 아마도 Plug-in 이 아닐까 싶다. 만약에 모질라 브라우저가 plug-in 을 지원하지 않는 다면 우리는 새로운 기능들 이 추가될때 마다 브라우저를 다시 코딩하고 컴파일하는 수고를 해야할것이다. 그러나 동적라이브러리를 사용하면 브라우저를 다시 코딩하고 컴파일 할필요 없이, 해당 기능을 지원하는 라이브러리 파일만 받아서 특정 디렉토리에 설치하기만 하면 될것이다. 물론 동적라이브러리를 사용하기만 한다고 해서 이러한 기능이 바로 구현되는 건 아니다. Plug-in 의 효율적인 구성을 위한 표준화된 API를 제공하고 여기에 맞게 Plug-in 용 라이브러리를 제작해야만 할것이다.
우리가 지금까지 얘로든 프로그램을 보면 현재 '+', '-' 연산을 지원하고 있는데, 만약 'x', '/' 연산을 지원하는 라이브러리가 만들어졌다면, 우리는 프로그램의 코딩을 다시해야만 할것이다. 이번에는 동적라이브러리를 이용해서 plug-in 방식의 확장이 가능하도록 프로그램을 다시 만들어 보도록 할것이다.
동적라이브러리를 이용해서 main 프로그램의 재코딩 없이 추가되는 새로운 기능을 추가시키기 위해서는 통일된 인터페이스를 지니는 특정한 형식을 가지도록 라이브러리가 작성되어야 하며, 설정파일을 통하여서 어떤 라이브러리가 불리어져야 하는지에 대한 정보를 읽어들일수 있어야 한다. 그래서 어떤 기능을 추가시키고자 한다면 특정 형식에 맞도록 라이브러리를 제작하고, 설정파일을 변경하는 정도로 만들어진 새로운 라이브러리의 기능을 이용할수 있어야 한다.
설정파일은 다음과 같은 형식으로 만들어진다. 설정파일의 이름은 plugin.cfg 라고 정했다.
+,ysum,libmysum.so
-,ydiff,libmysum.so
'-' 연산에대해서는 libmysum.so 라이브러리를 호출하며, ydiff 함수를 사용한다. '=' 연산에 대해서는 libmysum.so 라이브러리를 호출하고 ysum 함수를 사용한다는 뜻이다. 설정파일의 이름은 plugin.cfg 로 하기로 하겠다.
다음은 동적라이브러리로 만들어진 print_sum 의 새로운 버젼이다.
예제 : print_sum_dl.c
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
struct input_data
{
char oper[2];
char func[10];
char lib[30];
};
int main(int argc, char **argv)
{
char oper[2];
char left[11];
char right[11];
char buf[50];
char null[1];
int data_num;
struct input_data plug_num[10];
void *handle;
int (*result)(int, int);
int i;
char *error;
FILE *fp;
// 설정파일을 읽어들이고
// 내용을 구조체에 저장한다.
fp = fopen("plugin.cfg", "r");
data_num = 0;
while(fgets(buf, 50, fp) != NULL)
{
buf[strlen(buf) -1] = '\0';
sscanf(buf, "%[^,]%[,]%[^,]%[,]%[^,]", plug_num[data_num].oper,
null,
plug_num[data_num].func,
null,
plug_num[data_num].lib);
data_num ++;
}
fclose(fp);
printf("> ");
memset(left, 0x00, 11);
memset(right, 0x00, 11);
fscanf(stdin, "%[0-9]%[^0-9]%[0-9]", left, oper, right);
// 연산자를 비교해서
// 적당한 라이브러리를 불러온다.
for (i = 0; i < data_num ; i++)
{
int state;
if ((state = strcmp(plug_num[i].oper, oper)) == 0)
{
printf("my operator is : %s\n", plug_num[i].oper);
printf("my call function is : %s\n", plug_num[i].func);
break;
}
}
if (i == data_num)
{
printf("--> unknown operator\n");
exit(0);
}
handle = dlopen(plug_num[i].lib, RTLD_NOW);
if (!handle)
{
printf("open error\n");
fputs(dlerror(), stderr);
exit(1);
}
// 연산자에 적당한 함수를 불러온다.
result = dlsym(handle, plug_num[i].func);
if ((error = dlerror()) != NULL)
{
fputs(error, stderr);
exit(1);
}
printf("%s %s %s = %d\n",left, oper, right, result(atoi(left), atoi(right)) );
dlclose(handle);
}
위의 예제 프로그램은 다음과 같이 컴파일되어야 한다. 라이브러리 파일의 위치는 /usr/my/lib 아래에 있는것으로 하며, 라이브러리 찾기 경로에 등록되어 있다고 가정하겠다.
[root@localhost test]# ./print_sum_dl
> 10*10
my operator is : *
my call function is : ymulti
10 * 10 = 100
[root@localhost test]# ./print_sum_dl
> 10/10
my operator is : /
my call function is : ydiv
10 / 10 = 1
print_sum_dl.c 의 원본파일의 아무런 수정없이 단지 설정파일만 변경시켜 줌으로써 기존의 print_sum_dl 에 "곱하기"와 "나누기"의 새로운 기능이 추가 되었다.
위에서도 말했듯이 이러한 Plug-in 비슷한 기능을 구현하기 위해서는 통일된 함수 API가 제공될수 있어야 한다.
여기에 있는 내용중 동적라이브러리에 대한 내용은 솔라리스와 리눅스에서만 동일하게 사용할수 있다. Hp-Ux 혹은 윈도우에서는 사용가능하지 않는 방법이다. 이에 대한 몇가지 해법이 존재하는데, 이 내용은 나중에 시간이 되면 다루도록 하겠다. 어쨋든 솔라리스와 리눅스 상에서 코딩되고 윈도우 혹은 다른 유닉스로 포팅될 프로그램이 아니라면 위의 방법을 사용하는데 있어서 문제가 없을것이다.
MySQL 에 접속해서 데이터를 가져오는 쿼리를 던졌을때 테이블에 댇한 키파일이 깨졌다는 메세지가 뜬다.
"Warning: mysql_query(): Unable to save result set in c:\apm_setup\htdocs\mac\list.htm on line 76 Incorrect key file for table: 'glog'. Try to repair it"
구체적으로 이런 로그를 볼 수 있다.
이것은 비정상적으로 시스템이 종료되거나 DB서버를 비정상적으로 종료했을 때 DB 테이블의 유효성이 깨져서 생기는 문제이다.
정확한 원인을 파악하기 위해서는 해당 DB에 접속해서 다음과 같은 쿼리를 던져 본다.
mysql> analyze table glog; +------------------+---------+----------+------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +------------------+---------+----------+------------------------------------------------------------------+ | gdata.glog | analyze | error | Found key at page 5097472 that points to record outside datafile | | gdata.glog | analyze | error | Corrupt | +------------------+---------+----------+------------------------------------------------------------------+ 2 rows in set (0.08 sec)
이걸 고치기 위해서는 다음과 같은 쿼리를 던진다.
mysql> repair table glog; +------------------+--------+----------+----------------------------------------------+ | Table | Op | Msg_type | Msg_text | +------------------+--------+----------+----------------------------------------------+ | gdata.glog | repair | warning | Number of rows changed from 249503 to 249501 | | gdata.glog | repair | status | OK | +------------------+--------+----------+----------------------------------------------+ 2 rows in set (25.22 sec)
다시 한번 확인해보면 고쳐진것을 확인할 수 있다.
mysql> analyze table glog; +------------------+---------+----------+-----------------------------+ | Table | Op | Msg_type | Msg_text | +------------------+---------+----------+-----------------------------+ | gdata.glog | analyze | status | Table is already up to date | +------------------+---------+----------+-----------------------------+ 1 row in set (0.00 sec)
User Comments
IF you want to change a SET or ENUM column you may
not want to use the ALTER TABLE ... MODIFY
syntax.
It tries to keep the actual string values and not
the integer representation of the values, even
though they are stored as integers.
For example, if you just want to make a change in
spelling of the values in your enum column or your
set column, consider doing it like this:
ALTER TABLE table ADD new_column ...;
UPDATE table SET new_column = old_column + 0;
ALTER TABLE table DROP old_column;
You can use Alter Table to optimise a table without locking out selects (only writes), by altering a column to be the same as it's current definition. This is better than using repair table which obtains a read/write lock.
1 row in set (0.00 sec)E.g.
mysql> describe Temp_Table;
mysql> alter table Temp_Table change column ID ID int unsigned;
This will cause mysql to re-create the table and thus remove any deleted space.
This is useful for 24/7 databases where you don't want to completely lock a table.
while adding primary key constraint on null allowable integer column, mysql assigns default value 0 iff one NULL value exists on that column else alter table will fail with error "Duplicate entry '0' for key 1"
If you use ALTER TABLE to add a new column and set a DEFAULT value for the new column, then this value will be assigned to all the existing records.
So if you have a table with 100 records in, then use the following statement:
ALTER TABLE me.my_table
ADD COLUMN new_column INT NOT NULL DEFAULT 0;
then all the existing records will now have the value '0' in this new column 'new_column'.
In other words, you do not need to run the following UPDATE statement:
UPDATE me.my_table SET new_column = 0;
Hope this helps someone!
Mark Sweeting
http://www.sweeting.org/mark/
Add your own comment.