Skip to content

Instantly share code, notes, and snippets.

@frsyuki
Last active October 8, 2020 01:02
Show Gist options
  • Save frsyuki/5513665 to your computer and use it in GitHub Desktop.
Save frsyuki/5513665 to your computer and use it in GitHub Desktop.
Getting current time in microseconds in MySQL < 5.6

MySQL 5.5 で現在時刻をマイクロ秒の精度で取得する方法

画期的な方法を発見した。MySQL 5.5 の UUID() 関数は、100ナノ秒精度の現在時刻を含んだ UUID v1 を返す(12.15. Miscellaneous Functions)。これをパースすればマイクロ秒精度の現在時刻を取得することができる。

詳しい実装についてはmysqldのソースに書いてあるので読めばいい。mysql-5.5.27/sql/item_strfunc.cc に実装してある。141427日間のオフセットがかかっていたりするので気をつける。

DELIMITER //
CREATE FUNCTION TIMESTAMP_USEC()
RETURNS BIGINT NOT DETERMINISTIC
BEGIN
  set @uuid = UUID();
  set @low = CONV(SUBSTRING(@uuid, 1, 8), 16, 10);
  set @mid = CONV(SUBSTRING(@uuid, 10, 4), 16, 10);
  set @hi = CONV(SUBSTRING(@uuid, 15, 4), 16, 10) - 0x1000;
  set @hnsec = ((@hi << 48) | (@mid << 32) | @low) - (141427*24*60*60 *1000*1000*10);
  RETURN CAST(@hnsec / 10 AS UNSIGNED INTEGER);
END
//
DELIMITER ;

実行結果:

mysql> select timestamp_usec();
+------------------+
| timestamp_usec() |
+------------------+
| 1367612044966701 |
+------------------+
1 row in set (0.00 sec)

mysql> select from_unixtime(timestamp_usec() / 1000/1000);
+---------------------------------------------+
| FROM_UNIXTIME(timestamp_usec() / 1000/1000) |
+---------------------------------------------+
| 2013-05-03 13:26:23                         |
+---------------------------------------------+
1 row in set (0.00 sec)

MySQL 5.6 からは NOW(6) でマイクロ秒精度の現在時刻を取得できるが、この手法を使えばMySQL 5.5でも取得できる。 また、UUIDに含まれるタイムスタンプは、必ず単調に増加するように保証されている。

ただし NOW() とは異なり、1つのSQL文の中で複数回呼ぶと異なる値を返す点には注意が必要。

mysql> select timestamp_usec(), timestamp_usec();
+------------------+------------------+
| timestamp_usec() | timestamp_usec() |
+------------------+------------------+
| 1367612440310252 | 1367612440310292 |
+------------------+------------------+
1 row in set (0.00 sec)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment