14.3.1 START 트랜잭션이 COMMIT 및 ROLLBACK 구문

START 거래
    [ transaction_characteristic[, transaction_characteristic] ...]

transaction_characteristic:
    일관성 스냅 샷
  | 읽기 쓰기
  | 읽기 전용

[WORK]를 BEGIN
COMMIT [WORK]와 [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK]와 [NO] CHAIN] [[NO] RELEASE] 없습니다
SET의 자동 커밋 = {0 | 1}

이 문은 사용을 제어 제공하는  거래를 :

  • START TRANSACTION 또는  BEGIN 새 트랜잭션을 시작합니다.

  • COMMIT 그 변경 사항을 영구적하고, 현재의 트랜잭션 (transaction)을 범했습니다.

  • ROLLBACK 롤의 변경을 취소, 현재의 트랜잭션 (transaction)를 백업합니다.

  • SET autocommit 비활성화 또는 현재 세션에 대한 기본 자동 커밋 모드를 가능하게한다.

기본적으로 MySQL은 실행됩니다  자동 커밋  활성화 모드. 이것은 바로 디스크에 대한 업데이트 (수정) 테이블, MySQL의 저장 업데이트가 영구적으로하는 문을 실행으로 있다는 것을 의미한다. 변화는 롤백 할 수 없습니다.

문 하나의 시리즈에 대한 암시 적으로 자동 커밋 모드를 해제하려면 사용  START TRANSACTION 문 :

트랜잭션을 시작;
SELECT @A가 : 표 FROM SUM (급여) = WHERE 유형 = 1;
UPDATE 표 2 SET 요약 = @ WHERE 유형 = 1;
범하다;

으로  START TRANSACTION당신과 거래를 종료 할 때까지, 자동 커밋이 비활성화 된 상태로 남아 COMMIT 나  ROLLBACK. 자동 커밋 모드는 이전 상태로 되돌아갑니다.

START TRANSACTION 트랜잭션 특성을 제어하는 ​​여러 가지 개질제를 허용한다. 여러 수식을 지정하려면 쉼표로 구분합니다.

  • WITH CONSISTENT SNAPSHOT 수정은 시작  일관된 읽기  그것을 할 수있는 스토리지 엔진을. 이 경우에만 적용됩니다  InnoDB. 효과는 발행과 동일  START TRANSACTION a로 다음을 SELECT 어떤에서  InnoDB 테이블. 참조  절 15.5.2.3를, "일관된 Nonlocking 읽고" . WITH CONSISTENT SNAPSHOT 수정은 현재의 트랜잭션 (transaction) 변경되지 않는  격리 수준을 , 그래서 현재 격리 수준이 일관된 읽기를 허용 한 경우에만이 일관된 스냅 샷을 제공합니다. 일관된 읽기를 허용하는 유일한 격리 수준이다  REPEATABLE READ. 다른 분리 레벨의 경우,  WITH CONSISTENT SNAPSHOT절은 무시됩니다. 때 MySQL은 5.7.2로, 경고가 생성됩니다  WITH CONSISTENT SNAPSHOT 절이 무시됩니다.

  • READ WRITE 및  READ ONLY 수정 트랜잭션 액세스 모드를 설정합니다. 그들은 허용하거나 트랜잭션에 사용되는 테이블에 대한 변경을 금지합니다. READ ONLY제한은 수정하거나 다른 트랜잭션에 볼 수 있습니다 모두 트랜잭션 및 비 트랜잭션 테이블 잠금에서 거래를 방지; 거래는 여전히 수정하거나 임시 테이블을 잠글 수 있습니다.

    MySQL은에 쿼리에 대한 별도의 최적화를 가능하게  InnoDB 트랜잭션이 읽기 전용으로 알려져있다 테이블. 지정은  READ ONLY 이러한 최적화가 읽기 전용 상태가 자동으로 판별 할 수없는 경우에 적용됩니다 보장합니다. 참조  섹션 9.5.3을, "최적화 InnoDB의 읽기 전용 거래" 더 많은 정보를 얻을 수 있습니다.

    접근 모드를 지정하지 않으면, 디폴트 모드가 적용된다. 기본이 변경되지 않는 한, 그것은 읽기 / 쓰기. 모두를 지정하는 것은 허용되지 않습니다  READ WRITE 과  READ ONLY 같은 성명에서.

    읽기 전용 모드에서, 그것은으로 만든 테이블을 변경할 수 남아  TEMPORARY DML 문을 사용하여 키워드를. DDL 문으로 변경은 영구 테이블로, 허용되지 않습니다.

    기본 모드를 변경하는 방법을 포함하여 트랜잭션 액세스 모드에 대한 자세한 내용은 다음을 참조 섹션 14.3.6, "SET 트랜잭션 구문"을 .

    경우  read_only 시스템 변수가 사용 가능으로, 명시 적으로 트랜잭션을 시작  START TRANSACTION READ WRITE 요구  SUPER 권한을.

중대한

(예 : JDBC 등) MySQL 클라이언트 응용 프로그램을 작성에 사용되는 대부분의 API는 (때로는한다) 대신에 보내는 사용할 수 있습니다 트랜잭션을 시작하는 자신의 방법을 제공하는  START TRANSACTION 클라이언트에서 문을. 참조  25 장,  커넥터 및 API에 대한 자세한 내용은, 당신의 API에 대한, 또는 문서를.

명시 적으로 자동 커밋 모드를 해제하려면 다음 문을 사용합니다 :

SET의 자동 커밋 = 0;

설정에 따라 자동 커밋 모드를 해제 한 후  autocommit 제로 변수 (예에 대한 것과 같은 트랜잭션 안전 테이블의 변경  InnoDB 또는  NDB) 즉시 영구적으로하지 않습니다. 당신은 사용해야  COMMIT 디스크에 변경 사항을 저장하거나  ROLLBACK 변경 사항을 무시.

autocommit 세션 변수이며, 각 세션에 대해 설정해야합니다. 각각의 새로운 연결을 위해 자동 커밋 모드를 사용하지 않으려면의 설명을 참조하십시오  autocommit에서 시스템 변수를  제 6.1.5, "서버 시스템 변수" .

BEGIN 과  BEGIN WORK 의 별칭으로 지원되는  START TRANSACTION 트랜잭션을 시작합니다. START TRANSACTION 표준 SQL 구문이고, 임시 트랜잭션을 시작하는 좋은 방법이며, 수정 허용 BEGIN 하지 않습니다.

BEGIN 문은 사용과 다른  BEGIN 시작 키워드  BEGIN ... END 화합물 문을. 후자는 트랜잭션을 시작하지 않습니다. 참조 섹션 14.6.1를, "BEGIN ... END 복합 문 구문" .

노트

저장된 모든 프로그램 (저장 프로 시저 및 함수, 트리거, 이벤트), 파서 취급 이내  BEGIN [WORK] (a)의 시작으로  BEGIN ... END 블록. 와이 컨텍스트에서 트랜잭션을 시작  START TRANSACTION 하는 대신.

옵션  WORK 키워드에 대한 지원  COMMIT 및  ROLLBACK한,  CHAIN 그리고  RELEASE 절을. CHAIN 및 RELEASE 거래 완료 추가 제어에 사용될 수있다. 의 값은  completion_type 시스템 변수는 기본 완료 동작을 결정합니다. 참조  섹션 6.1.5, "서버 시스템 변수"를 .

AND CHAIN 절은 현재 종료하자마자 시작 새로운 트랜잭션을 발생, 새로운 트랜잭션 방금 종료 트랜잭션과 같은 분리 레벨을 갖는다. RELEASE 절은 현재 트랜잭션을 종료 한 후 현재 클라이언트 세션을 분리하도록 서버를 발생합니다. 포함  NO 키워드를 억제  CHAIN 또는  RELEASE 경우에 유용 할 수 있습니다 완료,  completion_type 시스템 변수가 체인의 원인 또는 기본적으로 완료를 해제하도록 설정되어 있습니다.

트랜잭션을 시작하면 보류중인 트랜잭션이 커밋됩니다. 참조  섹션 14.3.3, "는 암시 적 커밋 원인 문" 자세한 내용을.

트랜잭션을 시작도 함께 획득 한 테이블 잠금이 발생  LOCK TABLES 하면 실행했던 것처럼, 발매 예정을  UNLOCK TABLES. 트랜잭션을 시작하기로 취득하는 글로벌 읽기 잠금을 해제하지 않습니다  FLUSH TABLES WITH READ LOCK.

최상의 결과를 얻으려면, 거래는 하나의 거래 안전 스토리지 엔진에 의해 관리 만 테이블을 사용하여 수행해야합니다. 그렇지 않으면, 다음과 같은 문제가 발생할 수있다 :

  • 둘 이상의 트랜잭션 안전 저장 엔진 (예에서 테이블을 사용하는 경우  InnoDB) 및 트랜잭션 격리 수준되지 않습니다  SERIALIZABLE, 하나의 트랜잭션이 커밋 할 때 같은 테이블을 사용하는 다른 지속적인 거래 만 일부 변경을 볼 가능성이있다 첫 번째 트랜잭션에 의해 만들어진. 즉, 트랜잭션의 원 자성이 혼합 된 엔진과 발생할 수 있습니다 일관성을 보증 할 수 없습니다. (혼합 엔진 트랜잭션이 빈번하지 않으면 사용할 수  SET TRANSACTION ISOLATION LEVEL 로 분리 레벨을 설정할  SERIALIZABLE 필요에 따라 트랜잭션 단위에서).

  • 당신이 트랜잭션 내에서 트랜잭션 안전하지 않은 테이블을 사용하는 경우, 해당 테이블의 변경에 관계없이 자동 커밋 모드의 상태를 한 번에 저장됩니다.

  • 당신이 실행하는 경우  ROLLBACK 트랜잭션 내에서 비 트랜잭션 테이블을 업데이트 한 후 문을 ER_WARNING_NOT_COMPLETE_ROLLBACK 경고가 발생합니다. 트랜잭션 안전 테이블에 대한 변경 사항은 nontransaction 안전 테이블에 대한 변경 사항을 롤백하지만되지 않습니다.

각 트랜잭션에, 한 덩어리에 바이너리 로그에 저장됩니다  COMMIT. 롤백 트랜잭션은 기록되지 않습니다. ( 예외 :. 비 트랜잭션 테이블에 대한 수정은 롤백 할 수 없습니다 롤백 트랜잭션이 비 트랜잭션 테이블에 대한 수정이 포함 된 경우, 전체 트랜잭션이 함께 기록됩니다  ROLLBACK비 트랜잭션 테이블에 대한 수정이 복제되도록 끝에 문.) 참조  섹션 6.4.4, "바이너리 로그" .

당신은와의 거래에 대한 격리 수준 또는 액세스 모드를 변경할 수 있습니다  SET TRANSACTION 문을.참조  섹션 14.3.6, "SET 트랜잭션 구문"을 .

위로 롤링 (오류가 발생하면, 예를 들어)을 명시 적으로 요청하는 데 사용하지 않고 암시 적으로 발생할 수있는 느린 동작 할 수있다. 이 때문에,  SHOW PROCESSLIST 표시  Rolling back 에서  State 세션의 열뿐만 아니라, 명시 적으로 수행 롤백 용  ROLLBACK 문장뿐만 아니라 내재 롤백 대한.


[MySQL] alter table 명령어

※ 경고
높이뜬새의 모르는 사람이 없는 팁시리즈 입니다.
이 팁시리즈는 지면낭비라는 항의시에 즉각 중단됩니다.


alter table 명령어는 모르시는 분이 없듯이 테이블의 스키마를 변경 할 수 있게 끔 해주는 아주 유용한 명령어입니다.
alter table 명령어가 없으면 아주 끔찍한 일이 벌어질 수도 있습니다. create table...과 drop table의 남발!! 정말 끔찍하지 않습니까? 그런데 테이블의 스키마가 무엇이냐구요? 

