Skip to content

Instantly share code, notes, and snippets.

@kwon37xi
Last active February 13, 2018 08:11
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwon37xi/9205428 to your computer and use it in GitHub Desktop.
Save kwon37xi/9205428 to your computer and use it in GitHub Desktop.
MySQL 5.6의 DATETIME ms 반올림 버그와 구버전 JDBC 드라이버의 ms 절삭 버그 조합
/*
MySQL 5.6의 DATETIME 타입에 대한 밀리세컨드 부분 절삭 버그 재현
MySQL 5.6.4 ms 지원 : http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
MySQL 5.6 DATETIME 타입에서 ms 반올림(round) 버그 : http://bugs.mysql.com/bug.php?id=68760
MySQL Connector/J 5.1.22 까지는 Date 객체의 ms 부분을 미리 절삭해 전송하는 버그 있음
MySQL Connector/J 5.1.23 부터는 Date 객체의 ms 부분도 함께 전송 -> MySQL 5.6 서버의 ms 반올림 버그 유발 -> 초,분,날짜가 바뀌는 현상 유발
** 아래코드를 반올림 버그가 있는 MySQL 5.6서버에서 JDBC 드라이버 바꿔가며 실행한 결과
* Conector/J 5.1.22 이하
insert into datetest (normaldate, longdate) values('1999-12-31 23:59:59', '1999-12-31 23:59:59') -- ms 부분이 절삭된 SQL이 날아간다.
-- 입력된 데이터를 select 해보면 앞에가 DATETIME, 뒤는 DATETIME(6)
1999/12/31 23:59:59.000 | 1999/12/31 23:59:59.000
* Connector/J 5.1.23 이상
insert into datetest (normaldate, longdate) values('1999-12-31 23:59:59.555', '1999-12-31 23:59:59.555') -- ms 부분이 존재하는 SQL이 날아간다.
-- 입력된 데이터 select 해보면 DATETIME 타입의 경우 ms 부분을 반올림 해서 2000년으로 년도가 바뀌어버린다.
2000/01/01 00:00:00.000 | 1999/12/31 23:59:59.555
*/
@GrabConfig(systemClassLoader = true)
@Grab(group = 'mysql', module = 'mysql-connector-java', version = '5.1.22') // 여기서 5.1.23으로 업그레이드하면 현상이 바뀜
import groovy.sql.Sql
import java.util.Date
/*
drop table datetest;
create table datetest (
id int auto_increment primary key,
normaldate datetime not null,
longdate datetime(6) not null
);
*/
def driver = "com.mysql.jdbc.Driver"
def jdbcUrl = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"
def sql = Sql.newInstance(jdbcUrl, 'root', 'root', driver)
def format = 'yyyy/MM/dd HH:mm:ss.SSS'
Date date = Date.parse(format, '1999/12/31 23:59:59.555')
println "#Date to test ${date.format(format)}"
sql.execute('insert into datetest (normaldate, longdate) values(?, ?)', [date, date])
sql.eachRow('select id, normaldate, longdate from datetest order by id') {
println "${it.id} : ${it.normaldate.format(format)} | ${it.longdate.format(format)}"
}
sql.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment