RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR
'Web_developing'에 해당되는 글 102

Many changes have been made to temporal — DATE, TIME, DATETIME, and TIMESTAMP — functions in MySQL 4.1. This includes support for microseconds and time zones.

In this article, a time value is one of either: TIME, DATETIME, or TIMESTAMP. A date value is one of either: DATE, DATETIME, or TIMESTAMP. A datetime value is one of any of the date or time value types.

Changed Functions

Several existing functions had their functionality extended in MySQL 4.1:

ADDDATE(temporal_expression, number_of_days)
SUBDATE(temporal_expression, number_of_days)

ADDDATE and SUBDATE accept a slightly modified syntax beginning with version 4.1.1. They still operate on a date value, but now also accept a second, numeric argument.

The second argument specifies a number of days that should be added to (or subtracted from) the date value. As always, if either argument resolves to NULL, ADDDATE and SUBDATE returns NULL.

mysql> select adddate('2004-10-01',15), subdate('2004-10-01',15);+--------------------------+--------------------------+| adddate('2004-10-01',15) | subdate('2004-10-01',15) |+--------------------------+--------------------------+| 2004-10-16               | 2004-09-16               |+--------------------------+--------------------------+1 row in set (0.20 sec)
DATE_ADD(temporal_expression, INTERVAL interval_expression interval_constant)
DATE_SUB(temporal_expression, INTERVAL interval_expression interval_constant)
EXTRACT(interval_constant FROM temporal_expression)

The DATE_ADD, DATE_SUB, and EXTRACT functions accept five new interval constants — DAY_MICROSECOND, HOUR_MICROSECOND, MINUTE_MICROSECOND, SECOND_MICROSECOND, and MICROSECOND.

mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',INTERVAL '1.999999' SECOND_MICROSECOND);+--------------------------------------------------------------------------------+| DATE_ADD('1992-12-31 23:59:59.000002', INTERVAL '1.999999' SECOND_MICROSECOND) |+--------------------------------------------------------------------------------+| 1993-01-01 00:00:01.000001                                                     |+--------------------------------------------------------------------------------+1 row in set (0.02 sec)
DATE_FORMAT(temporal_expression, format_string)
TIME_FORMAT(time_expression, format_string)

The DATE_FORMAT and TIME_FORMAT functions got a new option in MySQL 4.1.1 too. One can now use %f in the format string, to return microseconds in the range from 000000 (6 zeros) to 999999 (6 nines).

mysql> select date_format(current_timestamp,'%f');+-------------------------------------+| date_format(current_timestamp,'%f') |+-------------------------------------+| 000000                              |+-------------------------------------+1 row in set (0.02 sec)mysql> select time_format(current_time,'%f');+--------------------------------+| time_format(current_time,'%f') |+--------------------------------+| 000000                         |+--------------------------------+1 row in set (0.02 sec)

New Functions

About twenty new temporal functions were added. Many of them are implementations of similar functions from other database systems, such as MaxDB and Oracle.

ADDTIME(temporal_expression, time_expression)
SUBTIME(temporal_expression, time_expression)

The ADDTIME and SUBTIME functions provide the ability to do time arithmetic. They accept two arguments, the first of which must resolve to a time value, and the second of which must resolve to a TIME value. ADDTIME adds the time argument to the first expression and returns the result, and as you may expect, SUBTIME subtracts the time argument from the first expression and returns the result. Both functions returns NULL if either argument resolves to NULL.

mysql> select addtime('10:15:30','02:10:00'), subtime('2004-10-15 10:15:30','02:10:00');+--------------------------------+-------------------------------------------+| addtime('10:15:30','02:10:00') | subtime('2004-10-15 10:15:30','02:10:00') |+--------------------------------+-------------------------------------------+| 12:25:30                       | 2004-10-15 08:05:30                       |+--------------------------------+-------------------------------------------+1 row in set (0.20 sec)
DATEDIFF(temporal_expression, temporal_expression)

The DATEDIFF function returns the number of days between its two arguments, which must both resolve to a date value. The function returns NULL if either argument resolves to NULL.

mysql> select datediff('2004-10-20','2004-10-10');+-------------------------------------+| datediff('2004-10-20','2004-10-10') |+-------------------------------------+|                                  10 |+-------------------------------------+1 row in set (0.02 sec)
TIMEDIFF(temporal_expression, temporal_expression)

The TIMEDIFF function is another new function that provides time arithmetic functionality. This function returns the amount of time elapsed between the two temporal arguments. Both arguments must resolve to the same type of time value. TIMEDIFF returns NULL if either argument resolves to NULL.

mysql> select timediff('10:30:15','02:10:00');+---------------------------------+| timediff('10:30:15','02:10:00') |+---------------------------------+| 08:20:15                        |+---------------------------------+1 row in set (0.02 sec)
DATE(temporal_expression)
TIME(temporal_expression)

The DATE function returns the DATE portion of a date value. It returns NULL if its argument resolves to NULL.

The TIME function complements the DATE function; it takes a time value and returns its TIME portion. TIME returns NULL if its argument resolves to NULL.

mysql> select date('2004-10-01 10:15:30'), time('2004-10-01 10:15:30');+-----------------------------+-----------------------------+| date('2004-10-01 10:15:30') | time('2004-10-01 10:15:30') |+-----------------------------+-----------------------------+| 2004-10-01                  | 10:15:30                    |+-----------------------------+-----------------------------+1 row in set (0.02 sec)
MAKEDATE(year, day_of_year)
MAKETIME(hour, minute, second)

The MAKEDATE function returns the date that results from the combination of its arguments. Both arguments must resolve to a positive integer; the first specifies a YEAR value and the second specifies a given day in that year. The function returns NULL if either argument resolves to NULL. MAKEDATE also returns NULL if the day_of_year value is less than or equal to 0 (zero).

The MAKETIME function takes three arguments — an HOUR value, a MINUTE value, and a SECOND value — and returns the time that results by combining them. Each of the arguments must resolve to an integer. The function returns NULL if any of the arguments resolve to NULL.

mysql> select makedate(2004,152), maketime(10,15,30);+--------------------+--------------------+| makedate(2004,152) | maketime(10,15,30) |+--------------------+--------------------+| 2004-05-31         | 10:15:30           |+--------------------+--------------------+1 row in set (0.02 sec)
TIMESTAMP(temporal_expression)
TIMESTAMP(date_expression, time_expression)

The TIMESTAMP function has two possible formats.

In the first format, the function takes a date value and returns it as a TIMESTAMP value.

mysql> select timestamp('2004-10-15');+-------------------------+| timestamp('2004-10-15') |+-------------------------+| 2004-10-15 00:00:00     |+-------------------------+1 row in set (0.02 sec)

In the second format, TIMESTAMP accepts two arguments: a date value and a TIME value. The TIME value is added to the first expression and TIMESTAMP returns the result as a TIMESTAMP value.

mysql> select timestamp('2004-10-15','10:15:30');+------------------------------------+| timestamp('2004-10-15','10:15:30') |+------------------------------------+| 2004-10-15 10:15:30                |+------------------------------------+1 row in set, 1 warning (0.02 sec)

In each case, the function returns NULL if an argument resolves to NULL.

And now, a short digression. The TIMESTAMP data type itself was changed slightly in MySQL 4.1. Recall that in earlier versions of MySQL, TIMESTAMP includes an optional display width parameter, that lets one specify the size of a TIMESTAMP column when it is displayed, like this.

mysql> create table xy (col1 timestamp(8));Query OK, 0 rows affected (0.41 sec)mysql> insert into xy values('2004-10-01 10:15:30');Query OK, 1 row affected (0.01 sec)

With 4.0:

mysql> select * from xy;+----------+| col1     |+----------+| 20041001 |+----------+1 row in set (0.02 sec)

Although this syntax is still accepted, the option is no longer operative beginning with MySQL 4.1. From the 4.1.0 release on, a TIMESTAMP value is always returned as a string with the format 'YYYY-MM-DD HH:MM:SS' and different timestamp lengths are not supported.

Same definition, with 4.1:

mysql> select * from xy;+---------------------+| col1                |+---------------------+| 2004-10-01 10:15:30 |+---------------------+1 row in set (0.02 sec)
DAY(date_expression)

The DAY function is a synonym for DAYOFMONTH(). It returns the day portion of its date value argument. DAY returns NULL if the argument resolves to NULL.

mysql> select day('2004-10-01');+-------------------+| day('2004-10-01') |+-------------------+|                 1 |+-------------------+1 row in set (0.02 sec)
LAST_DAY(date_expression)

The LAST_DAY function takes a date value and returns the corresponding value for the last day of the given month. LAST_DAY returns NULL if the argument resolves to an invalid value (e.g. '2004-10-32') or if the argument is NULL.

mysql> select last_day('2004-10-01');+------------------------+| last_day('2004-10-01') |+------------------------+| 2004-10-31             |+------------------------+1 row in set (0.02 sec)
MICROSECOND(time_expression)

The MICROSECOND function takes a time value as an argument, and returns the microsecond portion of that value. MICROSECOND returns NULL if the argument resolves to NULL.

mysql> select microsecond('2004-10-15 10:15:30.999999');+-------------------------------------------+| microsecond('2004-10-15 10:15:30.999999') |+-------------------------------------------+|                                    999999 |+-------------------------------------------+1 row in set (0.03 sec)
WEEKOFYEAR(temporal_expression)

The WEEKOFYEAR function calculates the calendar week of its date value argument and returns the week number. The result always falls into the range from 1 (first week of the year) to 53 (last week of the year). Note that the first week of the year is the first week that has a Thursday in that year (or put another way, the week that contains January 4th). WEEKOFYEAR returns NULL if its argument resolves to NULL.

mysql> select weekofyear('2004-10-15'), weekofyear('2000-01-01');+--------------------------+--------------------------+| weekofyear('2004-10-15') | weekofyear('2000-01-01') |+--------------------------+--------------------------+|                       42 |                       52 |+--------------------------+--------------------------+1 row in set (0.01 sec)
STR_TO_DATE(temporal_string, format_string)

The STR_TO_DATE function converts its temporal_string argument into a DATE, TIME, DATETIME, or TIMESTAMP value with the format specified by its format_string argument.

The format_string argument accepts the same formats as the DATE_FORMAT function; the temporal_string given must be a temporal value written in the same format. STR_TO_DATE returns NULL if the temporal_string is an invalid value for the given format, or if either argument resolves to NULL.

mysql> select str_to_date('2004-10-15 10:15:30','%Y-%m-%d %H:%i:%s');+--------------------------------------------------------+| str_to_date('2004-10-15 10:15:30','%Y-%m-%d %H:%i:%s') |+--------------------------------------------------------+| 2004-10-15 10:15:30                                    |+--------------------------------------------------------+1 row in set (0.02 sec)mysql> select str_to_date('2004-10-15 10:15:30','%d.%m.%y %H.%i');+-----------------------------------------------------+| str_to_date('2004-10-15 10:15:30','%d.%m.%y %H.%i') |+-----------------------------------------------------+| NULL                                                |+-----------------------------------------------------+1 row in set (0.02 sec)
GET_FORMAT(temporal_constant, format_string_constant)

The GET_FORMAT function returns a format string, like the ones we're used to using as arguments for the DATE_FORMAT and TIME_FORMAT functions. The temporal_constant argument has four possible values: DATE, TIME, DATETIME, and TIMESTAMP (but not until 4.1.4 for TIMESTAMP). The format_string_constant argument has five possible values, which must be enclosed in single quotes: 'EUR', 'USA', 'JIS', 'ISO', and 'INTERNAL'.

mysql> select get_format(timestamp,'iso');+-----------------------------+| get_format(timestamp,'iso') |+-----------------------------+| %Y-%m-%d %H:%i:%s           |+-----------------------------+1 row in set (0.02 sec)

The combination of valid values for GET_FORMAT's two arguments gives us up to 20 possible returns from the function: five for DATE, five for TIME, five for DATETIME, and five more for TIMESTAMP. When used with TIMESTAMP as the temporal constant, GET_FORMAT returns the same values as shown for DATETIME.

Function CallResult
GET_FORMAT(DATE,'USA')'%m.%d.%Y'
GET_FORMAT(DATE,'JIS')'%Y-%m-%d'
GET_FORMAT(DATE,'ISO')'%Y-%m-%d'
GET_FORMAT(DATE,'EUR')'%d.%m.%Y'
GET_FORMAT(DATE,'INTERNAL')'%Y%m%d'
GET_FORMAT(DATETIME,'USA')'%Y-%m-%d-%H.%i.%s'
GET_FORMAT(DATETIME,'JIS')'%Y-%m-%d %H:%i:%s'
GET_FORMAT(DATETIME,'ISO')'%Y-%m-%d %H:%i:%s'
GET_FORMAT(DATETIME,'EUR')'%Y-%m-%d-%H.%i.%s'
GET_FORMAT(DATETIME,'INTERNAL')'%Y%m%d%H%i%s'
GET_FORMAT(TIME,'USA')'%h:%i:%s %p'
GET_FORMAT(TIME,'JIS')'%H:%i:%s'
GET_FORMAT(TIME,'ISO')'%H:%i:%s'
GET_FORMAT(TIME,'EUR')'%H.%i.%S'
GET_FORMAT(TIME,'INTERNAL')'%H%i%s'

These formats came from how MaxDB defines its date and time formats.

The MySQL Reference Manual shows two examples of GET_FORMAT used in conjunction with the DATE_FORMAT and STR_TO_DATE functions, which I'll repeat here.