이것 역시 모르시는 분이 단 한사람도 없겠지만 쉽게 말해서 테이블의 구조라고 이해하시면 됩니다. 관계형 데이타베이스를 이용할려면 이놈들을 속성(attribute)들로 뭉쳐진 의미있는 정보의 단위로 이끌어 내야 하는데 이러한 것을 엔티티(Entity)라고 합니다. 정확히 말하면 이 엔티티의 구조를 설명한 게 스키마입니다! 이 스키마는 논리적 스키마와 물리적 스키마로 분리해서 부르는데 특정회사의 데이타베이스에 맞게 스키마를 표현하게 되면 물리적 스키마라고 부릅니다.
엔티티가 물리적 스키마에 의해서 실제 데이타베이스에 적용된 것이 테이블입니다. 더 자세한 사항은 시중에 나와 있는 데이타베이스 설계 관련 서적을 참고하세요! 없는 실력으로 더 자세한 설명은 도저히 무리입니다.^^

alter table 명령어는 각 회사의 데이타베이스에 따라서 약간씩 차이가 있습니다. 여기서는 제가 맨날 까먹는 alter table 명령어 중 MySQL 용 몇개를 오로지 안까먹기 위해서 적어둘려고 합니다. 사실 팁은 아닙니다.^^

일단 alter table 명령어를 쓰기 위해서 간단한 테이블을 하나 만들겠습니다. 테이블 이름은 mytable이고 컬럼은 id와 name만 가지고 있는 아주 간단한 예제용 테이블입니다.
 

mysql> create table mytable ( 
        ->id varchar(12) not null, 
        ->name varchar(20) not null );
 

아주 simple 하고 좋은데 id와 name외에 주소를 뜻하는 addr 컬럼을 추가해 봐야 하겠습니다.

[테이블에 새로운 컬럼 추가하기]

형식) alter table [테이블명] add column [추가할 컬럼명] [추가할 컬럼 데이타형]
 

mysql> alter table mytable add column addr varchar(70) not null;


뒤에 not null 을 안 붙이면 null 허용으로 컬럼이 추가됩니다. 위의 명령어에 의해서 addr 이라는 컬럼이 mytable에 추가 되었습니다. 그런데 주소를 뜻하는 addr 컬럼의 자릿수가 웬지 부족해 보입니다. varchar(100)으로 늘려봐야 겠습니다.

[테이블의 컬럼 타입 변경하기]

형식) alter table [테이블명] modify column [변경할 컬럼명] [변경할 컬럼 타입]
 

mysql> alter table mytable modify column addr varchar(100) not null;


desc mytable로 확인해 보면 addr 컬럼이 varchar(100)으로 정확하게 변경되었습니다.주소 컬럼에는 맞지 않겠지만 addr 컬럼을 int 형에 null 허용으로 변경해 보고 싶습니다.
 

mysql> alter table mytable modify column addr int;


desc mytable로 확인 해보니 int 형에 null 허용으로 변경되었습니다. 주소가 int 형이라니 말이 안됩니다. int 형이라면 아무래도 나이가 맞을 것 같습니다. addr의 컬럼명 자체를 age 로 바꿔야 겠습니다. 

[테이블의 컬럼 이름 변경하기] 

형식) alter table [테이블명] change column [기존 컬럼명] [변경할 컬럼명] [변경할 컬럼 타입]
 

mysql> alter table mytable change column addr age int not null;


addr 컬럼명이 age 라는 컬럼명으로 정확히 바뀌었습니다. 그치만 애초에 age 컬럼은 필요가 없었습니다. 테이블에서 age 컬럼을 삭제 해야 하겠습니다.

[테이블 컬럼 삭제하기]


형식) alter table [테이블명] drop column [삭제할 컬럼명]
 

mysql> alter table mytable drop column age;


desc mytable로 확인해보니 age 컬럼이 삭제되어져 있습니다. 뭔가 허전합니다. id 컬럼에 인덱스(Index)를 주면 허전함이 달래질 것 같습니다.

[테이블 컬럼에 인덱스 주기]

형식) alter table [테이블명] add index 인덱스명( 인덱스를 줄 컬럼1, 인덱스를 줄 컬럼2,...)
 

mysql> alter table mytable add index myindex( id );


위에서는 myindex 라는 인덱스명으로 id 컬럼에 index 가 추가되었습니다. 인덱스를 줄 컬럼을 한개 이상 써 넣으면 복수개의 컬럼에 대해서도 인덱스를 생성할 수 있습니다. 이번에는 id에 주어진 index 를 삭제해 보겠습니다.

[테이블 컬럼에 인덱스 삭제하기]


형식 ) alter table [테이블명] drop index 인덱스명
 

mysql> alter table mytable drop index myindex;


위에서는 처음에 줬던 index 인 myindex 를 삭제하고 있습니다. 참고로 인덱스를 확인하기 위해서는 아래의 명령어를 쓰시면 됩니다. mytable은 테이블 명입니다.
 

mysql> show index from mytable;


alter table로 인덱스도 추가하고, 날려봤는데 primary key 는 못 만들까요? 당연히 만들수 있습니다. 그대신 primary key 는 조건이 있습니다. primary key를 만들려는 컬럼에 조건이겠지요!!! 레코드에 값이 추가 안 되어있을 때는 괜찮지만, 값이 들어있다면 column 에 null 값이 들어 있는지, 중복된 값이 존재하는 column 인지를 따져봐야 합니다. null 값이 없고, 중복되는 column 이 없다면 primary key를 만들 수 있습니다.


[테이블에 primay key 만들기]


형식 ) alter table [테이블명] add primary key ( 키를 줄 column명1, 키를 줄 column명2, ... );
 

mysql> alter table mytable add primary key ( id );


위에서는 mytable의 id 컬럼에 primary key 를 만들고 있습니다. primary key 는 composite key 가 가능하므로 여러개의 column을 묶어서 primary key 로 사용할 수도 있습니다.


만들어진 primary key를 지워야 할 때도 있습니다.


