Статьи

Восстановление временных типов в MySQL 5.6: TIME, TIMESTAMP и DATETIME


Это сообщение от 
Александра Кузьминского из MySQL Performance Blog.

MySQL 5.6 представляет новую функцию — разрешение микросекунд в некоторых временных типах. Начиная с 5.6.4 TIME, TIMESTAMP и DATETIME могут иметь дробную часть. Чтобы создать поле с подсекундами, вы можете указать точность в скобках: TIME (3), DATETIME (6) и т. Д.

Очевидно, что новая функция требует изменения формата . У всех трех типов теперь может быть хвост с дробной частью. Хвост может быть длиной в один, два или три байта и может содержать до шести цифр после точки.

Нефракционная часть тоже изменилась. Таким образом, DATETIME использует только пять байтов по сравнению с восемью в предыдущих версиях.

Начиная с версии 79 инструментарий восстановления поддерживает новый формат.

Давайте восстановим образец таблицы, чтобы увидеть, как она работает. Таблица является:

CREATE TABLE `t` (
  `id` int(11) AUTO_INCREMENT,
  `t1` time(3),
  `t2` timestamp(6),
  `t3` datetime(1),
  `t4` datetime,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB
mysql> select * from t;
+----+--------------+----------------------------+-----------------------+---------------------+
| id | t1           | t2                         | t3                    | t4                  |
+----+--------------+----------------------------+-----------------------+---------------------+
|  1 | 05:05:10.000 | 2013-07-04 05:05:10.000000 | 2013-07-04 05:05:10.0 | 2013-07-04 05:05:10 |
|  2 | 05:14:24.414 | 2013-07-04 05:14:24.125000 | 2013-07-04 05:14:24.4 | 2013-07-04 05:14:25 |
|  3 | 05:14:32.566 | 2013-07-04 05:14:32.207031 | 2013-07-04 05:14:32.3 | 2013-07-04 05:14:32 |
|  4 | 05:14:34.344 | 2013-07-04 05:14:34.507813 | 2013-07-04 05:14:34.5 | 2013-07-04 05:14:35 |
|  5 | 05:14:45.348 | 2013-07-04 05:14:45.832031 | 2013-07-04 05:14:45.1 | 2013-07-04 05:14:45 |
+----+--------------+----------------------------+-----------------------+---------------------+

Во-первых, мы должны создать файл определения таблицы:

./create_defs.pl --db test --table t > include/table_defs.h

Затем перекомпилируйте инструмент и разбейте табличное пространство, содержащее записи таблицы t:

./page_parser -f /var/lib/mysql/test/t.ibd

Следующим шагом является получение записей из индекса InnoDB:

$ ./constraints_parser -5f pages-1372929630/FIL_PAGE_INDEX/0-30/00000000-00000003.page  2> /dev/null
-- Page id: 3, Format: COMPACT, Records list: Valid, Expected records: (5 5)
0000000007DB    A6000001A20110  t       1       "05:05:10.0"    "2013-07-04 05:05:10.0" "2013-07-04 05:05:10.0" "2013-07-04 05:05:10.0"
0000000007DE    A8000001530110  t       2       "05:14:24.4140" "2013-07-04 05:14:24.125000"    "2013-07-04 05:14:24.40"        "2013-07-04 05:14:25.0"
0000000007EC    B2000001A40110  t       3       "05:14:32.5660" "2013-07-04 05:14:32.207031"    "2013-07-04 05:14:32.30"        "2013-07-04 05:14:32.0"
0000000007ED    B3000001A50110  t       4       "05:14:34.3440" "2013-07-04 05:14:34.507813"    "2013-07-04 05:14:34.50"        "2013-07-04 05:14:35.0"
0000000007FB    BD000001670110  t       5       "05:14:45.3480" "2013-07-04 05:14:45.832031"    "2013-07-04 05:14:45.10"        "2013-07-04 05:14:45.0"
-- Page id: 3, Found records: 5, Lost records: NO, Leaf page: YES

Чтобы загрузить этот дамп, используйте команду LOAD DATA INFILE, сгенерированную contraints_parser, затем я перенаправил ее в / dev / null в примере выше.

Как видите, это довольно просто. Есть две заметки:

  • Из-за различий в формате инструмент может определить, является ли поле новым или старым
  • Для поля TIME (без дробной части) в новом формате вам нужно дать подсказку contraints_parser. Это вариант -6. Позвольте мне проиллюстрировать это

До 5.6.4 ВРЕМЯ было упаковано в три байта: ДД × 24 × 3600 + ЧЧ × 3600 + ММ × 60 + СС. Начиная с 5.6.4 он все еще использует три байта, но формат отличается:


ВРЕМЯ новый формат 
биты описание ценности
1 знак 1 = неотрицательный, 0 = отрицательный
1 неиспользуемый зарезервировано для будущих расширений
10 час 0-838
6 минут 0-59
6 второй 0-59

Если поле создано без дробной части, невозможно определить формат по значению поля. Давайте возьмем стол:

CREATE TABLE `t` (
  `id` int(11) AUTO_INCREMENT,
  `t1` time ,
  `t2` time(3) ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
mysql> select * from t;
+----+----------+--------------+
| id | t1       | t2           |
+----+----------+--------------+
|  1 | 11:01:17 | 11:01:17.000 |
|  2 | 11:01:17 | 11:01:17.125 |
|  3 | 11:01:17 | 11:01:17.125 |
+----+----------+--------------+

Если дробной части нет, constraints_parser предполагает старый формат. Поэтому, если мы попытаемся восстановить записи из таблицы выше, результат будет неправильным:

$ ./constraints_parser -5f pages-1373023772/FIL_PAGE_INDEX/0-31/00000000-00000003.page
-- Page id: 3, Format: COMPACT, Records list: Valid, Expected records: (3 3)
000000000807    C5000001AC0110  t8      1       "12:32:17"      "11:01:17.0"
000000000807    C5000001AC011C  t8      2       "12:32:17"      "11:01:17.1250"
000000000807    C5000001AC0128  t8      3       "12:32:17"      "11:01:17.1250"
-- Page id: 3, Found records: 3, Lost records: NO, Leaf page: YES

Таким образом, нам нужно дать подсказку, тогда значения ВРЕМЕНИ верны:

./constraints_parser -5f pages-1373023772/FIL_PAGE_INDEX/0-31/00000000-00000003.page -6
-- Page id: 3, Format: COMPACT, Records list: Valid, Expected records: (3 3)
000000000807    C5000001AC0110  t8      1       "11:01:17.0"    "11:01:17.0"
000000000807    C5000001AC011C  t8      2       "11:01:17.0"    "11:01:17.1250"
000000000807    C5000001AC0128  t8      3       "11:01:17.0"    "11:01:17.1250"
-- Page id: 3, Found records: 3, Lost records: NO, Leaf page: YES