mysql> SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR'));    -> '03.10.2003'mysql> SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA'));    -> 2003-10-31
UTC_DATE
UTC_DATE()
UTC_TIME
UTC_TIME()
UTC_TIMESTAMP
UTC_TIMESTAMP()

These functions, which can be written either with or without the parentheses, are niladic functions — they take no arguments.

UTC_DATE returns the current UTC (or Universal Coordinated Time) date as a value in either 'YYYY-MM-DD' or YYYYMMDD form (depending on whether the function is used in a string or numeric context). By the way, most people still call UTC time "Greenwich Mean Time".

The UTC_TIME function returns the current UTC time as a value in 'HH:MM:SS' or HHMMSS form (depending on whether the function is used in a string or numeric context).

The UTC_TIMESTAMP function returns the current UTC date and time as a value in 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS form (depending on whether the function is used in a string or numeric context).

mysql> select utc_date(), utc_date+1;+------------+------------+| utc_date() | utc_date+1 |+------------+------------+| 2004-09-14 |   20040915 |+------------+------------+1 row in set (0.02 sec)mysql> select utc_time(), utc_time+1;+------------+------------+| utc_time() | utc_time+1 |+------------+------------+| 16:09:12   |     160913 |+------------+------------+1 row in set (0.03 sec)mysql> select utc_timestamp(), utc_timestamp+1;+---------------------+-----------------+| utc_timestamp()     | utc_timestamp+1 |+---------------------+-----------------+| 2004-09-14 16:12:36 |  20040914161237 |+---------------------+-----------------+1 row in set (0.02 sec)

Time Zone Handling

MySQL 4.1 includes increased support for manipulating temporal values based on the time zone in which they exist.

For example, beginning with MySQL 4.1.3, the CURRENT_DATE(), CURRENT_TIME(), CURRENT_TIMESTAMP(), FROM_UNIXTIME(), LOCALTIME, LOCALTIMESTAMP, NOW, SYSDATE, and UNIX_TIMESTAMP() functions return values in the connection's current time zone, while the UTC_DATE(), UTC_TIME(), and UTC_TIMESTAMP() functions return values in Universal Coordinated, or UTC, time.

In addition, the new CONVERT_TZ function provides the ability to convert a DATETIME or TIMESTAMP value from one time zone to another.

Finally, data values of the TIMESTAMP data type are automatically interpreted as values belonging to the connection's current time zone. TIMESTAMP values thus behave the way they do in Oracle's TIMESTAMP WITH LOCAL TIME ZONE data type — that is, values stored in a TIMESTAMP column are normalized towards UTC and converted back to the current connection time zone at SELECT time. This gives MySQL the ability to provide the "current" TIMESTAMP value, even if the database is moved to a different location.

This brings up another point about changes to the TIMESTAMP data type.

The internal representation of TIMESTAMP values in InnoDB tables was changed between version 4.0 and 4.1, and then back again in version 4.1.4. This change will result in incorrect values in TIMESTAMP columns belonging to InnoDB tables after an upgrade.

To correct this problem, the course of action, when upgrading from MySQL 4.1.3 or earlier to version 4.1.4, is to use mysqldump to save, and then restore, all InnoDB tables that contain TIMESTAMP columns.

Now, back to time zones. Recall that in previous versions of MySQL, the time zone that is relevant for the server can be set either with the --timezone=timezone_name option to mysqld_safe or with the TZ environment variable when starting mysqld. That changed in MySQL 4.1.3.

Here's what happens now:

Beginning with MySQL 4.1.3, the MySQL server maintains several time zone settings: the system time zone, the server's current time zone, and a connection time zone for each client.

The system time zone.

When the server starts, it looks for the time zone of the host machine and uses that value to automatically set the system_time_zone system variable.

This variable replaces the old timezone system variable, which has been removed. So users migrating from an earlier version of MySQL will need to ensure that they replace all instances of the timezone system variable with references to system_time_zone instead.

The server's current time zone.

The dynamic global time_zone system variable specifies the time zone in which the server is running. Its initial value is 'SYSTEM', which simply means that the server time zone and the system time zone are the same.

This initial value can be explicitly set with the --default-time-zone=timezone option. Users with the SUPER privilege can also set the global value at runtime, with the SET GLOBAL time_zone statement, as shown here.

mysql> SET GLOBAL time_zone = timezone;

To get the current global time zone value, SELECT the @@global.time_zone variable:

mysql> SELECT @@global.time_zone;
The connection time zone for each client.

Each client that connects to MySQL has its own time zone setting, specified by the dynamic session time_zone variable. The initial value of this variable is the same as the global time_zone variable, but can be reset at runtime with the SET time_zone statement.

mysql> SET time_zone = timezone;

To get the current session time zone value, SELECT the @@session.time_zone variable:

mysql> SELECT @@session.time_zone;

You'll notice the = timezone argument in the SET GLOBAL time_zone and SET time_zone statements, as well as the same argument in the --default-time-zone server option. The values for these arguments can be given in one of three ways:

  1. As a string that specifies an offset from UTC, in the form '[+|-]HH:MM', for example '-7:00', to indicate the time zone that is seven hours earlier than UTC, Mountain Time. This method is always possible, regardless of which operating system MySQL is running under and whether or not the MySQL time zone tables have been populated.
  2. As a string that provides a full time zone name, for example 'Mountain Daylight Time'.
  3. Or as a string that provides an abbreviation for a full time zone name, for example, 'MDT', which is the abbreviation for 'Mountain Daylight Time'. By the way, the names I've used here are not universally accepted, since time zone names and abbreviations are operating system specific.

These last two methods work only on Unix-based systems and only if the time zone-related tables in the mysql database have been created and populated.

Now, it's important to remember that, although installing MySQL 4.1.3 or higher creates the time zone tables, the procedure does not also populate them. This last step must be done manually.

Also, users who are migrating from an earlier version of MySQL need to create the time zone tables separately, by upgrading the mysql database. If they don't, they won't be able to take advantage of the new time zone features.

So there's two things to do to ensure a smooth transition between MySQL 4.0 (or earlier) and 4.1.3 (and higher).

Step 1: Only if migrating from 4.1.2 or earlier:

Create the correct time zone tables, by running the mysql_fix_privilege_tables script.

Step 2: For all users running MySQL 4.1.3 or later on a Unix-based system (recall this doesn't work on Windows systems yet):

Populate the time zone tables.

To do so, run the mysql_tzinfo_to_sql program, provided with the MySQL distribution. mysql_tzinfo_to_sql reads the operating system time zone files and generates SQL statements from them. The SQL statements are then processed by mysql, to load the time zone tables.

To run mysql_tzinfo_to_sql successfully, one needs to know where the server machine's operating system time zone files are stored; check for a directory with a name similar to /usr/share/zoneinfo. Pass the directory name on the command line to mysql_tzinfo_to_sql, and send the output into the mysql program. Here's an example.

shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

mysql_tzinfo_to_sql can also be used to generate leap second information. An installation that needs to account for leap seconds within the database can initialize the leap second information by passing the name of a file holding the required information to the mysql program, as shown here.

shell> mysql_tzinfo_to_sql --leap file-name | mysql -u root mysql

Finally, there's one new function that makes use of the time zone tables to convert a datetime value between two timezones:

CONVERT_TZ(temporal_expression, from_timezone, to_timezone)

The CONVERT_TZ function takes three arguments. The first argument must resolve to a DATETIME or TIMESTAMP value, while the others must each resolve to a time zone in the form '[+|-]HH:MM' or a named time zone identifier, such as 'GMT' or (on some systems) 'Greenwich Mean Time'. Named time zones can only be used if the time zone tables are properly set up.

CONVERT_TZ assumes that the first argument is a datetime value that belongs to the time zone given in the from_timezone argument. The function converts that value into a datetime value belonging to the time zone given in the to_timezone argument.

In effect, you get the same datetime value, but from the point of view of a different time zone. The function returns NULL if any of the arguments are invalid, and also if any of the arguments resolve to NULL.

mysql> select convert_tz('2004-10-01 10:15:30','+01:00','+07:00');+-----------------------------------------------------+| convert_tz('2004-10-01 10:15:30','+01:00','+07:00') |+-----------------------------------------------------+| 2004-10-01 16:15:30                                 |+-----------------------------------------------------+1 row in set (0.02 sec)

Fractional Seconds

Fractional seconds support is simple. We have very little of it with 4.1, but the foundation has been laid for adding more support in later versions.

At this time, MySQL does not provide the ability to define a fractional-seconds precision for a time value column, although it is planned to add this ability to the TIMESTAMP data type in a future version. In fact, the syntax is accepted, but nothing is done with the fractional-seconds definition.

The reason the syntax is accepted, of course, is due to the fact that in previous versions of MySQL, one could define a display width for the TIMESTAMP data type, as I alluded to earlier.

It is possible to INSERT a TIMESTAMP value that includes a fractional-seconds portion into a TIMESTAMP column without getting an error. But it isn't possible to get the complete value, or even just the microseconds portion, back out because the microseconds are just chopped off at INSERT time.

mysql> create table xy(tscol timestamp);Query OK, 0 rows affected (0.09 sec)mysql> insert into xy (tscol) values ('2004-10-15 10:15:30.999999');Query OK, 1 row affected (0.01 sec)mysql> select * from xy;+---------------------+| tscol               |+---------------------+| 2004-10-15 10:15:30 |+---------------------+1 row in set (0.04 sec)mysql> select extract(microsecond from tscol) from xy;+---------------------------------+| extract(microsecond from tscol) |+---------------------------------+|                               0 |+---------------------------------+1 row in set (0.00 sec)

Nor do the niladic temporal functions that could include fractional seconds — CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP, NOW, SYSDATE, and so on — return values that include a fractional-seconds portion.

So, what do we do with microseconds?

Well, MySQL 4.1 can do temporal arithmetic that takes microseconds into account. As I said earlier, both the DATE_ADD and the DATE_SUB functions will now accept an INTERVAL qualifier of either MICROSECOND, SECOND_MICROSECOND, MINUTE_MICROSECOND, HOUR_MICROSECOND, or DAY_MICROSECOND — and will add (or subtract, respectively) the given value to or from a given temporal value. The same is true for temporal arithmetic done with the INTERVAL keyword.

mysql> select current_timestamp + INTERVAL 1.999999 second_microsecond;+----------------------------------------------------------+| current_timestamp + INTERVAL 1.999999 second_microsecond |+----------------------------------------------------------+| 2004-09-16 16:28:45.999999                               |+----------------------------------------------------------+1 row in set (0.02 sec)

The new ADDTIME and SUBTIME functions also do time arithmetic that includes microseconds. So does the TIMEDIFF function. The DATE_FORMAT, TIME_FORMAT and STR_TO_DATE functions now accept format strings with the ability to properly display temporal values that include a fractional-seconds portion. The EXTRACT and MICROSECOND functions can now return the fractional-seconds portion of a temporal value. And the TIME and TIMESTAMP functions can return values that include a fractional-seconds portion.

To summarize: MySQL's fractional-seconds support beginning with version 4.1 allows one to manipulate temporal values that include microseconds, but does not allow one to actually store such values in the database.

2006/09/08 10:48 2006/09/08 10:48
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 폴라리스
원본 http://blog.naver.com/neodays/20018207957

mysql 4.0 --> mysql 4.1 업그레이드시 확인사항


# 항목앞에 (*) 는 Incompatible Change(호환되지 않는 변경) 입니다.. 주의요망!!

# 이글을 작성당시 4.1 최신버전은 4.1.10 입니다.

# 이글은 mysql document 중 Upgrading from Version 4.0 to 4.1 을 번역한 겁니다.


- 글자셋 지원이 향상되었다. 서버는 다중 글자셋을 지원한다.

- 4.1 은 테이블명,컬럼명을 UTF8 형식으로 저장한다. standard 7-bit US-ASCII 가 아닌 문자로 된 테이블명, 컬럼명이 있을때는 dump & restore 를 사용하라.

그렇지 않으면(직접 복사,이전한 경우) 테이블을 사용할 수 없을 것이며 table not found 에러가 발생할 것이다. 이 경우에는 4.0 으로 다운그레이드 하면 다시 사용할 수 있다.

- 권한테이블의 password 필드가 길어졌다. mysql_fix_privilege_tables 를 사용하여 수정하라.

- Berkeley DB table handler 의 포멧이 더 길어졌다. 4.0 으로 다운그레이드 해야할 경우 mysqldump 를 사용하여 백업하고 4.0 서버를 시작하기 전에 모든 log.XXXXXXXXXX 파일을 삭제한 후 데이타를 로드하라.

- 커넥션별 타임존을 지원한다. 이름으로 타임존을 사용하려면 time zone 테이블을 생성해야 한다.

- 오래된 DBD-mysql module (Msql-MySQL-modules) 을 사용한다면 새 버전(DBD-mysql 2.xx 이상)으로 업그레이드하라. 업그레이드하지 않으면 몇몇 메소드(DBI->do() 와 같은..)가 에러상태를 정확히 판단하지 못할 것이다.

- --defaults-file=option-file-name 옵션은 옵션파일이 없다면 에러를 낼 것이다.

- 4.0.12 이상의 버전이라면 4.1 의 변화를 미리 적용해 볼 수 있다. --new 옵션을 사용하여 mysqld 를 실행하라. 또한 SET @@new=1 명령으로도 동작시킬수 있으며 SET @@new=0 으로 중단할 수있다.

몇가지 4.1 의 변화가 (업그레이드시) 문제가 될 수 있다고 생각되면 업그레이드하기 전에 --new 옵션을 사용해 미리 적용해 보길 권한다. 옵션파일에 아래와 같이 추가하여 적용해 볼 수 있다.

[mysqld-4.0]
new


[Server Changes]

1. 모든 테이블과 컬럼들이 글자셋을 가진다. 글자셋은 SHOW CREATE TABLE 을 사용해 확인할 수 있으며 mysqldump 에서도 글자셋 설정이 추가되었다.(4.0.6 이상의 버전에서는 이 새로운 형식의 덤프를 이해할 수 있지만 그 이전버전에서는 이해할 수 없다.) 단일글자셋을 사용하는 환경에서는 아무런 영향이 없다.( 즉 이전버전에서는 mysqldump 의 글자셋 설정이 아무 의미가 없다는 뜻..)

2. 4.1에서 직접 지원하는 글자셋을 사용한 4.0 데이타는 그대로 사용이 가능하다. 또한 4.1 에서 DB명, 테이블명, 컬럼명은 기본 글자셋이 무엇이든 상관없이 유니코드(UTF8) 로 저장된다.

(*)3. 4.1.0 ~ 4.1.3 버전에서 InnoDB 테이블에 TIMESTAMP 컬럼을 사용했다면 Dump & Restore 해야한다. 해당 버전의 TIMESTAMP 컬럼의 저장방식이 잘못되었다. 4.0 버전이거나 4.1.4 이후 버전이라면 문제가 없다.

(*)4. 4.1.3 부터 InnoDB 는 latin1 이 아니고 BINARY 가 아닌 문자열의 비교에 글자셋 비교함수를 사용한다. 이것으로 공백문자와 ASCII(32) 보다 작은 코드값의 문자들은 글자셋 내에서 정렬순서에 변화가 생겼다. InnoDB 는 latin1 과 BINARY 문자열에 대해서는 여전히 문자열 끝에 공백을 추가하여 비교하는 방식을 사용한다. 만약 4.1.2 혹은 그 이전 버전에서 latin1 이 아닌 컬럼에 인덱스가 있거나 테이블에 CHAR/VARCHAR/TEXT 등의 BINARY 가 아닌 컬럼에 ASCII(32) 보다 작은 코드값의 문자가 있다면 4.1.3 으로 업그레이드 후 ALTER TABLE 이나 OPTIMIZE TABLE 을 사용하여 인덱스를 재구성하라. 또한 이런 경우 MyISAM 테이블도 재구성하거나 수정하여야 한다.

(*)5. 4.1.0 ~ 4.1.5 의 버전에서 UTF8 형식의 컬럼이나 다른 멀티바이트 글자셋 컬럼에 prefix index 를 사용하였다면 4.1.6 혹은 그 이상 버전으로 업그레이드 하기 위해서는 테이블을 재구성해야 한다.

(*)6. 4.1 이전 버전에서 DB명, 테이블명, 컬럼명 등에 액센트 문자(128 ~225 코드값) 를 사용하였다면 4.1 버전으로 곧장 업그레이드 할 수 없다. (4.1 버전은 메타데이타 저장에 UTF8 을 사용하기 때문에..) RENAME TABLE 을 사용하여 UTF8 에서 지원되는 테이블명,DB명,컬럼명으로 변경하라.

(*)7. CHAR(N) 은 N 개의 글자를 의미한다. 이전 버전에서는 N 바이트를 의미했다. 1바이트 글자셋에서는 문제가 없으나 멀티바이트 글자셋을 사용한다면 문제가 된다.

8. 4.1 에서 frm 파일의 포멧이 변경되었다. 4.0.11 이후의 버전은 새 형식을 사용할 수 있지만 그 이전 버전에서는 사용할 수 없다. 4.1 에서 그 이전 버전으로 테이블을 이전하려면 Dump & Restore 를 사용하라.

9. 4.1.1 이나 그 이상의 버전으로 업그레이드하면 4.0 이나 4.1.0 으로 다운그레이드 하는것은 어렵다.

이전 버전에서는 InnoDB 의 다중 테이블스페이스를 인식하지 못한다.

(*)10. 4.1.3 의 커넥션별 타임존 지원기능에서 타임존 시스템 변수명은 system_time_zone 으로 변경되었다.

11. 윈도우 서버는 --shared-memory 옵션을 사용하여 공유메모리를 사용한 로컬 클라이언트 접속을 지원한다. 하나의 윈도우 머신에서 다수의 서버를 운영한다면 각각의 서버에 --shared-memory-base-name 옵션을 사용하라.

12. 통계 UDF 함수 인터페이스가 조금 변경되었다. 이제 각각의 XXX() 통계함수에 xxx_clear() 함수를 선언해야 한다.


[Client Changes]

mysqldump 에 --opt 와 --quote-names 옵션이 디폴트로 활성화되었다. --skip-opt 와 --skip-quote-names 옵션으로 비활성화 할 수 있다.


[SQL Changes]

(*)1. 4.1.2 부터 SHOW TABLE STATUS 출력내용중 Type 이 Engine 으로 변경되었다.

(TYPE 옵션은 4.x 버전에선 계속 지원되지만 5.1 버전에서는 사라질것이다.)

(*)2. 문자 비교는 SQL 표준을 따른다. 비교전에 문자열 끝공백을 제거하는 대신에 짧은 문자열을 공백을 추가하여 늘리는 방식을 사용한다. 이와 관련된 문제는 'a' > 'a\t' 라는 것이다.(이전 버전에서는 'a' = 'a\t' 이었다.) 만약 ASCII(32) 보다 작은 코드값의 문자로 끝나는 CHAR 나 VARCHAR 컬럼이 있다면 REPAIR TABLE 이나 myisamchk 를 사용하여 수정하라.

3. multiple-table DELETE 를 사용할때 삭제하려는 테이블의 별칭(Alias) 를 사용해야 한다.

DELETE test FROM test AS t1, test2 WHERE ...

Do this:

DELETE t1 FROM test AS t1, test2 WHERE ...

이것은 4.0 버전에서 발생하던 문제를 수정하기 위함이다.

(*)4. TIMESTAMP 는 이제 'YYYY-MM-DD HH:MM:SS' 형식의 문자열로 리턴된다. (4.0.12 부터 --new 옵션이 이와같이 동작하도록 지원한다.)

만약 4.0 의 방식처럼 숫자로 리턴되길 원한다면 +0 를 붙여서 출력하라.

mysql> SELECT ts_col + 0 FROM tbl_name;

TIMESTAMP 컬럼의 길이는 더이상 지원하지 않는다. TIMESTAMP(10) 에서 (10) 은 무시된다.

이것은 SQL 표준 호환성을 위해 필요했다. 차기 버전에서는 하위호환을 가지도록 timestamp 의 길이가 초단위의 일부분을 출력하도록 할것이다.

(*)5. 0xFFDF 와 같은 이진값은 해당값의 문자로 간주된다. 이것은 문자를 이진값으로 입력할때 글자셋과 관련된 문제를 해결한다. 숫자값으로 사용하기 위해서는 CAST() 를 사용하라.

mysql> SELECT CAST(0xFEFF AS UNSIGNED INTEGER) < CAST(0xFF AS UNSIGNED INTEGER);
-> 0

CAST() 를 사용하지 않는다면 해당값의 문자에 대한 비교가 될것이다.

mysql> SELECT 0xFEFF < 0xFF;
-> 1

이진값을 숫자형식에 사용하거나 = 연산에 대해 사용할때도 위와 동일하다.(4.0.13 부터 --new 옵션으로 4.0 서버에서 이러한 동작을 반영해볼 수 있다.)

6. DATE, DATETIME, TIME 값을 다루는 함수를 위해 클라이언트에 리턴되는 값은 임시적인 형식으로 고정되었다. 가령 4.1 버전에서 다음과 같은 값을 리턴한다.

mysql> SELECT CAST('2001-1-1' AS DATETIME);
-> '2001-01-01 00:00:00'

4.0 에서는 결과형식이 다르다.

mysql> SELECT CAST('2001-1-1' AS DATETIME);
-> '2001-01-01'

7. AUTO_INCREMENT 컬럼에 DEFAULT 를 명시할 수 없다.(4.0 에서는 무시되었으나 4.1 에서는 에러를 발생한다.)

8. LIMIT 는 음수를 인자로 받지 않는다. (-1 대신에 큰 정수숫자를 사용하라.)

9. SERIALIZE 는 sql_mode 변수값을 위한 모드값이 아니다. 대신에 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 를 사용하라. 또한 SERIALIZE 는 --sql-mode 옵션의 유효한 값이 아니며

대신 --transaction-isolation=SERIALIZABLE 를 사용하라.


[C API Changes]

(*)1. 4.1.3 에서 mysql_shutdown() 함수의 인자(SHUTDOWN-level)가 추가되었다. 이전에 사용한 mysql_shutdown(X) 을 mysql_shutdown(X,SHUTDOWN_DEFAULT) 로 수정해야 한다.

2. mysql_real_query() 와 같은 몇몇 API 들이 에러발생시 -1 이 아닌 1 을 리턴한다. 만약 아래와 같은 코드를 사용하였다면 수정해야 한다.

if (mysql_real_query(mysql_object, query, query_length) == -1)
{
printf("Got error");
}

Non-Zero 값을 체크하도록 수정하라.

if (mysql_real_query(mysql_object, query, query_length) != 0)
{
printf("Got error");
}


[Password-Handling Changes]

- 보안을 강화하기 위해 패스워드 해시 방식이 변경되었다. 4.0 이나 그 이전의 라이브러리를 사용한 클라이언트를 사용시에 문제가 발생할 수 있다.(아직 4.1로 업그레이드 하지 않은 클라이언트가 리모트 접속을 시도할때 발생할 수 있다.) 다음 항목은 이 문제 해결에 대한 전략을 제공한다. 이것은 낡은 클라이언트와 보안성의 사이에서 타협안을 제시한다.

1. 클라이언트만 4.1 라이브러리를 사용하도록 업그레이드한다. (몇가지 API 의 리턴값을 제외하고) 어떤 변화도 필요하지 않지만 Server/Client 어느쪽에서도 4.1의 새로운 기능을 사용할 수 없을것이다.

2. 4.1로 업그레이드 후 mysql_fix_privilege_tables 스크립트를 실행하여 password 컬럼의 길이를 수정한다. 그러나 서버 시작시 --old-passwords 옵션을 사용하여 하위호환성을 유지한다. 그러다가 모든 클라이언트가 4.1로 업그레이드 하면 --old-passwords 옵션 사용을 중지할 수 있다. 또한 패스워드를 새 형식에 맞도록 수정할수도 있다.

3. 4.1로 업그레이드 후 mysql_fix_privilege_tables 스크립트를 실행하여 password 컬럼의 길이를 수정한다. 모든 클라이언트가 4.1로 업그레이드 되었다면 --old-passwords 옵션을 사용하지 않고 서버를 실행한다. 대신에 모든 계정에 대해 패스워드를 새 형식에 맞도록 수정한다.

4. Netware 환경에서 4.0 에서 4.1 로 업그레이드 할때 Perl 과 PHP 버전을 업그레이드 하라.


2006/09/08 10:46 2006/09/08 10:46
이 글에는 트랙백을 보낼 수 없습니다
Web_developing/Mysql  2006/09/08 10:45
출처 블로그 > badajoa2002님의 블로그
원본 http://blog.naver.com/badajoa2002/14377724

1.   트렌젝션이란 무엇인가? (What is transaction ?)

트렌젝션이란, 중단없이 시작에서부터 종료까지 한번에 수행되어야 하는 하나의 작업단위를 이야기한다. 수행이 끝난후에는 중간에 작업이 실패되었을 경우에는 작업 수행전의 상태로 그대로 돌아가야 한다.

이해를 돕기위해서 쉽게 예를 들어서 설명하도록 하자, A계좌에서 B계좌로 1,000원을 계좌 이체를 한다고 가정하자. 작업은 다음과 같은 순서로 이루어지게 된다.

1)       A계좌에서 1,000원을 인출한다.

2)       B 계좌에 1,000원을 더한다.

만약 위의 작업을 수행하던 도중 A계좌에서 1,000원이 인출된 후에, 은행 시스템의 오류로 인해서 B계좌에 1,000원이 더해지지 않는다면, 중간에 1,000원이라는 돈은 공중에서 증발해 버린것이 된다. 이럴때는 다시 계좌이체를 수행하기 이전의 상태로 되돌려서 A계좌에로부터 1,000원을 인출하지 말아야 한다.

그래서 위의 1),2) 작업은 한꺼번에 이루어져야 한다. 계좌이체 작업과 같이 한번에 이루어져야 하는 작업을 트렌젝션이라고 부른다.

이처럼 트렌젝션은 쇼핑몰의 주문 결제나,예매와 같이 Mission Critical 작업 있어서 필수적인 개념이라고 있다.

2.  트렌젝션의 기본속성 ACID (Transaction attribute “ACID” )

트렌젝션은 크게 4가지 특성을 가지는데 Atomicity,Consistency,Isolation,Durability, 네가지를 줄여서 ACID라고 부른다.

그럼 이제 부터 ACID속성 각각에 대해서 상세하게 알아보도록 하자.

Atomicity (원자성)

Database modifications must follow an all or nothing.

원자성이란, 하나의 트렌젝션이 하나의 단위로만 처리가 되어야 한다는것이다. 하나의 트렌젝션안에 여러가지 step 트렌젝션이, 하나로 처리가 되어야한다. 위의 계좌 이체처럼, 계좌에서 돈을 빼고, 돈을 다른 계좌에 넣는 것과 같이 두개이상의 step으로 구성되어 있더라도, 계좌 이체라는 하나의 트렌젝션으로 처리가 된다.