[테이블에 primay key 삭제하기]

형식) alter table [테이블명] drop primary key;
 

mysql> alter table mytable drop primary key;


위에서는 mytable에 만들었던 primary key를 삭제하고 있습니다. 참고로 primary를 만들때는 index가 자동으로 primary key 컬럼에 추가됩니다.

primary key도 다시 날려버리고 아주 좋습니다. 마지막으로 테이블명을 변경해 보고 싶습니다. 사실 mytable이라는 테이블명이 아주 마음에 안 들었습니다.

[테이블 명 바꾸기]


형식) alter table [원본 테이블명] rename [새로운 테이블명];

mysql> alter table mytable rename utable;


alter table에 대해서 대충 알아 봤습니다. 그 유명한 다른 primary key를 뽀려온 foreign key 에 대한 부분도 정리 했으면 좋겠는데.. 오늘은 제 시간 관계 상 여기서 정리를 끝내겠습니다.

Mysql을 처음 설치할 때 database root 계정으로 사용할 password를 설정한다. 하지만 시간이 오래 지나서 그때 설정한 password를 기억할 수 없다면 다음의 방법으로 재설정할 수 있다. (Ubuntu 12.04 기준)

Step 1. 실행중인 mysql service를 중지 시킨다.

Step 2. Password를 검사하지 않도록 mysql 환경설정 파일을 수정한다.
: /etc/mysql/my.conf file에 skip-grant-tables를 추가하면 password를 검사하지 않는다.

Step 3. 새로운 설정 값으로 mysql service를 실행한다.

Step 4. root 계정으로 mysql database를 연다.

Step 5. root password를 재설정한다.

Step 6. my.conf를 복원하고 mysql service를 재실행 시킨다. 

MySQL에 root로 접속 한 뒤
use mysql;
select host,user from user;
현재 생성된 db의 사용자 계정들을 확인할 수 있다.

사용자 계정 생성
GRANT USAGE ON [database명].[table명] TO [user명]@[server명] IDENTIFIED BY [‘패스워드’];
ex) grant usage on database.* to user1@localhost identified by ‘user1’;

생성된 사용자 계정 권한 설정
GRANT ALL ON [database명].[table명] TO [user명]@[server명];    =>  모든 권한을 준다
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,ALTER ON [database명].[tabel명] TO [user명]@[server명];   => 특정 권한을 준다
ex) grant all on database.* to user1@localhost;
grant select,insert,update,delete,create,drop.index,alter on database.* to user1@localhost;

REVOKE ALL ON [database명].[table명] FROM [user명]@[server명];    =>  모든 권한을 삭제한다
REVOKE DROP ON [database명].[table명] FROM [user명]@[server명];    => 특정 권한(drop)을 삭제한다
ex) revoke all on database.* from user1@localhost;
revoke drop,index on database.* from user1@localhost;

계정 권한을 새로 로드
FLUSH PRIVILEGES;
flush privileges;

사용자 계정 삭제
DROP USER [user명]@[server명];
ex) drop user user1@localhost;


오늘은 mysql 설치시 사용자를 추가하는 방법에 대해 남겨볼까 한다. 할때마다 잘 기억이 안나서 검색엔진에 항상 의존을 하게 되는데 다음에는 검색엔진에 의존하지 않고 바로 블로그에서 검색해서 보면 좋을 듯 하다. 


사용자를 생성하는 방법은 여러가지가 있는데 아래 방법이 가장 쉽고 심플하다. 다른 방법들은 쿼리문을 직접 던져야 하기 때문에 솔직히 말해서 좀 불편하다. 혹시나 오랜만에 해 보거나 처음해 보는 사람들을 위해서 서버에 mysql을 설치한 후 mysql에 로그인한 후 아래 명령를 실행시켜준다.


-  mysql 서버 로그인하기

 $ mysql -uroot -prootpassword mysql


- 다른 PC에서 mysql 서버로 접속을 하기 위한 사용자 추가

 mysql> create user 'userId'@'%' identified by 'userpassword';


- 위 사용자에게 모든 것을 할 수 있는 권한 주기

mysql> grant all privileges on *.* to 'userid'@'%';


- 위 사용자에게 특정 DB를 관리할수 있는 권한 주기

 mysql> grant all privileges on dbname.* to 'userid'@'%';


- 로컬PC에서 mysql로 접속하기 위한 사용자 추가

 mysql> create user 'userId'@'localhost' identified by 'userpassword';


- 위 사용자에게 모든 것을 할 수 있는 권한 주기

 mysql> grant all privileges on *.* to 'userid'@'localhost';


- 위 사용자에게 특정 DB를 관리할 수 있는 권한 주기

 mysql> grant all privileges on dbname.* to 'userid'@'localhost';



대부분 사용자를 생성하고 권한을 줄때는 특정 DB를 관리하는 계정을 따로 만들기 위해서이다. 그러므로 사용자를 생성하고 권한을 줄때는 특정 DB를 관리할 수 있는 권한만 주면 된다.

MySQL에서 사용자의 로그인 보안 수준을 높이기 위해서,
MySQL 4.0.x 이하 버전과 MySQL 4.1.x 이상 버전의 PASSWORD() 함수의 구현 알고리즘이 달라졌다.
사실 아주 오래전 이야기이지만, 아직도 MySQL 4.0.x를 사용하는 사이트가 많고,
최근 들어서 MySQL 5.1이나 5.5 버전으로 업그레이드를 준비하면서 이런 내용이
업그레이드에 걸림돌이 되는 경우가 많은 것으로 보인다.



MySQL 4.0.x 이하 버전
  - PASSWORD()
  - OLD_PASSWORD() 함수는 없음


  mysql> SELECT PASSWORD('mypass');
  +--------------------+
  | PASSWORD('mypass') |
  +--------------------+
  | 6f8c114b58f2ce9e   |
  +--------------------+


