DB/MYSQL

LAST_INSERT_ID() 사용 시 주의할 점

MAKGA 2022. 1. 7. 13:30
320x100

인터넷으로 검색을 하다보면 insert의 성공 결과로 LAST_INSERT_ID()를 사용하는 내용이 많다.

하지만 LAST_INSERT_ID()는 '마지막으로 성공한 Auto increment의 값'을 반환하는 함수이며, 없다면 기본값인 0을 반환한다.

다음과 같은 경우에는 사용자의 주의가 필요하다.


1. auto increment 없이 insert를 하는 경우

LAST_INSERT_ID()는 auto increment의 성공한 값을 반환한다고 했다.

auto increment 설정 없이 아무리 insert 한다고 해도 LAST_INSERT_ID()는 0을 반환할 뿐이다.

자동으로 증가해야 될 시퀀스들을 따로 구현해 사용하는 경우 해당 함수로는 insert의 성공 여부를 판단할 수 없다.


2. innoDB 사용시 머신의 재시작

MYSQL의 innoDB는 메모리를 기반으로 저장하기 때문에 Auto increment를 하게 되면 그 값이 메모리에 저장된다.

하지만 재시작을 하게 되면 그 데이터가 휘발되어 버리기 때문에 머신을 재시작 하게 되면 해당 컬럼에서 max(column)을 실행해 저장되어있는 최고 값을 가져와 가지고 있게 된다.

이 때 재시작 직전에 가장 마지막에 삽입했던 데이터를 삭제하게 되면, 재시작시 그 삭제됬던 key 값을 다시 가지게 될 수 있는 문제가 생겨버린다.

이미 삭제된 key이므로 데이터 중복은 일어나지 않겠지만, 다른 테이블과의 관계나 로그등으로 key를 확인하는 경우 무결성이 떨어질 수 있다.


3. 다음과 같은 쿼리를 사용하는 경우
#column_name이 auto increment가 설정되어있다고 가정
INSERT INTO table_name(column_name) VALUES ('A'),('B'),('C');

SELECT LAST_INSERT_ID();

3개의 데이터를 입력했을 때, LAST_INSERT_ID()의 결과가 무엇으로 나올까?

3이 나와야 할 것 같지만 1이 나온다.

3개의 데이터를 입력했지만 결국 하나의 '쿼리'로 동작한다. INSERT 쿼리에 반응하는 녀석이니 결국 쿼리 수로 계산을 해야한다.

 

이런 원인으로 인해 bulk로 대량의 insert문을 실행했을 때 문제가 발생할 수 있다.


4. 다음과 같은 쿼리를 사용하는 경우
#column_name이 auto increment가 설정되어있다고 가정
START TRANSACTION;

INSERT INTO table_name(column_name) VALUES('A');
INSERT INTO table_name(column_name) VALUES('B');
INSERT INTO table_name(column_name) VALUES('C');

ROLLBACK;

SELECT LAST_INSERT_ID();

INSERT INTO table_name(column_name) VALUES('D');

COMMIT;

SELECT LAST_INSERT_ID();

3번의 insert 쿼리 이후 ROLLBACK을 해서 데이터가 적용되지 않게 했을 때, LAST_INSERT_ID()의 결과는 어떻게 될까?

ROLLBACK이 됐으니 같이 auto increment도 취소 됐으리라 생각할 수 있지만 답은 3이다.

auto increment는 insert에 대해 적용된다. insert가 실패한 것이 아니므로 이미 증가되었고, 데이터가 rollback 되었다고 해서 증가분까지 없어지지 않는다.


그저 insert의 성공 결과를 알아야겠다면 insert한 데이터들로 select 쿼리를 한번 날려야한다.


 

320x100