그래서, 어느 step에서라도 트렌젝션이 실패가 되었을 경우에는 모든 상태가 트렌젝션 상태 전으로 rolled back되서, 이전 상태를 유지해야 한다.

트렌젝션의 원자성은 트렌젝션이 완전히 수행되거나, 아무것도 수행되지 않은 All or Nothing 이미를 가지게 된다.

Consistency (일관성)

states that only valid data will be written to the database

트렌젝션이 종료된후에 저장되는 데이타는 오류없는 데이타만 저장되어야 한다.

다시 풀어서 이야기하자면 계좌이체 과정에서, 인출은 되었는데, 다른 계좌로 돈이 안넘어갔다던지, 트렌젝션이 끝난후에, 잘못된 데이타 값으로 변경되었던지, 데이타베이스 constraint 깨졌던지 했을때, Consistency 잘못되었다고 이야기하고, 이런경우에 트렌젝션 내용을 저장하지 말고, 이전 상태로rollback되어야 한다.

Isolation (격리성)

Multiple transactions occurring at the same time not impact each other execution

격리성이란, 트렌젝션중에 의해서 변경된 내용이 트렌젝션이 완료되기전까지는 다른 트렌젝션에 영향을 주어서는 안된다는 이야기이다.

Tx A라는 트렌젝션 수행중 EMP 테이블의 값을 변경했을때, Tx A 완료되지 않은 상태에서 Tx B EMP 테이블의 값을 참고할 경우에, Tx A 의해 변경된 값을 참고하는것이 아니라(아직 TxA 완료되지 않았기 때문에) 기존의 값을 참고하게 해야한다.

Durability (지속성)

Ensures that any transaction committed to the database will not be lost.

지속성이랑, 트렌젝션이 완료된후에의 값이 영구저장소에 제대로 기록이 되어야한다는 의미이다. 트렌젝션이 완료되었는데, 디스크 IO에러,네트워크 등으로 값이 제대로 기록이되지 않거나 해서는 안된다는 이야기다.

2006/09/08 10:45 2006/09/08 10:45
이 글에는 트랙백을 보낼 수 없습니다
Web_developing/Mysql  2006/09/08 10:44
숫자 관련 함수
ABS(숫자) : 절대값 출력.
   select abs(123);
CEILING(숫자) : 값보다 큰 정수 중 가장 작은 수.
  --양수일 경우는 소숫점 자리에서 무조건 반올림(4.0과 같은 소숫점 자리 0 값은 제외)
  --음수일 경우는 소숫점 자리를 무조건 버림
   select ceiling(4.0);
   select ceiling(4.1);
   select ceiling(4.9);
FLOOR(숫자) : 값보다 작은 정수 중 가장 큰 수[실수를 무조건 버림(음수일 경우는 제외)].
  --음수일 경우는 [.0/.00/.000/...] 을 제외하고 무조건 소숫점을 버리고 반내림(?)
   select floor(4.0);
   select floor(4.1);
   select floor(4.9);
   select floor(-4.6789);
ROUND(숫자,자릿수) : 숫자를 소수점 이하 자릿수에서 반올림.(자릿수는 양수,0,음수를 갖을 수 있다.)
   --자릿수를 생략하면 소숫점이 5 이상일 때 반올림/자릿수를 지정하면 지정한 자리수에서 반올림
   select round(4.5);
   select round(4.55);
   select round(-4.5);
   select round(4.556);
   select round(4.556,0);
   select round(4.556,1);
   select round(4.556,2);
   select round(45.556,-1);
   select round(455.556,-2);
TRUNCATE(숫자,자릿수) : 숫자를 소수점 이하 자릿수에서 버림.
  ==>만일 자릿수를 소숫점 이전으로 정하면 소숫점이하는 버리고 나머지 값은 0 값으로 처리
     / 예) truncate(9999,-3) --> 9000
  ==>또는 자릿수를 소숫점이하로 정하며, 해당숫자가 자릿수보다 소숫점이 모자랄경우 0 값으로 대치
     / 예) truncate(999,3) --> 999.000
  --반드시 자릿수를 명시해주어야 한다
  --음수일 경우는 해당자릿수에서 소숫점을 버리면서 무조건 반올림
  ==>(자릿수 숫자에서 이후 숫자가 0 일 경우는 제외 / 예)-4.0,0/-400,-2/-4.1230,4)
  ==>음수 역시 자릿수를 소숫점이하로 정하며, 해당숫자가 자릿수보다 소숫점이 모자랄경우 0 값으로 대치
  ==>또한 자릿수를 소숫점 이전으로 정하면 소숫점이하는 버리고 나머지 값은 역시 0 값으로 처리
POW(X,Y) 또는 POWER(X,Y) : XY
  --소숫점이 있는 경우도 실행, 단 음수는 양수로 승처리
  select pow(-2.5,2);
  select pow(1.5,2);
MOD (분자, 분모) : 분자를 분모로 나눈 나머지를 구한다.(연산자 %와 같음)
  select mod(12,5);    ==> 2
  select 12%5;           ==> 2
GREATEST(숫자1,숫자2,숫자3...) : 주어진 수 중 제일 큰 수 리턴.
  select greatest(100,101,90);
LEAST(숫자1,숫자2,숫자3...) : 주어진 수 중 제일 작은 수 리턴.
  select least(100,101,90);
INTERVAL(a,b,c,d.....) : a(숫자)의 위치 반환
  --두 번째 이후는 오름차순 정렬이 되어야 함
  예) INTERVAL(5,2,4,6,8) ==> 2
       5는 4와 6사이에 존재, 4~6사이의 위치가 앞에서 2번째
  select interval(4,1,2,3,5,6);
문자 관련 함수
ASCII(문자) : 문자의 아스키 코드값 리턴.
  SELECT ASCII('문자');
  select ascii('A');
CONCAT('문자열1','문자열2','문자열3'...) : 문자열들을 이어준다.
  select concat('ASP,','PHP,','SQL',' WEB STUDY');
INSERT('문자열','시작위치','길이','새로운문자열') : 문자열의 시작위치부터 길이만큼 새로운 문자열로 대치
  '시작위치' 와 '길이'는 문자열이 아니므로 작은따옴표로 굳이 묶어주지 않아도 된다.
  select insert('MySql web study','7','3','offline');
  select insert('MySql web study',7,3,'offline');
REPLACE('문자열','기존문자열','바뀔문자열') : 문자열 중 기존문자열을 바뀔 문자열로 바꾼다.
  select replace('MySql web study','web','offline');
INSTR('문자열','찾는문자열') : 문자열 중 찾는 문자열의 위치값을 출력
  --값이 존재하지 않으면 0값 리턴
  select instr('MySql web study','s');
  select instr('MySql web study','S');
LEFT('문자열',개수) : 문자열 중 왼쪽에서 개수만큼을 추출.
  select left('MySql web study',5);
  select left('MySql web study','5');
RIGHT('문자열',개수) : 문자열 중 오른쪽에서 개수만큼을 추출.
  select right('MySql web study',5);
  select right('MySql web study','5');
MID('문자열',시작위치,개수) : 문자열 중 시작위치부터 개수만큼 출력
  select mid('MySql web study',7,3);
  select mid('MySql web study','7','3');
SUBSTRING('문자열',시작위치,개수) : 문자열 중 시작위치부터 개수만큼 출력
  select substring('Mysql web study',11,5);
  select substring('Mysql web study','11','5');
LTRIM('문자열') : 문자열 중 왼쪽의 공백을 없앤다.
  select ltrim('          web study');
RTRIM('문자열') : 문자열 중 오른쪽의 공백을 없앤다.
  select rtrim('web study          ');
TRIM('문자열') : 양쪽 모두의 공백을 없앤다.
  select trim('     web study      ');
LCASE('문자열') 또는 LOWER('문자열') : 소문자로 바꾼다.
  select lcase('MYSQL');
  select lower('MySQL');
UCASE('문자열') 또는 UPPER('문자열') : 대문자로 바꾼다.
  select ucase('mySql');
  select upper('mysql');
REVERSE('문자열') : 문자열을 반대로 나열한다.
  예) REVERSE('abcde') ==> edcba
  select reverse('lqSyM');
논리 관련 함수, 집계함수
--논리 관련 함수
IF(논리식,참일 때 값,거짓일 때 값)
  논리식이 참이면 참일 때 값을 출력하고 논리식이 거짓이면 거짓일 때 출력한다.
IFNULL(값1,값2)
값1이 NULL 이면 값2로 대치하고 그렇지 않으면 값1을 출력

--집계 함수
COUNT(필드명)
  NULL 값이 아닌 레코드 수를 구한다.
SUM(필드명)
  필드명의 합계를 구한다.
AVG(필드명)
  각각의 그룹 안에서 필드명의 평균값을 구한다.
MAX(필드명)
  최대값을 구한다.
MIN(필드명)
  최소값을 구한다.
날짜 관련 함수
NOW() 또는 SYSDATE() 또는 CURRENT_TIMESTAMP()
  현재 날짜와 시간 출력
  ※ 함수의 상황이 숫자인지 문자열인지에 따라
     YYYYMMDDHHMMSS 또는
     'YYYY-MM-DD HH:MM:SS' 형식으로 반환한다.
  예)
  select now();
  ==> '2001-05-07 09:10:10'
  select now() + 0;
  ==> 20010507091010
CURDATE() 또는 CURRENT_DATE()
  현재 날짜 출력
  ※ 함수의 상황이 숫자인지 문자열인지에 따라
     YYYYMMDD 또는
     'YYYY-MM-DD 형식으로 반환한다.
  예)
  select curdate();
  ==> '2001-05-07'
  select curdate() + 0;
  ==> 20010507
CURTIME() 또는 CURRENT_TIME()
  현재 시간 출력
  ※ 함수의 상황이 숫자인지 문자열인지에 따라
  HHMMSS 또는 'HH:MM:SS' 형식으로 반환한다.
  예)
  select curtime();
  ==> '09:10:10'
  select curtime() + 0;
  ==> 091010
DATE_ADD(날짜,INTERVAL 기준값)
  날짜에서 기준값 만큼 더한다.
※ 기준값 : YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
  예)
  select date_add(now(), interval 2 day);
  ==> 오늘보다 2일 후의 날짜와 시간 출력.
  select date_add(curdate(), interval 2 day);
  ==> 오늘보다 2일 후의 날짜 출력.
DATE_SUB(날짜,INTERVAL 기준값)
  날짜에서 기준값 만큼 뺸다.
※ 기준값 : YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
  select date_sub(now(),interval 2 day);
  ==> 오늘보다 2일 전의 날짜와 시간 출력.
  select date_sub(curdate(), interval 2 day);
  ==> 오늘보다 2일 전의 날짜 출력.
YEAR(날짜) : 날짜의 연도 출력.
  select year('20000101');
  select year(20000101);
  select year('2000-01-01');
  select year(now());
  select year(curdate());
  select year(date_add(now(),interval 2 year));
  select year(date_sub(curdate(),interval 2 year));

MONTH(날짜) : 날짜의 월 출력.
  select month('20001231');
  select month(20001231);
  select month('2000-12-31');
  select month(now());
  select month(curdate());
  select month(date_add(now(),interval 2 month));
  select month(date_sub(curdate(),interval 2 month));

MONTHNAME(날짜) : 날짜의 월을 영어로 출력.
  select monthname(20021221);
  select monthname('20000721');
  select monthname('2000-08-10');
  select monthname(now());
  select monthname(curdate());
  select monthname(date_add(now(),interval 17 month));
  select monthname(date_sub(curdate(),interval 11 month));

DAYNAME(날짜) : 날짜의 요일일 영어로 출력.
  select dayname(20000121);
  select dayname('20010123');
  select dayname('2001-06-22');
  select dayname(now());
  select dayname(curdate());
  select dayname(date_add(now(),interval 21 day));
  select dayname(date_sub(curdate(),interval 333 day));

DAYOFMONTH(날짜) : 날짜의 월별 일자 출력.
  select dayofmonth(20030112);
  select dayofmonth('20011231');
  select dayofmonth('2001-12-23');
  select dayofmonth(now());
  select dayofmonth(curdate());
  select dayofmonth(date_add(now(),interval 56 day));
  select dayofmonth(date_sub(curdate(),interval 33 day));

DAYOFWEEK(날짜) : 날짜의 주별 일자 출력(월요일(0),화요일(1)...일요일(6))
  select dayofweek(20011209);
  select dayofweek('20001212');
  select dayofweek('2003-03-21');
  select dayofweek(now());
  select dayofweek(curdate());
  select dayofweek(date_add(now(),interval 23 day));
  select dayofweek(date_sub(curdate(),interval 31 day));

WEEKDAY(날짜) : 날짜의 주별 일자 출력(월요일(0),화요일(1)...일요일(6))
  select weekday(20000101);
  select weekday('20030223');
  select weekday('2002-10-26');
  select weekday(now());
  select weekday(curdate());
  select weekday(date_add(now(),interval 23 day));
  select weekday(date_sub(curdate(),interval 33 day));

DAYOFYEAR(날짜) : 일년을 기준으로 한 날짜까지의 날 수.
  select dayofyear(20020724);
  select dayofyear('20001231');
  select dayofyear('2002-01-01');
  select dayofyear(now());
  select dayofyear(curdate());
  select dayofyear(date_add(curdate(),interval 44 year));
  select dayofyear(date_sub(now(),interval 25 month));
  select dayofyear(date_add(now(),interval 55 day));
  select dayofyear(date_sub(curdate(),interval 777 hour));
  select dayofyear(date_add(now(),interval 999999 minute));