MySQL 4.1.x 이상 버전
  - PASSWORD()         ==> 버전업된 암호화 함수
  - OLD_PASSWORD()     ==> 기존 암호화 (MySQL 4.0.x의 PASSWORD()와 동일)


  mysql>select PASSWORD('mypass');
  +-------------------------------------------+
  | password('mypass')                        |
  +-------------------------------------------+
  | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
  +-------------------------------------------+
  
  mysql>select OLD_PASSWORD('mypass');
  +------------------------+
  | old_password('mypass') |
  +------------------------+
  | 6f8c114b58f2ce9e       |
  +------------------------+


위 결과를 보면, 새로운 암호화 알고리즘에 의해서 암호화된 내용은 암호 제일 앞에 "*" 마크가 붙게 되므로, 새로운 암호인지 예전 암호인지 쉽게 구분할 수 있다.


그런데, old_passwords=1로 설정하게 되면, MySQL 4.1.x 이상 버전에서도 아래와 같이 MySQL 4.0.x와 같은 결과를 보여주게 된다.
MySQL 4.1.x 이상 버전에서도, 이전 버전과 동일하게 짧은 암호화 문장으로 변환됨
  root@localhost:(none)>select PASSWORD('mypass');
  +--------------------+
  | PASSWORD('mypass') |
  +--------------------+
  | 6f8c114b58f2ce9e   |
  +--------------------+
  
  root@localhost:(none)>select OLD_PASSWORD('mypass');
  +------------------------+
  | OLD_PASSWORD('mypass') |
  +------------------------+
  | 6f8c114b58f2ce9e       |
  +------------------------+


MySQL 4.1.x 이상 버전에서 old_passwords=0 (기본 설정값)인 경우에는, mysql.user 테이블의 비밀번호가 
예전 버전에서 생성된 짧은 비밀번호라면 로그인할 수 없게 된다.


하지만, MySQL 4.1.x 이상 버전에서도 mysql.user 테이블에 사용자의 비밀번호가 예전 버전인 경우 로그인할 수 있도록 
해주기 위해서 old_passwords 라는 옵션을 1로 설정할 수 있도록 해둔 것이다.


근본적인 원인은 MySQL이 업그레이드되면서 기존 비밀번호의 암호화 수준을 보완하여 더 보안 수준을 높이면서 
이런 문제가 야기되었다는 것이며, 가능하다면 업그레이드된 긴 암호를 사용하는 것이 좋아 보인다.


더 중요한 것은
MySQL의 PASSWORD() 함수는 MySQL의 사용자 자체의 계정 및 비밀번호를 관리하기 위한 함수이지
일반 서비스용 계정및 암호를 관리하는 용도로는 적합하지 않다는 것이다.


예를 들어서 MySQL 4.0.x 버전의 회원정보가 예전 방식의 PASSWORD() 함수로 암호화되어서 저장되어져 있다면,
MySQL 4.1.x 이상의 PASSWORD() 함수로는 로그인이 되지 않게 될 것이다. (이 경우에는 OLD_PASSWORD()를 사용해야만 로그인을 할수 있게 된다.)
하지만, 이 경우 예전 버전의 PASSWORD()함수의 암호화 내용을 새로운 버전의 PASSWORD() 함수로 대체할 수 없다.
(한번 암호화된 문장은 다시 풀어낼 수 없는 형태 - 비대칭형 암호화 - 이기 때문)
서비스용 계정이 MySQL의 사용자 계정 암호화 방식에 의존하게 되면 이런 문제가 야기될 수 있으므로 
필요시에는 MD5와 같은 알고리즘을 사용할 것을 추천한다.


또한, 이렇게 두개 버전의 암호화 방식이 존재하는 상태에서
서비스용 MySQL의 버전 업그레이드와 연관되어서 명확히 해결하지 않고 업그레이드를 진행하게 되면,
일부 사용자의 암호는 예전 버전이고, 또 일부 사용자는 새로운 암호화 버전을 사용하도록 되어버리면
걷잡을 수 없는 혼란에 빠져들고, 이를 처리하기 위해서 또 한번 쿼리와 IF ~ ELSE가 필요해질 수도 있다는 것이다.

'프로그램 > MySql' 카테고리의 다른 글

[MySQL]사용자 계정 생성 및 삭제  (0) 2016.11.29
MYSQL 사용자 생성  (0) 2016.11.29
MySQL 계열의 FLUSH PRIVILEGES 명령어  (0) 2016.11.28
MySQL 내장 함수 (MySQL전용 함수)  (0) 2016.11.28
MySQL 기본 명령어 정리  (0) 2016.11.28
MySQL이나 MariaDB를 사용하다보면 FLUSH PRIVILEGES라는 명령어를 자주 사용하게 된다. 대체 무슨 의미일까. 보통은 INSERT, DELETE, UPDATE를 통해 사용자를 추가, 삭제, 권한 변경 등을 수행하였을 때 이 변경 사항을 반영하기 위하여 사용한다. 이 떄 FLUSH PRIVILEGES는 grant 테이블을 reload함으로서 변경 사항을 즉시 반영하도록 한다. UPDATE USER SET PASSWORD=password('새로운패스워드') WHERE USER='사용자명'; FLUSH PRIVILEGES; DELETE FROM USER WHERE USER='사용자명'; FLUSH PRIVILEGES; 그런데 만약 INSERT, DELETE, UPDATE와 같은 SQL문을 사용하지 않고 바로 grant 명령어를 사용하여 작업하였다면 FLUSH PRIVILEGES를 실행할 필요가 없어진다. 또한 MySQL/MariaDB 상이 아닌 OS 커맨드 상에서도 flush를 할 수 있다. $ mysqladmin reload $ mysqladmin flush-privileges 패스워드가 설정된 경우는 인증을 해야 한다. $ mysqladmin -u root -p reload Enter password: 그런데 이 FLUSH PRIVILEGES는 굉장히 성능에 영향을 준다. 특히 습관적으로 FLUSH PRIVILEGES를 사용하는 경우가 있는데(모든 명령 이후에 사용하는 경우도 있다) 이는 엄청난 부하가 된다.

'프로그램 > MySql' 카테고리의 다른 글

