Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Tại sao giới hạn thời gian tối đa của MySQL là 838:59:59?

TIME các giá trị luôn được lưu trữ trên 3 byte trong MySQL. Nhưng định dạng đã thay đổi trên phiên bản 5.6 .4 . Tôi nghi ngờ đây không phải là lần đầu tiên khi nó thay đổi. Nhưng sự thay đổi khác, nếu có, đã xảy ra từ lâu và không có bằng chứng công khai về điều đó. Lịch sử mã nguồn MySQL trên GitHub bắt đầu với phiên bản 5.5 (bản cam kết cũ nhất là từ tháng 5 năm 2008) nhưng sự thay đổi mà tôi đang tìm kiếm đã xảy ra vào khoảng năm 2001-2002 (MySQL 4 được đưa ra vào năm 2003)

Định dạng hiện tại, như được mô tả trong tài liệu, sử dụng 6 bit cho giây (các giá trị có thể có:0 thành 63 ), 6 bit cho phút, 10 bit cho giờ (giá trị có thể:0 thành 1023 ), 1 bit cho dấu (thêm các giá trị âm của các khoảng đã được đề cập) và 1 bit không được sử dụng và được gắn nhãn "dành riêng cho các phần mở rộng trong tương lai".

Nó được tối ưu hóa để làm việc với các thành phần thời gian (giờ, phút, giây) và không tốn nhiều dung lượng. Sử dụng định dạng này, bạn có thể lưu trữ các giá trị trong khoảng từ -1023:59:59+1023:59:59 . Tuy nhiên, MySQL giới hạn số giờ là 838 , có thể là để tương thích ngược với các ứng dụng đã được viết trước đó, khi tôi nghĩ đây là giới hạn.

Cho đến phiên bản 5.6.4, TIME giá trị cũng được lưu trữ trên 3 byte và các thành phần được đóng gói dưới dạng days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Định dạng này được tối ưu hóa để làm việc với dấu thời gian (vì trên thực tế, nó là dấu thời gian). Sử dụng định dạng này, có thể lưu trữ các giá trị trong phạm vi khoảng -2330 thành +2330 giờ. Mặc dù có sẵn phạm vi giá trị lớn này, nhưng MySQL vẫn giới hạn các giá trị ở -838 thành +838 giờ.

Đã xảy ra lỗi # 11655 trên MySQL 4. Có thể trả về TIME giá trị bên ngoài -838..+838 phạm vi sử dụng SELECT lồng nhau các câu lệnh. Đó không phải là một tính năng mà là một lỗi và nó đã được sửa.

Lý do duy nhất để giới hạn các giá trị trong phạm vi này và để chủ động thay đổi bất kỳ đoạn mã nào tạo ra TIME các giá trị bên ngoài nó là khả năng tương thích ngược.

Tôi nghi ngờ MySQL 3 đã sử dụng một định dạng khác, do cách dữ liệu được đóng gói, đã giới hạn các giá trị hợp lệ trong phạm vi -838..+838 giờ.

Bằng cách xem xét mã nguồn của MySQL Tôi đã tìm thấy công thức thú vị này:

#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)

Hãy tạm thời bỏ qua MAX một phần của các tên được sử dụng ở trên và hãy chỉ nhớ rằng TIME_MAX_MINUTETIME_MAX_SECOND là các số giữa 0059 . Công thức chỉ nối giờ, phút và giây trong một số nguyên duy nhất. Ví dụ:giá trị 170:29:45 trở thành 1702945 .

Công thức này đặt ra câu hỏi sau:cho rằng TIME giá trị được lưu trữ trên 3 byte có dấu, giá trị dương lớn nhất có thể được biểu diễn theo cách này là bao nhiêu?

Giá trị chúng tôi đang tìm kiếm là 0x7FFFFF trong ký hiệu thập phân là 8388607 . Kể từ bốn chữ số cuối cùng (8607 ) nên được đọc là phút (86 ) và giây (07 ) và giá trị hợp lệ tối đa của chúng là 59 , giá trị lớn nhất có thể được lưu trữ trên 3 byte có dấu bằng công thức ở trên là 8385959 . Mà, dưới dạng TIME+838:59:59 . Ta-da!

Đoán xem nào? Đoạn C mã liệt kê ở trên được trích xuất từ ​​cái này:

/* Limits for the TIME data type */
#define TIME_MAX_HOUR 838
#define TIME_MAX_MINUTE 59
#define TIME_MAX_SECOND 59
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)

Tôi chắc chắn đây là cách MySQL 3 sử dụng để giữ TIME giá trị nội bộ. Định dạng này áp đặt giới hạn của phạm vi và yêu cầu tương thích ngược đối với các phiên bản tiếp theo đã phổ biến giới hạn cho thời của chúng ta.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Đặt kết quả của một truy vấn thành một biến trong MySQL

  2. Truy vấn chậm khi sử dụng ORDER BY

  3. MySQL:lấy TỐI ĐA hoặc TUYỆT VỜI nhất của một số cột, nhưng với các trường NULL

  4. Cách tốt nhất để lưu trữ và truy xuất các từ đồng nghĩa trong cơ sở dữ liệu mysql

  5. Máy chủ MySQL độc lập