WEEK(날짜) : 일년 중 몇 번쨰 주.
  select week(now());
  select week(date_sub(curdate(),interval 12 month));

FROM_DAYS(날 수)
  --00년 00월 00일부터 날 수 만큼 경과한 날의 날짜 출력.
     ※ 날 수는 366 이상을 입력 그 이하는 무조건 '0000-00-00' 으로 출력.
  --또한 9999-12-31 [from_days(3652424)] 까지의 날짜가 출력가능 하다고는 하나
     정확히 말하면 0000-03-15 [from_days(3652499)] 까지의 날짜가 출력가능함.
  --따라서 날 수는 366 이상 3652424[3652499] 이하가 되어야 한다.
  select from_days(3652424);
  select from_days('3652499');

TO_DAYS(날짜)
  --00 년 00 월 00일 부터 날짜까지의 일자 수 출력.
  --from_days와 비교해 볼 때 정확한 날짜범위는 3652424 일 수 까지임을 알 수 있다.
  select to_days('99991231');
  select to_days('0000-03-15');
  응용 예제1) 자신이 살아 온 날수
  select to_days(now()) - to_days('본인생일자');
  select to_days(now()) - to_days('1970-10-10');
  응용 예제2) 살아 온 날수를 이용하여 자신의 나이를 만으로 구하기
  select (to_days(now())-to_days('1970-10-10'))/365;
  select floor((to_days(now())-to_days('19701010'))/365);

DATE_FORMAT(날짜,'형식') : 날짜를 형식에 맞게 출력
DATE타입구분기호설명구분기호설명
년도%Y4자리 연도%y2자리 년도
%M
%b
긴 월 이름 (January, ...)
짧은 월 이름(Jan, ...)
%m
%c
숫자의 월 (01...12)
숫자의 월 (1...12)
요일%W긴 요일 이름 (Sunday, ...)%a짧은 요일 이름 (Sun, ...)
%D
%w
월 내에서 서수 형식의 일(1th, ...)
숫자의 요일 (0=Sunday, ...)
%d
%e
%j
월 내의 일자 (01...31)
월 내의 일자 (1...31)
일년 중의 날수 (001...366)
%l
%h
%I
12시간제의 시 (1...12)
12시간제의 시 (01...12)
12시간제의 시 (01...12)
%k
%H
12시간제의 시 (0...23)
12시간제의 시 (00...23)
%i숫자의 분 (00...59)
%S숫자의 초 (00...59)%s숫자의 초 (00...59)
시간%r12시간제의 시간 (hh:mm:ss AM 또는 PM)%T24시간제의 시간 (hh:mm:ss)
%U일요일을 기준으로 한 주 (0...52)%u월요일을 기준으로 한 주 (0...52)
기타%%문자 '%'%pAM 또는 PM

  ☞ 예)
  select date_format(now(),'%Y:%M:%p');
  ==> 2001:May:PM

▶ DATABASE() : 현재의 데이터베이스 이름을 출력한다.

▶ PASSWORD('문자열')
: 문자열을 암호화한다.

▶ FORMAT(숫자,소수이하자리수) : 숫자를 #,###,###.## 형식으로 출력
  --임의의 소수점자릿수를 생성한다./소숫점을 필요한 만큼 취한다.
  --소숫점을 만들어 같은 길이로 한다음 동일하게 프로그램에서 불러와서 소숫점을 버리고
     필요한 곳에 출력하는 등에 응용할 수 있다.
  select format(123,5);
  select format(123.12345600123,9);
  select format(123.123,-3);
  ※ 소숫점이하자리수가 0 이나 음수값은 해당이 안됨
2006/09/08 10:44 2006/09/08 10:44
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > What you see is what you get
원본 http://blog.naver.com/etwas0227/60022701812

MySQL 5.0, 스토리지와 SQL 분리한 DBMS 업계 다크호스

MySQL 5.0이 지난 2005년 11월에 발표된 이후 새롭게 추가된 성능에 대해서는 여러 번 소개되었으며 많은 곳에서 언급이 되고 있다. 하지만 실제 사용자들이 가장 많이 물어온 것은 과연 MySQL 5.0에서 얼마나 많은 성능향상이 있었는지에 대한 부분이었다. 이번 특집을 통해 MySQL 5.0이 이전 버전들에 비해 그리고 다른 데이터베이스와 비교할 때 어떤 성능을 나타내고 있는지 알아보고 어떠한 변화가 이러한 성능향상을 가져왔는지 알아보자.

그동안 MySQL은 가볍고 빠른 데이터베이스로 많이 알려져 왔지만 실제로 어떠한 성능을 내는지 비교 벤치마크가 이뤄진 적이 별로 없는 탓에 체감적인 성능으로만 이야기되는 경우가 많았다. 사실 MySQL 5.0 이전 버전까지는 다른 상용 데이터베이스에 비해 지원되는 기능이 많이 부족해서 같은 선상에 놓고 벤치마크를 진행하기가 어려웠던 것도 그 중 하나의 이유였다. 일반적인 데이터베이스 벤치마크가 트랜잭션의 지원을 기본으로 함에도 불구하고 MySQL의 기본 스토리지 엔진인 MyISAM은 트랜잭션을 지원하지 않았고, 트랜잭션을 지원하는 스토리지 엔진인 InnoDB 엔진 같은 경우 MyISAM보다 한참 떨어지는 성능을 낸다는 것이 일반적인 인식이었기 때문이다.

물론 아직도 업계에서 공식적인 성능 비교를 위해 많이 사용하는 TPC-C를 기반으로 하여 MySQL을 벤치마크 테스트를 할 수 있는 테스트 프로그램이 OSDL(Open Source Development Lab)의 DBT-2 외에는 전무하고 아직 DBT-2는 0.37 버전이라서 객관적인 성능 비교는 힘든 상태이지만 상대적인 비교를 통해 MySQL의 버전 별 성능과 엔진 별 성능 그리고 다른 데이터베이스와의 성능 차이를 알아보자.

MySQL 성능 벤치마크 테스트
앞에서 언급한 대로 벤치마크 테스트의 경우 TPC(Transaction Processing Performance Council)와 같은 공인된 기관에서 테스트 결과를 제시하는 것을 가장 신뢰할 수 있겠지만 현재 MySQL을 기반으로 수행된 TPC 테스트 결과가 없으며, 다른 공식적인 벤치마크 테스트 결과도 최소 6개월 이전의 데이터로서 현재 MySQL 5.0 버전이 출시된 상태에서는 그다지 실효성이 없는 상태이다. 그래서 이번에 제시되는 벤치마크 테스트는 MySQL 5.0의 정식버전 출시 이전에 MySQL 본사 벤치마크 테스트 랩에서 수행된 결과를 사용한다.

벤치마크 시나리오
이번 벤치마크는 기본적으로 MySQL의 성능을 측정하기 위해 만들어진 오픈소스 벤치마크 툴인 Sysbench(sysbench.sourceforge.net)를 기반으로 수행되었다. Sysbench는 데이터베이스가 동작하는 서버의 파일 I/O 성능, 스케쥴러 성능, 메모리 할당과 전송 속도 및 데이터베이스의 OLTP(Online Transaction Processing) 성능을 측정할 수 있으며 처음 만들어질 당시에는 MySQL을 위한 것이었으나 현재는 테스트의 스펙을 만족시키는 각종 데이터베이스들을 지원하고 있다. 이번 벤치마크 테스트는 다음과 같은 사항으로 수행되었다.

CPU : 하이퍼쓰레딩이 가능한 인텔 2.0GHz 제온 CPU 4개
디스크 : 8개의 SCSI 디스크를 하드웨어 RAID0+1으로 RAID 구성
메모리 : 4GB
운영체제 : 레드햇 AS 3.0 업데이트 2. 커널 2.4.21-EL
테이블 크기 : 100만 건(300MB)


이번 테스트는 데이터베이스 자체가 낼 수 있는 최고의 성능을 알아보기 위해 Primary Key를 사용하도록 하였으며 가능한 모든 테이블의 데이터가 데이터베이스의 메모리 캐시를 사용할 수 있도록 하였다. 본 테스트는 MySQL 4.1.12과 5.0.7의 버전 간의 성능비교와 MySQL 4.1.12, MySQL 5.0.7, Oracle 10g, PostgreSQL 8, EnterpriseDB 8 등 여러 데이터베이스와의 성능비교를 비롯해 CPU 개수에 따른 확장성 테스트를 하는 것이 목적이다. 이번 테스트에 사용된 테이블 스키마는 다음과 같다.