MYSQL 사용자 생성  (0) 2016.11.29
PASSWORD()와 OLD_PASSWORD() 함수 그리고 old_passwords 설정  (0) 2016.11.28
MySQL 내장 함수 (MySQL전용 함수)  (0) 2016.11.28
MySQL 기본 명령어 정리  (0) 2016.11.28
join문  (0) 2015.10.14

7.3.3 MySQL 내장 함수 (MySQL전용 함수)


- IFNULL(A, B) : A가 null 이면 B를 A가 null이 아니면 A를 그대로 반환한다.

- ISNULL(A) : A가 null 이면 true(1) , null 이 아니면 false(0) 을 반환한다.


- NOW() : 현재시간 반환

- SYSDATE() : 현재시간 반환

** 일반적인 웹서비스에서 NOW()가 아닌 SYSDATE()를 꼭 사용해야 이유는 없다. 기능은 동일하지만 SYSDATE()는 '호출시점'에 따라 값이 결정되기 떄문에 인덱싱 등에 문제를 가진다.

    where from_data > SYSDATE() 는 실행때마다 SYSDATE값이 달라진다, 이건 상수가 아닌상태이다!!



- DATE_FOMRAT : Date Type -> String

  SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H시 %i분 %s초') AS cur_str;

- STR_TODATE : 문자열을 날자 타입으로 변경

  SELECT STR_TO_DATE( '2011-04-30', '%Y-%m-%d') as cur_dt;


- DATE_ADD, DATE_SUB : 날자 타입의 가감

  SELECT DATE_ADD( NOW(), INTERVAL 1 DAY ) as tomorrow;

  SELECT DATE_ADD( NOW(), INTERVAL -1 DAY ) as yesterday;

** YEAR, MONTH, DAY, HOUR, MINUTE, SECOND 의 값이 있고 [ INTERVAL n 단위 ] 형식으로 입력하면 된다.


- RPAD(),  LPAD() : 문자의 좌우측에 문자를 덧붙여 지정된 길이로 만든다.

  SELECT RPAD("Cloee', 10, '_'); -> Cloee_____

- RTRIM(), LTRIM(), TRIM() : 문자의 우측, 좌측, 양측의 공백(Space, NewLine, Tab)을 제거

- CONCAT : 문자열을 연결, 인자의 갯수는 제한이 없다.

- CONCAT : 문자열을 구분자를 넣어서 연결해준다.

  SELECT CONCAT_WS(',', 'A', 'B', 'C') --> A,B,C


- GROUP_CONCAT :  값들을 정렬한후, 연결하거나 구분자설정, 중복제거등 유용하다.


  ex1-SELECT GROUP_CONCAT(dept_no) 

  ==> d001, d002, d003, d004 

  FROM dept (dept모든 레코드에서 dept_no 칼럼을 기본 구분자, 로 연결한 값을 반환)

  


  ex2- SELECT GROUP_CONCAT(dept_no, SEPARATOR '|') FROM dept

  ==> d001|d002|d003}d004 

  

  ex3- SELECT GROUP_CONCAT(dept_no, ORDER BY dept_name DESC) from dept

  ==> d007,d008,d004,d001

  dept_name 역순 정렬 -> dept_no 들의 연결값을 가져옴


  ex4- SELECT GROUP_CONCAT(DISTINCT dept_no ORDER BY dept_name DESC) from dept

  ==> d007,d008,d006,d004

  ex3과 동일하지만 중복된 dept_no가 있다면 제거하고 가져온다.

  

** 제한적인 메모리 버퍼를 사용하는데 TOAD나 SQLYog에서는 단순한 Warnning지만, JDBC로 연결할 때는 SQLException이 발생하므로, GROUP_CONCAT의 결과가 버퍼를 초과하지 않도록 주의해야한다.


  

- CASE WHEN (Function가 아닌 Syntax)

SELECT emp_no, frst_name 

CASE gender WHEN 'M TEHN 'Man' 

 WHEN 'F' THEN 'Woman' 

ELSE 'Unknown' 

END AS gender

FROM emp LIMIT 10

 ** CASE WHEN 절이 일치해야만 THEN 이하도 실행이 된다.   서브쿼리->CASE WHEN으로 성능 향상을 꾀할 수 있다.(P407)



- MD5, SHA : 비대칭형 암호화 알고리즘 (SHA - SHA-1알고리즘, 160bit 해시 값, MD5 - Message Digest알고리즘 128bit 해시 값)

 중복의 가능성이 매우 낮기 때문에, 길이가 긴 데이터를 줄여서 인덱싱하는 용도로도 사용한다.(url값 인덱싱)



- COUNT() : 칼럼이나 표현식을 인자로 받고, *을 사용하지만 '모든 칼럼이 아니라, RECORD 자체를 의미'한다.
  - MyISAM : 메타테이블의 전체 레코드수가 있어서 where가 없는 count(*)는 결과를 바로 반환가능
  - 그외 스토리지 : 직접 읽어야만 하므로, 큰 테이블에서 count(*)는 주의해야한다.

- 표준 주석
  -   --공백하나 : 한줄의 주석
  -   /* 내용 */ : 여러준 주석
  -   # 라인 이후 주석 : 비표준 

  - 변형 주석
   CREATE /*! 50154 TEMPORARY */ TABLE tb_test (fd INT, PRIMARY KEY(fd));
   -> 5.1.54이상 CREATE TEMPORARY TABLE tb_test (fd INT, PRIMARY KEY(fd));
   -> 5.1.54미만 CREATE TABLE tb_test (fd INT, PRIMARY KEY(fd));
    MySQL의 버전에 따라 주석이 될수도, 쿼리문장이 될 수도 있다. !뒤에가 기준 버전이 된다.

    MySQL 5.0에서 쿼리나 프로시저에 포함된 주석은 모두 삭제되는데 이를 트릭으로 막을 수 있다.

    BEGIN
        /*! 99999 주석 내용 */
        RETURN '테스트'
    END 


'프로그램 > MySql' 카테고리의 다른 글

