Vấn đề năm 2038

Bình thường thì mình cũng không để ý đâu cho đến gặp lỗi Integration Test (#IT), chả là mình đổi 1 loạt trường dữ liệu từ #Date sang #LocalDate và #LocalDateTime, rồi lúc random đến năm 2100 thì không save vào #MySQL được, lần mò mãi mới nghĩ ra MySQL #timestamp là 32 bit và tối đa nó chỉ đến 03:14:07 ngày thứ 3, 19 tháng 1 năm 2038 (231-1 = 2,147,483,647 tính từ giây đầu tiên của năm 1970) Sau khi lần mò thì thấy wiki có hẳn 1 trang Year #2038 problem như kiểu #Y2K nhỉ =)) và hiện tại MySQL đang tìm giải pháp cho vấn đề này, tuy nhiên là việc thay đổi sẽ tương đối khó khăn nên chúng ta vẫn cần dùng giải pháp thay thế.

Xin tạm biệt và cám ơn

Cho dù răng timestamp là rất tiện, giúp chúng ta không cần phải quan tâm đến timezone nữa. Thế nhưng chẳng ai muốn đến năm 2038 ứng dụng của chúng ta sẽ phải dừng lại cả. Vậy nên sau khi họp bàn rất nhiều, bọn mình đã quyết định chào tạm biệt timestamp, thay vào đó là sử dụng một trong 2 giải pháp sau đây.

Những giải pháp thay thế

Vậy có những giải pháp nào?

  1. Sử dụng long, bigint để thay thế: giải pháp này an toàn, hiệu năng ổn, tuy nhiên sẽ khó khăn trong việc truy vấn và debug về sau này, và sẽ rất khó để tester test được, gây tốn nhiều tài nguyên con người và dễ lỗi, phương án này chắc chắn các boss và #PM sẽ không thích.
  2. Sử dụng Date và DateTime: giải pháp này an toàn và dễ debug, tuy nhiên là Date không chứa thông tin của #timezone, vậy nên khi sử dụng phải chú ý việc này, phải config để timezone của server và database là như nhau.

Một chút lưu ý

Trong quá trình phát triển phải nâng phiên bản của #hibernate lên 5.4.18 và #spring boot là 2.3.2.RELEASE tương ứng. Ồ tại sao nâng phiên bản lại được vậy?Vì ở những phiên bản trước đó khi serialize LocalDate và LocalDateTime ra date thì hibernate sử dụng timezone của MySQL Server (khi connect đến #DB hibernate gọi query để lấy) vậy hibernate sẽ convert time sang time của DB, điều này gây ra sự sai lệch nếu máy local của bạn và DB lệch nhau, ví dụ dự án của mình thì server là GMT+9 còn máy mình là GMT+7. Ở phiên bản mới thì Hibernate sẽ không sử dụng timezone của DB nữa mà sử dụng timezone của máy local nên vấn đề đã được giải quyết Với mình thì lựa chọn phương án 2, tuy chậm tí nhưng debug đỡ khổ, tiết kiệm thời gian và công sức cho cá nhân và doanh nghiệp, đặc biệt là giảm áp lực cho các bạn QA (convert string date sang long rồi query sẽ khiến các bạn ấy dễ mắc lỗi)

Tham khảo

  1. wiki
  2. jpa-java-time