CREATE TABLE `sbtest` (
`id` int(10) unsigned NOT NULL auto_increment,
`k` int(10) unsigned NOT NULL default '0',
`c` char(120) NOT NULL default '',
`pad` char(60) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `k` (`k`);


그리고 한 번의 트래낵션으로 처리되는 테스트쿼리는 다음과 같다

특정 데이터 지정(10회) : SELECT c FROM sbtest WHERE id=N
특정 범위 지정(1회) : SELECT c FROM sbtest WHERE id BETWEEN N AND M
범위 지정 합계(1회) : SELECT SUM(c) FROM sbtest WHERE id BETWEEN N and M
범위 지정 후 Order by 수행(1회) : SELECT c FROM sbtest WHERE id between N and M ORDER BY c
범위 지정 후 DISTINCT 수행(1회) : SELECT DISTINCT c FROM sbtest WHERE id BETWEEN N and M ORDER BY c


MySQL 버전 간 성능비교
MySQL은 여러 가지 스토리지 엔진을 사용할 수 있다는 것을 들고 있다. 하지만 InnoDB 자체의 스토리지 엔진으로서의 우수성에도 불구하고 성능 문제로 InnoDB 엔진이 사용되지 않는 경우가 많았다. MySQL은 5.0 버전을 출시하면서 InnoDB 스토리지 엔진의 성능향상을 하나의 큰 변화로 내세웠는데 이번 벤치마크는 실제로 어떠한 성능차이를 보여주는지 알아보기 위해 행해졌다. MySQL의 버전 간 성능 비교는 4.1.12 표준 바이너리와 ICC(Intel C Compiler) 바이너리, 5.0.7 표준 바이너리와 5.0.7 커스텀 빌드간의 성능을 비교했으며 모두 InnoDB 스토리지 엔진을 사용했다.

<그림 1> MySQL 버전 별 InnoDB 성능


<그림 1>에서 확인할 수 있는 것과 동일한 피크 치에서의 성능 차이는 커스텀 빌드의 5.0.7과 4.1.12 표준 바이너리와는 약 20%, 5.0.7 표준 바이너리와 4.1.12 표준 바이너리와는 10% 정도의 차이를 보여주고 있다. ICC 바이너리의 경우 최고 성능은 떨어지나 꾸준히 부하를 증가하는 경우에도 일관된 수치를 보여준다는 장점이 있다.

다른 DBMS와의 벤치마크
이번 벤치마크는 MySQL 5.0과 오라클 10g, PorsgreSQL8, EnterpriseDB8과의 비교 벤치마크 테스트이다. 이 중에서 EnterpriseDB의 경우에는 조금 생소할 수도 있는데, EnterpriseDB는 PostgreSQL 기반의 상용 데이터베이스로써 오라클을 기반으로 작성된 애플리케이션을 전혀 수정하지 않고 사용할 수 있도록 한 데이터베이스이다. 벤치마크 테스트는 데이터베이스와 상관없이 동일한 방법으로 수행되었다. 물론 본 벤치마크 테스트의 경우 앞에서 설명한 바와 같이 100만 건의 레코드를 가진 테이블에서 Primary Key를 사용하는 특수한 환경에서 테스트되었기 때문에 실사용 시의 속도와는 차이가 있을 수 있다.

<그림 2> MySQL과 기타 데이터베이스와의 비교 벤치마크


<그림 2>의 결과를 간단히 정리하면 MySQL 5.0/InnoDB가 최상의 결과를 보이며, 오라클 10g는 6.5%, PostgreSQL 8은 23.47%, MySQL 5.0/MyISAM은 43.18%, EnterpriseDB 8은 46.02% 정도 느린 결과를 보이는 것을 알 수 있다. 이번 벤치마크에서 가장 뜻밖의 결과를 보인 테스트였다. 뜻밖인 부분은 MyISAM의 성능이 매우 떨어지는 것으로 나왔다는 것이었는데, 이는 이번 테스트가 Primary Key만을 사용하게 해서 대부분의 테이블 데이터를 메모리 버퍼를 통해 수행되게 하면서 나타난 결과라고도 볼 수 있다. 만일 이번 테스트가 1GB 정도의 메모리를 가진 낮은 사양의 서버에서 일반 키를 사용하게 수행했다면 전혀 다른 결과가 나왔을 수도 있을 것이다.

CPU 개수에 따른 확장성 테스트
이제까지의 테스트는 4개의 CPU에서 수행된 결과였다면 이번 테스트는 CPU 개수를 1개에서 4개까지 변화시키면서 시스템이 확장되는 것에 따라 데이터베이스의 성능이 고르게 증가하는지를 보기 위한 확장성 테스트이다. 이번 테스트는 가능한 디스크 I/O를 줄이고 CPU에 의존적인 데이터베이스 엔진 자체의 성능을 평가하기 위한 테스트였기 때문에 확장성 테스트에 매우 적합하다고 할 수 있다.

<그림 3> CPU 개수에 따른 데이터베이스 확장성 테스트


CPU가 하나일 때와 4의 CPU에 하이퍼쓰래딩을 켠 상태를 비교해봤을 때 오라클이 3.83로 가장 뛰어난 확장성을 보였으며, MyISAM을 제외한 3개는 비슷한 정도의 확장성을 보여줬다. 본 테스트에서도 MyISAM이 가장 떨어지는 확장성을 보여줬는데 이는 MyISAM이 작은 시스템에서 최적의 성능을 내도록 설계된 스토리지 엔진이기 때문으로 보인다.

MySQL의 성능을 좌우하는 기술
이번 테스트의 경우 사실 다른 데이터베이스와의 성능 비교를 위한 것이라기 보다는 MyISAM에 대한 정보만을 가지고 있는 MySQL 사용자들에게 InnoDB의 성능이 MySQL 5.0버전에서 얼마나 좋아졌으며 실제적으로 어떠한 성능을 내는지 보여주는 것에 중점을 맞췄다. 물론 MyISAM이 InnoDB에 비해 성능이 떨어지는 스토리지 엔진이라는 것이 아닌 어떠한 상황에서 더 좋은 성능을 낼 수 있는지를 설명하기 위한 것이다.

MySQL 데이터베이스 아키텍처
MySQL 5.0 버전의 출시와 함께 그 동안 여러 변화를 거쳐오던 MySQL의 전체 아키텍처가 확고하게 자리를 잡았다. 물론 5.1 버전까지 아키텍처 통합은 계속적으로 이뤄질 예정이지만 그 동안 스토리지 엔진 별로 실제 사용할 수 있는 기능들에 많은 차이가 있었던 것에 비해서 5.0 버전에서는 스토리지 레이어와 SQL 레이어를 확실하게 구분하면서 기본적인 기능들이 스토리지 엔진과 상관없이 동작하도록 했다. 또한 메모리 버퍼나 캐시, SQL 파서, 옵티마이저 등을 통합시키면서 성능향상을 이뤄냈다. 이를 통해 5.0에 새롭게 적용되는 스토어드 프로시저, 트리거, 뷰, 커서 등과 같은 기능들이 스토리지 엔진과 상관없이 어떤 스토리지 엔진에서도 동작하게 되었으며 앞으로 계속적인 통합과 분리 작업을 통해 데이터베이스의 성능 향상이 모든 스토리지 엔진에 동일하게 이루어지게 될 것이다.

<그림 4> MySQL의 5.0의 아키텍처 구성도


새로운 Greedy 옵티마이저 사용
MySQL 5.0에서 새롭게 소개되는 greedy 옵티마이저의 적용을 통해 적절한 쿼리 실행 계획을 수립하기 위해 필요한 시간을 비약적으로 단축했다. 이 새로운 옵티마이저로 인한 성능의 향상은 특히 여러 테이블이 조인되며 적절한 조인 키를 찾을 수 없을 때 발휘된다. Greedy 옵티마이저가 사용되기 전에는 적절한 쿼리 실행 계획을 찾기 위한 복잡도는 조인되는 테이블의 개수를 N이라고 할 때 N!로 계산되었다. 하지만 Greedy 옵티마이저가 적용됨으로써 이를 N!/(D-1)로 줄일 수 있게 되었다(D는 검색의 깊이). 물론 Greedy 옵티마이저가 언제나 모든 쿼리 실행 계획에 최선의 결과를 보여주는 것은 아니라는 것을 감안하더라도 많은 테이블이 포함되는 조인의 경우 최대 1000에 가까운 경우의 수를 줄여주게 된다. 이를 통해 많은 테이블을 한번에 조인할 경우 때때로 서버 자체가 멈춘 것 같이 느껴지던 현상을 대부분 해결했다.

조건절 사용 시의 성능 향상
이전 버전까지는 AND나 OR을 통해 비교할 경우 같은 키를 사용해야만 쿼리가 최적화되었지만 인덱스 조합 기법을 사용함으로써 서로 다른 키를 사용하는 AND와 OR 비교 역시 쿼리 최적화가 이뤄지게 되었다. 또한 인덱스 조합 기법은 AND와 OR 뿐만 아니라 >, < 등과 같은 모든 1:1 비교에 적용되었다. 이를 통해 「WHERE key1 > 4 OR key2 < 7」와 같은 조건문과 「WHERE (key1 > 4 OR key2 < 7) AND (key3 >= 10 OR key4 = 1)」와 같은 쿼리에도 다중 인덱스를 사용해서 결과를 얻을 수 있게 되었다. 그리고 이전 버전에서 NOT IN 또는 NOT BETWEEN을 사용할 경우 테이블 스캔을 하게 됨으로써 많은 시간이 소모되었던 것과 달리 범위 분석을 통해 최적화가 가능해 짐으로써 이와 같은 조건절을 사용하는 쿼리 역시 IN과 BETWEEN을 사용하는 쿼리와 같은 수준으로 성능이 향상되었다.

플러그인 가능한 다중 스토리지 엔진 구조
MySQL의 가장 큰 장점이라면 바로 다중 스토리지 엔진 구조라고 할 수 있다. 물론 이전 버전까지도 여러 가지 스토리지 엔진을 이용할 수 있었지만 5.0 버전이 발표되면서 향상된 주요 기능 중 하나로 집중적으로 제시하고 있는데 이는 이번 버전에서 스토리지 엔진 자체의 기능과 그 외 데이터베이스 기능들을 제대로 분리하기 시작했기 때문이다. 현재 5.0 버전에서는 10개에 이르는 스토리지 엔진을 지원하며 2개의 스토리지 엔진이 새롭게 지원되기 시작했다. 이러한 다중 스토리지 엔진의 장점이라면 실제적인 데이터베이스 사용 용도에 맞게 스토리지 엔진을 선택하여 최선의 성능을 발휘할 수 있다는 점이다. 예를 들어 MyISAM 스토리지 엔진의 경우 트랜잭션이 필요하지 않고 2CPU, 2GB 이하의 작은 시스템에서 다른 스토리지 엔진에 비해 좋은 성능을 보여주며 InnoDB의 경우 트랜잭션이 많고 쓰기 관련 작업이 많은 데이터베이스에서 그리고 CPU와 메모리가 많은 시스템에서 가장 좋은 성능을 발휘한다.

그리고 5.0에 새롭게 도입된 아카이브 스토리지 엔진의 경우 엔진 자체가 데이터를 실제 크기의 20% 정도로 자동으로 압축하여 주며 매우 빠른 INSERT 속도를 보임으로써 로그성 데이터의 처리에 최적화되어 있다. 다중 스토리지 엔진 구조의 또 하나의 장점은 사용중인 데이터베이스를 용도에 따라 다른 스토리지 엔진으로 간단히 변경할 수 있다는 점이다. 한 번 스토리지 엔진이 정해지면 계속 해당 스토리지 엔진만을 사용해야 하는 것이 아니라 예를 들어 처음 데이터를 쌓을 때는 InnoDB 엔진을 사용했다가 일정 기간이 지난 후에는 보관을 위해서 아카이브 스토리지 엔진으로 Alter Table 명령 한 번으로 변경할 수 있다는 것이다. 그리고 하나의 데이터베이스 내에서도 테이블의 용도에 따라 여러 스토리지 엔진을 혼용하는 것 역시 가능하다. 이와 같이 다중 스토리지 엔진 구조를 잘 활용하면 현재 가진 시스템 자원을 최적화하여 목적에 맞는 데이터베이스를 구축할 수 있다.

InnoDB 스토리지 엔진의 향상
이번 벤치마크 테스트에서도 확인할 수 있었지만 MySQL 5.0 버전에서는 InnoDB 스토리지 엔진에 대해 많은 향상이 이뤄졌다. 무엇보다 InnoDB 스토리지 엔진의 코드 자체를 50% 이상 새롭게 작성하며 스토리지 엔진 자체를 최적화해서 성능을 10% 이상 높였으며, 그 동안 다른 스토리지 엔진에 비해 떨어지던 데이터 저장 효율을 높임으로써 기존 3.X나 4.X 버전의 InnoDB 데이터를 5.0으로 마이그레이션하는 것 만으로 총 데이터 저장 공간을 15~20% 정도 절약할 수 있게 되었다. 또한 내부 저장 알고리즘 개선을 통해 다른 데이터베이스에서 많은 DBA들의 고민거리인 스토리지 재구성 작업이 사라지게 되었다. 그리고 데드락 시 락을 트래킹하는 범위를 200회로 제한함으로써 이전 버전에서 데드락 자동복구를 위해 락을 트래킹하는 도중에 메모리 부족으로 종종 발생하던 서버가 멈추는 현상을 제거했다. 기본적으로 지원되던 B-Tree 인덱스 외에 클러스터 인덱스를 지원하여 클러스터 인덱스가 적용될 경우에는 10배 이상의 속도를 향상시킬 수 있다.

용도에 맞는 데이터베이스의 사용
필자가 MySQL에 대해 설명할 경우 많은 사용자들이 다른 데이터베이스와 기능을 1:1로 비교하고 싶어하며, 성능도 1:1의 절대적 비교를 원하곤 한다. 하지만 필자는 꼭 필요한 경우가 아니면 다른 데이터베이스와의 직접적인 비교를 삼가한다. 많은 경우 실제로 필요한 기능이 아님에도 불구하고 기능이 많으면 많을수록 좋은 게 아니냐는 식의 비교가 될 경우가 있기 때문이다. 물론 사람의 욕심이라는 것이 가능하다면 더 많은 것을 원하는 것이 당연하겠지만 물건을 구입할 때도 마찬가지듯이 현재 자신이 필요한 용도와는 상관없이 욕심을 내는 경우 낭비가 이뤄지게 되는 것이 사실이다. MySQL 역시 아직 모자라는 부분이 많다. 하지만 사용할 데이터베이스의 용도를 확실히 정하고 그에 맞게 사용된다면 비용 절감과 성능향상이라는 두 마리 토끼를 잡을 수 있을 것이라 믿는다.

[MySQL 5.0 최신 성능 관리팁] 커스텀 빌드로 최적의 성능 끌어내기

최적의 빌드로 최선의 성능을
MySQL을 있는 그대로 사용하는 것과 기본적인 튜닝을 하는 것은 최소 25%에서 많은 경우 75% 이상의 성능 차이를 보인다. MySQL을 사용하면서 기본적으로 할 수 있는 성능향상 팁들에 대해 간략하게 알아보자.

MySQL 컴파일하기
이번 벤치마크에서도 최고의 성능을 낸 것은 커스텀 빌드된 MySQL이였다. 물론 기본적으로 제공되는 바이너리 버전 역시 안정성이 고려되는 범위 내에서 최선의 성능을 낼 수 있도록 컴파일되어 있다. 하지만 아무래도 안정성을 먼저 고려하기 때문에 GCC의 경우 아직 2.9대를 사용하고 있으며, 기본적인 기능도 모두 포함시켜서 컴파일하게 된다. 현재 출시되는 레드햇 리눅스의 경우 GCC 3.4 버전 이상을 사용하고 있고, 이와 같이 높은 GCC 버전에서 적절히 컴파일될 경우 더 나은 성능을 나타내게 된다. 그리고 사용자에게 필요 없는 기능은 제외하고 컴파일 함으로써 성능 향상을 꾀할 수 있다. 다음은 이번 벤치마크에 사용된 컴파일 옵션이다. 물론 이는 제온 CPU에 최적화 된 옵션이므로 다른 플랫폼에서는 차이가 날 수 있다. 플랫폼 별 옵션에 대해서는 바이너리 버전을 다운받은 압축 파일 내에 bin 디렉토리의 mysqlbug라는 파일을 확인하면 바이너리 버전을 컴파일할 때 사용한 컴파일 옵션을 확인할 수 있다.

CFLAGS="-g -O3 -fno-omit-frame-pointer " CXX="gcc" CXXFLAGS=" -g -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer" CXXLDFLAGS="" \ ./configure --prefix=/usr/local/mysql \ --enable-assembler \ --with-extra-charsets=complex \ --enable-thread-safe-client \ --with-readline \ --with-big-tables \ --enable-local-infile

MySQL의 기본 설정 파일 셋팅하기
MySQL을 설치하고 난 후 mysql 디렉토리 내에 support-files이라는 디렉토리를 보면 MySQL에 할당할 수 있는메모리 양에 맞춘 추천 configuration 파일이 5개 존재한다. my-small, medium, large, huge, innodb-heavy-4G 이렇게 5개 파일이 있으며 각각은 64MB 이하, 128MB 이하, 512MB 이하, 2GB 이하, 4GB 이하를 위해 제공되며 이 중 innodb-heavy-4G를 제외한 나머지 4개 파일은 MyISAM만을 사용하는 것을 기본으로 제공되고 있다. 물론 이 기본 설정 파일들은 시스템에서 MySQL을 메인으로 사용한다는 것을 전제하고 있기 때문에 다른 애플리케이션의 비중이 더 클 경우 MySQL에 어느 정도 메모리를 할당할 수 있을지를 먼저 결정해야 한다. MyISAM과 InnoDB를 모두 사용할 경우 앞에서 이야기한 메모리 양의 두 배가 필요하므로 주의해야 한다. 이 중 사용자가 할당 가능한 메모리 양에 맞는 cnf 파일을 선택하여 유닉스 계열인 경우 /etc/my.cnf로 이름을 변경하여 옮겨 놓으면 기본적인 셋팅은 마무리된다. InnoDB만 사용할 경우 innodb-heavy-4G가 매우 잘 설정된 설정파일의 예제이므로 이를 자신이 사용할 메모리 양에 맞게 비율을 맞춰 줄여주는 것도 좋은 방법이다. 물론 사용자의 데이터베이스 사용용도에 딱 맞춘 튜닝을 위해서는 추가적인 모니터링 작업과 튜닝작업이 필요하지만 기본 셋팅만 잘 해 놓아도 하지 않는 것에 비해 15% 이상의 성능향상이 가능하므로 반드시 설정 파일 셋팅을 가장 먼저 신경쓰도록 하자.

2006/09/08 10:44 2006/09/08 10:44
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 쉼터
원본 http://blog.naver.com/purume2000/110002019159
  • 프라이머리 키는 짧은 것을 사용한다. 테이블 조인할 때는 문자열형 보다는 숫치형을 사용한다.
  • 여러 부분으로 구성된 키를 사용할 때는 첫 번째 부분이 가장 많이 사용되는 키이어야 한다.
  • 의심스러울 때는, 앞부분이 더 많이 중복된 컬럼을 사용해서 보다 나은 키 압축 효과를 얻는다.
  • 클라이언트를 실행 중이고 MySQL 서버가 같은 머신에 있다면, TCP/IP 대신에 유닉스 소켓을 사용하여 서버에 연결하는 것이 좋다.(이렇게 하면 7.5% 정도까지 효율이 증진된다.) MySQL 서버에 접속할 때 호스트이름이나 localhost를 지정하지 않으면 유닉스 소켓으로 접속하게 된다.
  • 가능하다면 --skip-locking(일부 운영체제에서는 이 것이 기본값이다)을 사용한다. 이는 외부적인 잠금을 사용하지 않게 되고 퍼포먼스가 향상된다.
  • 긴 키를 사용하기 보다는 응용프로그램 수준에서 해시된 값을 사용한다.

    SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND col_1='constant' AND col_2='constant';


  • Store BLOB's that you need to access as files in files. 데이터베이스에는 파일이름만 저장한다.
  • 레코드들의 큰 부분을 지우는 것 보다 레코드 전체를 지우는 것이 더 빠르다.
  • SQL이 충분히 빠르지 않다면, 데이터에 접근하는 더 낮은 수준의 인터페이스를 점검해 본다
  • 2006/09/08 10:43 2006/09/08 10:43
    이 글에는 트랙백을 보낼 수 없습니다
    출처 블로그 > 쉼터
    원본 http://blog.naver.com/purume2000/110002594268

    mysql 로그 보기 (호스트명-bin.001 )

    /mysql/date/호스트명-bin.001

    호스트명-bin.001 파일을 볼려면 ..


    /usr/local/mysql/bin/mysqlbinlog -uroot -p암호 호스트명-bin.001

    파일내용을 보면 update , delete , insert 같은 문장이 실행된것을 볼수 있다


    http://sir.co.kr/bbs/board.php?bo_table=pl_mysql&wr_id=31

    2006/09/08 10:42 2006/09/08 10:42
    이 글에는 트랙백을 보낼 수 없습니다
    http://blog.naver.com/zeldign/40024483673
    출처 블로그 > 햇살
    원본 http://blog.naver.com/nbshs/130003918355
    http://blog.naver.com/rosekingdom/60001322063
    mysql함수 [숫자열, 문자열, 집계, 날짜, 기타함수...]
    MySQL commands :
    Note that all text commands must be first on line and end with ';'
    help      (\h)    Display this help.
    ?            (\?)    Synonym for `help'.
    clear      (\c)    Clear command.
    connect (\r)    Reconnect to the server. Optional arguments are db and host.
    ego       (\G)    Send command to mysql server, display result vertically.
    exit       (\q)    Exit mysql. Same as quit.
    go         (\g)    Send command to mysql server.
    notee     (\t)    Don't write into outfile.
    print     (\p)    Print current command.
    quit       (\q)    Quit mysql.
    rehash   (\#)    Rebuild completion hash.
    source    (\.)    Execute a SQL script file. Takes a file name as an argument.
    status    (\s)    Get status information from the server.
    tee        (\T)    Set outfile [to_outfile]. Append everything into given outfile.
    use        (\u)    Use another database. Takes database name as argument.

    Connection id: 6 (Can be used with mysqladmin kill)

    MySQL 함수
    숫자 관련 함수
    ABS(숫자) : 절대값 출력.
       select abs(123);
    CEILING(숫자) : 값보다 큰 정수 중 가장 작은 수.
      --양수일 경우는 소숫점 자리에서 무조건 반올림(4.0과 같은 소숫점 자리 0 값은 제외)
      --음수일 경우는 소숫점 자리를 무조건 버림
       select ceiling(4.0);
       select ceiling(4.1);
       select ceiling(4.9);
    FLOOR(숫자) : 값보다 작은 정수 중 가장 큰 수[실수를 무조건 버림(음수일 경우는 제외)].
      --음수일 경우는 [.0/.00/.000/...] 을 제외하고 무조건 소숫점을 버리고 반내림(?)
       select floor(4.0);
       select floor(4.1);
       select floor(4.9);
       select floor(-4.6789);
    ROUND(숫자,자릿수) : 숫자를 소수점 이하 자릿수에서 반올림.(자릿수는 양수,0,음수를 갖을 수 있다.)
       --자릿수를 생략하면 소숫점이 5 이상일 때 반올림/자릿수를 지정하면 지정한 자리수에서 반올림
       select round(4.5);
       select round(4.55);
       select round(-4.5);
       select round(4.556);
       select round(4.556,0);
       select round(4.556,1);
       select round(4.556,2);
       select round(45.556,-1);
       select round(455.556,-2);
    TRUNCATE(숫자,자릿수) : 숫자를 소수점 이하 자릿수에서 버림.
      ==>만일 자릿수를 소숫점 이전으로 정하면 소숫점이하는 버리고 나머지 값은 0 값으로 처리
         / 예) truncate(9999,-3) --> 9000
      ==>또는 자릿수를 소숫점이하로 정하며, 해당숫자가 자릿수보다 소숫점이 모자랄경우 0 값으로 대치
         / 예) truncate(999,3) --> 999.000
      --반드시 자릿수를 명시해주어야 한다
      --음수일 경우는 해당자릿수에서 소숫점을 버리면서 무조건 반올림
      ==>(자릿수 숫자에서 이후 숫자가 0 일 경우는 제외 / 예)-4.0,0/-400,-2/-4.1230,4)
      ==>음수 역시 자릿수를 소숫점이하로 정하며, 해당숫자가 자릿수보다 소숫점이 모자랄경우 0 값으로 대치
      ==>또한 자릿수를 소숫점 이전으로 정하면 소숫점이하는 버리고 나머지 값은 역시 0 값으로 처리
    POW(X,Y) 또는 POWER(X,Y) : XY
      --소숫점이 있는 경우도 실행, 단 음수는 양수로 승처리
      select pow(-2.5,2);
      select pow(1.5,2);
    MOD (분자, 분모) : 분자를 분모로 나눈 나머지를 구한다.(연산자 %와 같음)
      select mod(12,5);    ==> 2
      select 12%5;           ==> 2
    GREATEST(숫자1,숫자2,숫자3...) : 주어진 수 중 제일 큰 수 리턴.
      select greatest(100,101,90);
    LEAST(숫자1,숫자2,숫자3...) : 주어진 수 중 제일 작은 수 리턴.
      select least(100,101,90);
    INTERVAL(a,b,c,d.....) : a(숫자)의 위치 반환
      --두 번째 이후는 오름차순 정렬이 되어야 함
      예) INTERVAL(5,2,4,6,8) ==> 2
           5는 4와 6사이에 존재, 4~6사이의 위치가 앞에서 2번째
      select interval(4,1,2,3,5,6);
    문자 관련 함수
    ASCII(문자) : 문자의 아스키 코드값 리턴.
      SELECT ASCII('문자');
      select ascii('A');
    CONCAT('문자열1','문자열2','문자열3'...) : 문자열들을 이어준다.
      select concat('ASP,','PHP,','SQL',' WEB STUDY');
    INSERT('문자열','시작위치','길이','새로운문자열') : 문자열의 시작위치부터 길이만큼 새로운 문자열로 대치
      '시작위치' 와 '길이'는 문자열이 아니므로 작은따옴표로 굳이 묶어주지 않아도 된다.
      select insert('MySql web study','7','3','offline');
      select insert('MySql web study',7,3,'offline');
    REPLACE('문자열','기존문자열','바뀔문자열') : 문자열 중 기존문자열을 바뀔 문자열로 바꾼다.
      select replace('MySql web study','web','offline');
    INSTR('문자열','찾는문자열') : 문자열 중 찾는 문자열의 위치값을 출력
      --값이 존재하지 않으면 0값 리턴
      select instr('MySql web study','s');
      select instr('MySql web study','S');
    LEFT('문자열',개수) : 문자열 중 왼쪽에서 개수만큼을 추출.
      select left('MySql web study',5);
      select left('MySql web study','5');
    RIGHT('문자열',개수) : 문자열 중 오른쪽에서 개수만큼을 추출.
      select right('MySql web study',5);
      select right('MySql web study','5');
    MID('문자열',시작위치,개수) : 문자열 중 시작위치부터 개수만큼 출력
      select mid('MySql web study',7,3);
      select mid('MySql web study','7','3');
    SUBSTRING('문자열',시작위치,개수) : 문자열 중 시작위치부터 개수만큼 출력
      select substring('Mysql web study',11,5);
      select substring('Mysql web study','11','5');
    LTRIM('문자열') : 문자열 중 왼쪽의 공백을 없앤다.
      select ltrim('          web study');
    RTRIM('문자열') : 문자열 중 오른쪽의 공백을 없앤다.
      select rtrim('web study          ');
    TRIM('문자열') : 양쪽 모두의 공백을 없앤다.
      select trim('     web study      ');
    LCASE('문자열') 또는 LOWER('문자열') : 소문자로 바꾼다.
      select lcase('MYSQL');
      select lower('MySQL');
    UCASE('문자열') 또는 UPPER('문자열') : 대문자로 바꾼다.
      select ucase('mySql');
      select upper('mysql');
    REVERSE('문자열') : 문자열을 반대로 나열한다.
      예) REVERSE('abcde') ==> edcba
      select reverse('lqSyM');
    논리 관련 함수, 집계함수
    --논리 관련 함수
    IF(논리식,참일 때 값,거짓일 때 값)
      논리식이 참이면 참일 때 값을 출력하고 논리식이 거짓이면 거짓일 때 출력한다.
    IFNULL(값1,값2)
    값1이 NULL 이면 값2로 대치하고 그렇지 않으면 값1을 출력

    --집계 함수
    COUNT(필드명)
      NULL 값이 아닌 레코드 수를 구한다.
    SUM(필드명)
      필드명의 합계를 구한다.
    AVG(필드명)
      각각의 그룹 안에서 필드명의 평균값을 구한다.
    MAX(필드명)
      최대값을 구한다.
    MIN(필드명)
      최소값을 구한다.
    날짜 관련 함수
    NOW() 또는 SYSDATE() 또는 CURRENT_TIMESTAMP()
      현재 날짜와 시간 출력
      ※ 함수의 상황이 숫자인지 문자열인지에 따라
         YYYYMMDDHHMMSS 또는
         'YYYY-MM-DD HH:MM:SS' 형식으로 반환한다.
      예)
      select now();
      ==> '2001-05-07 09:10:10'
      select now() + 0;
      ==> 20010507091010
    CURDATE() 또는 CURRENT_DATE()
      현재 날짜 출력
      ※ 함수의 상황이 숫자인지 문자열인지에 따라
         YYYYMMDD 또는
         'YYYY-MM-DD 형식으로 반환한다.
      예)
      select curdate();
      ==> '2001-05-07'
      select curdate() + 0;
      ==> 20010507
    CURTIME() 또는 CURRENT_TIME()
      현재 시간 출력
      ※ 함수의 상황이 숫자인지 문자열인지에 따라
      HHMMSS 또는 'HH:MM:SS' 형식으로 반환한다.
      예)
      select curtime();
      ==> '09:10:10'
      select curtime() + 0;
      ==> 091010
    DATE_ADD(날짜,INTERVAL 기준값)
      날짜에서 기준값 만큼 더한다.
    ※ 기준값 : YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
      예)
      select date_add(now(), interval 2 day);
      ==> 오늘보다 2일 후의 날짜와 시간 출력.
      select date_add(curdate(), interval 2 day);
      ==> 오늘보다 2일 후의 날짜 출력.
    DATE_SUB(날짜,INTERVAL 기준값)
      날짜에서 기준값 만큼 뺸다.
    ※ 기준값 : YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
      select date_sub(now(),interval 2 day);
      ==> 오늘보다 2일 전의 날짜와 시간 출력.
      select date_sub(curdate(), interval 2 day);
      ==> 오늘보다 2일 전의 날짜 출력.
    YEAR(날짜) : 날짜의 연도 출력.
      select year('20000101');
      select year(20000101);
      select year('2000-01-01');
      select year(now());
      select year(curdate());
      select year(date_add(now(),interval 2 year));
      select year(date_sub(curdate(),interval 2 year));

    MONTH(날짜) : 날짜의 월 출력.
      select month('20001231');
      select month(20001231);
      select month('2000-12-31');
      select month(now());
      select month(curdate());
      select month(date_add(now(),interval 2 month));
      select month(date_sub(curdate(),interval 2 month));

    MONTHNAME(날짜) : 날짜의 월을 영어로 출력.
      select monthname(20021221);
      select monthname('20000721');
      select monthname('2000-08-10');
      select monthname(now());
      select monthname(curdate());
      select monthname(date_add(now(),interval 17 month));
      select monthname(date_sub(curdate(),interval 11 month));

    DAYNAME(날짜) : 날짜의 요일일 영어로 출력.
      select dayname(20000121);
      select dayname('20010123');
      select dayname('2001-06-22');
      select dayname(now());
      select dayname(curdate());
      select dayname(date_add(now(),interval 21 day));
      select dayname(date_sub(curdate(),interval 333 day));

    DAYOFMONTH(날짜) : 날짜의 월별 일자 출력.
      select dayofmonth(20030112);
      select dayofmonth('20011231');
      select dayofmonth('2001-12-23');
      select dayofmonth(now());
      select dayofmonth(curdate());
      select dayofmonth(date_add(now(),interval 56 day));
      select dayofmonth(date_sub(curdate(),interval 33 day));

    DAYOFWEEK(날짜) : 날짜의 주별 일자 출력(월요일(0),화요일(1)...일요일(6))
      select dayofweek(20011209);
      select dayofweek('20001212');
      select dayofweek('2003-03-21');
      select dayofweek(now());
      select dayofweek(curdate());
      select dayofweek(date_add(now(),interval 23 day));
      select dayofweek(date_sub(curdate(),interval 31 day));

    WEEKDAY(날짜) : 날짜의 주별 일자 출력(월요일(0),화요일(1)...일요일(6))
      select weekday(20000101);
      select weekday('20030223');
      select weekday('2002-10-26');
      select weekday(now());
      select weekday(curdate());
      select weekday(date_add(now(),interval 23 day));
      select weekday(date_sub(curdate(),interval 33 day));

    DAYOFYEAR(날짜) : 일년을 기준으로 한 날짜까지의 날 수.
      select dayofyear(20020724);
      select dayofyear('20001231');
      select dayofyear('2002-01-01');
      select dayofyear(now());
      select dayofyear(curdate());
      select dayofyear(date_add(curdate(),interval 44 year));
      select dayofyear(date_sub(now(),interval 25 month));
      select dayofyear(date_add(now(),interval 55 day));
      select dayofyear(date_sub(curdate(),interval 777 hour));
      select dayofyear(date_add(now(),interval 999999 minute));

    WEEK(날짜) : 일년 중 몇 번쨰 주.
      select week(now());
      select week(date_sub(curdate(),interval 12 month));

    FROM_DAYS(날 수)
      --00년 00월 00일부터 날 수 만큼 경과한 날의 날짜 출력.
         ※ 날 수는 366 이상을 입력 그 이하는 무조건 '0000-00-00' 으로 출력.
      --또한 9999-12-31 [from_days(3652424)] 까지의 날짜가 출력가능 하다고는 하나
         정확히 말하면 0000-03-15 [from_days(3652499)] 까지의 날짜가 출력가능함.
      --따라서 날 수는 366 이상 3652424[3652499] 이하가 되어야 한다.
      select from_days(3652424);
      select from_days('3652499');

    TO_DAYS(날짜)
      --00 년 00 월 00일 부터 날짜까지의 일자 수 출력.
      --from_days와 비교해 볼 때 정확한 날짜범위는 3652424 일 수 까지임을 알 수 있다.
      select to_days('99991231');
      select to_days('0000-03-15');
      응용 예제1) 자신이 살아 온 날수
      select to_days(now()) - to_days('본인생일자');
      select to_days(now()) - to_days('1970-10-10');
      응용 예제2) 살아 온 날수를 이용하여 자신의 나이를 만으로 구하기
      select (to_days(now())-to_days('1970-10-10'))/365;
      select floor((to_days(now())-to_days('19701010'))/365);

    DATE_FORMAT(날짜,'형식') : 날짜를 형식에 맞게 출력
    DATE타입구분기호설명구분기호설명
    년도%Y4자리 연도%y2자리 년도
    %M
    %b
    긴 월 이름 (January, ...)
    짧은 월 이름(Jan, ...)
    %m
    %c
    숫자의 월 (01...12)
    숫자의 월 (1...12)
    요일%W긴 요일 이름 (Sunday, ...)%a짧은 요일 이름 (Sun, ...)
    %D
    %w
    월 내에서 서수 형식의 일(1th, ...)
    숫자의 요일 (0=Sunday, ...)
    %d
    %e
    %j
    월 내의 일자 (01...31)
    월 내의 일자 (1...31)
    일년 중의 날수 (001...366)
    %l
    %h
    %I
    12시간제의 시 (1...12)
    12시간제의 시 (01...12)
    12시간제의 시 (01...12)
    %k
    %H
    12시간제의 시 (0...23)
    12시간제의 시 (00...23)
    %i숫자의 분 (00...59)
    %S숫자의 초 (00...59)%s숫자의 초 (00...59)
    시간%r12시간제의 시간 (hh:mm:ss AM 또는 PM)%T24시간제의 시간 (hh:mm:ss)
    %U일요일을 기준으로 한 주 (0...52)%u월요일을 기준으로 한 주 (0...52)
    기타%%문자 '%'%pAM 또는 PM

      ☞ 예)
      select date_format(now(),'%Y:%M:%p');
      ==> 2001:May:PM

    ▶ DATABASE() : 현재의 데이터베이스 이름을 출력한다.

    ▶ PASSWORD('문자열')
    : 문자열을 암호화한다.

    ▶ FORMAT(숫자,소수이하자리수) : 숫자를 #,###,###.## 형식으로 출력
      --임의의 소수점자릿수를 생성한다./소숫점을 필요한 만큼 취한다.
      --소숫점을 만들어 같은 길이로 한다음 동일하게 프로그램에서 불러와서 소숫점을 버리고
         필요한 곳에 출력하는 등에 응용할 수 있다.
      select format(123,5);
      select format(123.12345600123,9);
      select format(123.123,-3);
      ※ 소숫점이하자리수가 0 이나 음수값은 해당이 안됨
    2006/09/08 10:42 2006/09/08 10:42
    이 글에는 트랙백을 보낼 수 없습니다
    출처 블로그 > 울보천사의 블로그
    원본 http://blog.naver.com/mirckorea/30007500571

    본 자료는 제 개인 홈페이지(http://mirckorea.net)에서 사용하기 위해 만들었습니다.

    본 자료는 양력 1841년 1월 1일 부터 2110년 12월 31일까지의 양력,음력,절기,간지(년,일),띠, 요일,한식,삼복(초복,중복,말복), 국경일, 기념일을 MySQL DB 자료로 만든것입니다.

    처음 계획은 2200년까지 입력하는 것이었으나, 직접 입력하다보니 너무 힘들어서 2110년까지만 입력했습니다.

    본 자료는 슈퍼개발님이 공개하신 DB 자료를 사용하다가 필요한 정보(절기,복날등)가 부족하여,
    슈퍼개발님의 DB를 사용하는 분들이 참고하기 쉽도록 필드 이름을 참고하여 직접 다시 만들었습니다.

    1900년~2100까지의 음력 날짜 및 요일 및 절기는 중국 사이트 의 정보를 참고했습니다.
    (제일 뒤에 숫자 년도를 바꾸면 2100년까지의 음력 정보를 알 수 있습니다.)

    1841년 1월 1일~1899년 12월 31일, 2100년 1월 1일~2110년 12월 31일까지의 음력 정보는 고영창님의 진짜만세력을 참고했습니다.

    24절기 및 한식/삼복(초복,중복,말복)은 진짜 만세력을 기초로 DB에 직접 입력했습니다.

    국경일/기념일/음력 절의 날짜/한식, 삼복 계산법은 네이버에 공개된 자료를 참고했습니다.

    cd_no 시퀀스
    cd_sgi 단기년도
    cd_sy 양력의 년
    cd_sm 양력의 월
    cd_sd 양력의 일
    cd_ly 음력의 년
    cd_lm 음력의 월
    cd_ld 음력의 일
    cd_hyganjee 년을 기준으로 한문간지
    cd_kyganjee 년을 기준으로 한글간지
    cd_hdganjee 일을 기준으로 한문간지
    cd_kdganjee 일을 기준으로 한글간지
    cd_hterms 한문 절기
    cd_kterms 한글 절기
    cd_week 요일(월.화.수.목.금.토.일)
    cd_sol_plan 양력의 지정된 행사(국경일/기념일 등)
    cd_lun_plan 음력의 지정된 행사(절/한식 등)
    cd_dogday 복날 정보(초복/중복/말복)
    cd_ddi 띠(쥐.소.호랑이..... 돼지)
    cd_kk 윤달 정보(윤달 1, 평달 0)
    holiday 기념일(국경일 1,법정공휴일 2, 국가공인기념일? 3, 기타 기념일 4, 음력절 5)

    holiday 숫자는 국경일부터 PhpMyAdmin에서
    UPDATE calenda_data SET `cd_sol_plan`= '신정',`holiday`='2' where cd_sm='1' and cd_sd='1'
    쿼리로 넣었는데 해당 날짜에 기념일 및 음력절등이 중복되었을 경우 누락되거나 덮어씌워졌을 수 있습니다. 국경일, 기념일 및 음력 절등을 수정하시려면 위의 쿼리를 참고해서 실행하십시오.

    기념일 숫자는 그리 중요하지 않습니다.
    국경일 및 법정 공유일을 달력에 빨간 글씨로 표시하기 위해서 적용한 것 뿐이므로, 해당 날짜에 기념일(양력(cd_sol_plan)/음력(cd_lun_plan)), 복날정보가 Null 값이 아닌지 검사해서 불러와서 달력에 뿌려주게 하면 될거라 생각합니다.

    cd_sol_plan, cd_lun_plan, cd_dogday 값을 불러와서 하나의 변수로 합쳐서 달력에 뿌려주면 될 것이라 생각합니다.

    한식은 동지(冬至)부터 105일째 되는 날로 계산되었으며, 초복,중복,말복 또한 절기를 기초로 계산해서 추가했습니다.

    음력 년도(간지)는 사주를 볼 때는 입춘을 기준으로 변경되지만, 통상 음력 1월 1일을 기준으로 사용하기 때문에 음력 1월 1일을 기준으로 적용하였습니다.

    월간(월건) 및 일진은 제가 계산하는 방법을 잘 몰라서 입력하지 못했습니다. 워찌나 복잡하던지...

    또 한가지 이유로는 월간을 정확하게 적용하려면 입춘을 기준으로 간지(년)를 입력하고, 입춘을 기준으로 입력된 간지를 바탕으로 월건이 다시 계산되기 때문에, 만세력이 필요한 사이트나 사주 사이트가 아닌 일반 홈페이지에서 입춘을 기준으로 간지를 적용한 음력 달력을 보여줄 경우 혼돈을 줄 수 있을 것 같아서 통상적으로 음력 1월 1일에 간지가 빠뀌도록 사용하므로, 월건을 입력하지 않았습니다.

    DB에 자료를 넣을실 때는...
    mysql -u[아이디] -p[비밀번호] DB이름 > 20060811.sql

    SQL 자료가 15Mb정도 됩니다. DB에 입력할 경우 약 8,645Kb 정도 되는 것 같습니다. DB 용량에 제한이 있는 분은 필요한 만큼 잘라서 사용하십시오.  (cd_no 다시 정의해 줘야겠죠?)

    많은 음력 자료와 절기 정보등을 만세력을 보면서 직접 입력하였는데, 제가 입력하다가 잠시 졸았을 경우.. 음력 날짜 및 절기에 오류가 있을 수 있습니다. 하지만 진짜 만세력과 맞을꺼라 생각합니다. 혹시나 한 두 곳 틀릴 수도 있습니다. (년도 간지의 경우 만세력은 입춘을 기준으로 하고 본 자료는 음력 1월 1일을 기준으로 적용했기 때문에 다릅니다. 태클 걸어오면 대략 난감하옵니다.)

    기타 참고사이트: http://inkull.myi.cc/in26-2.html 
    네이버 지식인

    ※ 본 자료는 참고한 사이트의 정보를 기초로 했으므로, 오차가 있을 수 있습니다.
    ※ 본 자료는 UTF8 형식입니다. MySQL이 UTF8이 아닐 경우 울트라에디터등으로 변환해서 사용하십시오.

    2006/09/08 10:40 2006/09/08 10:40
    이 글에는 트랙백을 보낼 수 없습니다
    Fedora Core 4에서. 꼭. mysql 4.0.X 설치시 "LinuxThreads"... "Not found" ... 에러


    /usr/include/pthread.h

    파일에

    /* Linuxthreads */

    한줄 추가하면 끝!


    원인
    ; mysql configure 과정에서 pthread.h 파일을 찾아 위 문구가 있는지 조사하게 되는데
      Fedora Core 4의 glibc는 '/* Linuxthreads */' 가 없어 발생하는 에러.. 
    2006/09/08 10:39 2006/09/08 10:39
    이 글에는 트랙백을 보낼 수 없습니다
    웅쓰:웅자의 상상플러스
    웅자의 상상플러스
    전체 (379)
    게임 (5)
    영화 (2)
    기타 (23)
    맛집 (5)
    영어 (2)
    대수학 (3)
    형태소 (5)
    Hacking (9)
    Linux (112)
    HTML (48)
    Application_developing (48)
    Web_developing (102)
    Window (11)
    «   2024/05   »
          1 2 3 4
    5 6 7 8 9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 31  
    1. 2016/01 (1)
    2. 2015/12 (3)
    3. 2015/10 (3)
    4. 2015/03 (2)
    5. 2015/01 (4)