MYSQL 사용자 생성  (0) 2016.11.29
PASSWORD()와 OLD_PASSWORD() 함수 그리고 old_passwords 설정  (0) 2016.11.28
MySQL 계열의 FLUSH PRIVILEGES 명령어  (0) 2016.11.28
MySQL 기본 명령어 정리  (0) 2016.11.28
join문  (0) 2015.10.14

MySQL 기본 명령어 정리

MySQL의 기본 명령어와 SQL문 정리. 내가 RDBMS에 완전 문외한이기 때문에 기본 SQL쿼리까지…

Redhat Linux 7.3, MySQL 3.23.58 에서 테스트함.

설치는 Redhat 기본 제공 RPM으로 했다.

데이터베이스 접속

mysql -u 사용자명 -p dbname

설치 직후에는 root 사용자에 비밀번호가 없으므로 다음과 같이 접속하여 MySQL을 관리할 수 있다.

mysql -u root mysql

외부 서버에서 접속이 불가하면 MySQL 설정에서 bind-address 항목을 살펴본다.

비밀번호 변경

MySQL을 설치한 직후에는 root 계정에 암호가 지정되어 있지 않다. 다음 세가지 방법으로 비밀번호를 변경 할 수 있다.

# mysqladmin 이용
mysqladmin -u root password 새비밀번호
# update문 이용
mysql -u root mysql
----
mysql> UPDATE user SET password=password('새비밀번호') WHERE user='root';
mysql> FLUSH PRIVILEGES;
# Set Password 이용
mysql> SET PASSWORD FOR root=password('새비밀번호');

일단 root 비밀번호가 설정된 상태에서는 mysql이나 mysqladmin 명령을 실행할 때 -p 옵션을 붙여주고 기존 비밀번호를 입력해야만 한다.

사용자 추가/삭제

GRANT ALL PRIVILEGES ON dbname.* TO username@localhost IDENTIFIED BY 'password';

username 이라는 사용자를 password라는 비밀번호를 갖도록 하여 추가한다. username은 dbname이라는 데이타베이스에 대해 모든 권한을 가지고 있다. username 사용자는 로칼 호스트에서만 접속할 수 있다. 다른 호스트에서 접속하려면

GRANT ALL PRIVILEGES ON dbname.* TO username@'%' IDENTIFIED BY 'password';

위를 또한 번 실행한다. '%'에서 홑따옴표를 주의한다.

특정 권한만 주려면, 아래와 같은 형태로 권한을 나열한다.

GRANT INSERT,UPDATE,SELECT ON dbname.* TO username@'localhost' IDENTIFIED BY 'pwd';

MySQL error 1045(28000): Access denied for user ...에 따르면 '%'란 localhost 를 제외한 모든 호스트를 뜻한다고 한다. 즉, localhost에 대해서는 명시적으로 따로 권한을 지정해야 한다.

CREATE USER를 통한 사용자 생성이 안될 경우에는 mysql - ERROR 1396 (HY000): Operation CREATE USER failed for 'jack'@'localhost' 참조하여, 먼저 생성하려던 사용자를 drop 하고 재시도 해본다. 이 현상이 나타나는 이유는, CREATE USER/GRANT 명령으로 사용자와 권한을 추가/관리해야 하는데 mysql.db, mysql.user 테이블을 직접 조작하다가 일관성이 깨졌기 때문이다. 가급적 mysql의 계정/권한 테이블에 대한 직접 조작은 하지 말아야 한다.

drop user admin@localhost;
flush privileges;
create user admin@localhost identified by 'admins_password'

불필요한 사용자 삭제는

mysql> DLETE FROM USER WHERE USER='username';
mysql> FLUSH PRIVILEGES;

데이터베이스 생성/보기

# 데이터베이스를 생성하고,
mysql> CREATE DATABASE dbname;
 
# 현재 존재하는 데이터베이스 목록을 보여준다.
mysql> SHOW DATABASES;
 
# 특정 데이타베이스를 사용하겠다고 선언한다.
mysql> USE dbname;
 
# 쓸모 없으면 과감히 삭제한다.
mysql> DROP DATABASE [IF EXISTS] dbname;

IF EXISTS 옵션은 비록 데이타베이스가 없더라도 오류를 발생시키지 말라는 의미이다.

테이블 생성/보기

테이블을 생성하고,

mysql> CREATE TABLE tablename (
  column_name1 INT PRIMARY KEY AUTO_INCREMENT,
  column_name2 VARCHAR(15) NOT NULL,
  column_name3 INT
) ENGINE=INNODB;

현재 데이타베이스의 테이블 목록을 보고

mysql> SHOW TABLES;

테이블 구조를 살펴본다.

mysql> EXPLAIN tablesname;
혹은
mysql> DESCRIBE tablename;

이름을 잘못 지정했으면 이름을 변경할 수도 있다.

mysql> RENAME TABLE tablename1 TO tablename2[, tablename3 TO tablename4];

필요 없으면 삭제한다.

mysql> DROP TABLE [IF EXISTS] tablename;

현재 상태 보기

mysql> STATUS
 
--------------
mysql Ver 11.18 Distrib 3.23.58, FOR pc-linux (i686)
 
Connection id: 26
CURRENT DATABASE: study
CURRENT USER: study@localhost
CURRENT pager: stdout
USING OUTFILE: ''
Server version: 3.23.58
Protocol version: 10
Connection: Localhost via UNIX socket
Client characterset: latin1
Server characterset: euc_kr
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 2 hours 9 MIN 59 sec
 
Threads: 1 Questions: 160 Slow queries: 0 Opens: 28 FLUSH TABLES: 1
OPEN TABLES: 1 Queries per SECOND avg: 0.021
--------------

INSERT

mysql> INSERT INTO tablename VALUES(1,2, ...);
혹은
mysql> INSERT INTO tablename (col1, col2, ...) VALUES(1,2, ...);

SELECT

mysql> SELECT col1, col2, ... FROM tablename;

컬럼명을 *로 하면 모든 컬럼 의미.

mysql> SELECT col1 AS '성명', col2 AS '국어점수' FROM grade;

컬럼의 이름을 바꿔서 출력.

mysql> SELECT * FROM tablename ORDER BY col1 DESC;
mysql> SELECT col1, korean + math english AS '총점' FROM tablename ORDER BY '총점' ASC;

DESC는 내림차순 ASC는 오름차순.

mysql> SELECT * FROM grade WHERE korean < 90;

결과중 처음부터 10개만 가져오기

mysql> SELECT * FROM grade LIMIT 10;

결과중 100번째부터 10개만 가져오기. 첫번째 레코드는 0번 부터 시작한다.

mysql> SELECT * FROM grade LIMIT 100, 10;

UPDATE

mysql> UPDATE tablename SET col1=새값 WEHER 조건

DELETE

mysql> DELETE FROM tablename WEHRE 조건

DELETE with JOIN

-- DELETE 바로 뒤에 삭제할 테이블을 적는다.
-- INNER JOIN
DELETE T1, T2
FROM T1
INNER JOIN T2 ON T1.key = T2.key
WHERE condition;
 
-- LEFT JOIN
DELETE T1
FROM T1 
LEFT JOIN T2 ON T1.key = T2.key 
WHERE T2.key IS NULL;

mysql에서 쿼리 결과 세로로 보기

-E 옵션을 줘서 실행한다.

mysql -E -u root -p mysql

mysql에서 발생한 오류나 경고 다시 보기

mysql> SHOW errors;
mysql> SHOW warnings;

show processlist

SHOW FULL processlist;
SHOW FULL processlist\G;

MySQL 버전 알아보기

SHOW VARIABLES LIKE "%version%";

CREATE TABLE 구문 보기

SHOW CREATE TABLE [테이블이름]\G

테이블/컬럼 정보보기

-- 전체 테이블 정보를 주석까지 포함해 보여준다.
SHOW TABLE STATUS;

SHOW TABLE STATUS like 'member%'; -- 테이블 이름 매칭 조건

-- 테이블의 컬럼 정보를 주석까지 포함해 보여준다.
SHOW FULL COLUMNS FROM [테이블이름];

테이블/컬럼의 주석(Comment) 지정

-- 테이블의 주석 변경
ALTER TABLE [테이블이름] COMMENT = '테이블설명';

-- 컬럼의 주석 변경
ALTER TABLE [테이블이름] CHANGE COLUMN [컬럼이름] [새컬럼이름] ...여러 속성... COMMENT '새 주석';

테이블과 컬럼의 전체 정보

information_schemaTABLES, COLUMNS를 쿼리하여 테이블, 컬럼 정보를 살펴볼 수 있다.

select t.TABLE_SCHEMA, t.TABLE_NAME, c.COLUMN_NAME, c.COLUMN_TYPE, c.COLUMN_COMMENT from `TABLES` t
	inner join `COLUMNS` c on t.TABLE_NAME = c.TABLE_NAME
order by t.TABLE_SCHEMA, t.TABLE_NAME


join문

 

6-1.full join
join 문중에서 가장 간단한 join문이라는 특징이 있으며 full join은 다음과 같이 설명할 수 있습니다.

>select * from tableA, tableB;

일반적인 join문은 양쪽 테이블의 레코드 갯수를 곱한 수만큼 검색을 하기 때문에 join을 사용할 때에는 주의해서 사용해야 합니다. 자칫 잘못걸린 join문은 검색속도를 저하시키고 전반적인 시스템의 성능저하를 유발시킬 수 있기 때문입니다.
다음의 예제는 full join의 형식과 일치하며 모두 같은 값을 출력합니다.

>select * from tableA, tableB;
>select * from tableA join tableB;
>select * from tableA cross join tableB;

 

6-2. straight_join
이 join문은 칼럼의 순서를 from절에 나오는 테이블의 순서대로 출력하는 join 입니다. 경우에 따라 MySQL은 속도를 빠르게 하기 위해 나름대로 내부적으로 from절에 나온 테이블의 순서를 바꾸는 경우가 있습니다. 이때 칼럼의 순서를 from 절에 나오는 순서대로 바꾸기 위해  straight_join을 사용하면 되니다.

 

 

6-3 theta join
full join문에 where 를 걸게 되면 theta join입니다.

>select * from tableA, tableB where
->tableA.b=tableB.b;

 

 

6-4. inner join
>select * from tableA INNER JOIN tableB USING(b);
또는
>select * from tableA INNER JOIN tableB ON
->tableA.b=tableB.b;
where절 대신에 ON을 사용하여 비교하고자 하는 컬럼을
직접 지정해 주는 방식. USING는 지정된 공통컬럼명을
ON으로 지정한것과 동일한 효과를 가짐.

 

 

6-5. NATURAL JOIN
두개의 테이블에 같은 이름을 가진 컬럼들이 있고
그 컬럼들을 기준으로 join을 하려 한다면 natural join을
사용합니다.
>select * from tableA natural join tableB;


추가 예제)
join문을 사용할 때 select 되는 컬럼의 지정방법
select tableA.x, tableB.x from tableA, tableB;

같은 결과 alias를 사용한 방법
select a.x, b.x from tableA as a, tableB as b;

 

 

6-6. left outer join
tableA와 tableB 를 join하여 검색할때 where 절의
tableA.b=tableB.b라고 검색하면 두 테이블의 b컬럼에
일치하는 data만을 불러 오지만 만약 tableB.b의 값이
tableA.b에 존재하지 않는 값을 가지고 있는 레코드까지
가져와야 할 경우 사용.
>select * from tableA left outer join tableB using(b);

ex)
>select * from grade left outer join study_report
->using(student_name);

 

 

6-7. right outer join
left outer join과는 반대의 개념으로
tableA와 tableB을 join하여 검색할 경우 tableB
기준으로 tableA에 값이 존재 하지 않는 것을
가져와야 할 경우 사용

※ 참고
outer 는 명시적 옵션이므로 생략가능


+ Recent posts