MySQL道普請便り

第254回知っておくと得するかもしれないMySQLの組み込み関数(その2)

今回は以前紹介した第248回 知っておくと得するかもしれないMySQLの組み込み関数「その2」として、⁠知っておくと得する」可能性のある関数を、再びいくつかピックアップしてご紹介します。

MD5() / SHA2()関数

MD5()とSHA2()関数は、文字列をハッシュ化するための関数です。どちらも「暗号化」ではなく、入力から一方向で固定長の値を算出する要約関数です。

MD5()関数は引数文字列をMD5アルゴリズム(128ビット)でハッシュ化し、32文字の16進文字列を返します。

mysql>  SELECT MD5('aaa');
+----------------------------------+
| MD5('aaa')                       |
+----------------------------------+
| 47bce5c74f589f4867dbd57e9ca9f808 |
+----------------------------------+
1 row in set (0.00 sec)

SHA2()関数はSHA-2アルゴリズムでハッシュ値を返し、引数にビット長を指定して異なる長さのハッシュ(224 / 256 / 384 / 512)を返します。

mysql>  SELECT SHA2('aaa',256);
+------------------------------------------------------------------+
| SHA2('aaa',256)                                                  |
+------------------------------------------------------------------+
| 9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0 |
+------------------------------------------------------------------+
1 row in set (0.01 sec)

これらの関数は、データの整合性チェックに活用できます。たとえば、通常プライマリーとレプリカのデータは同一であるべきですが、誤操作などで不一致が起きる可能性があります。すべてのデータを目視で確認することは困難です。そこで、行のデータをCONCAT()でまとめてハッシュ化し、プライマリとレプリカで比較します。

mysql> SELECT md5(concat(user,host)) FROM user ORDER BY user LIMIT 5;
+----------------------------------+
| md5(concat(user,host))           |
+----------------------------------+
| 8a4fdc53ee19786fce19f765e0c06099 |
| d4addca5b72e136f051c76fa64d67511 |
| 4de58b5b61f86e2a8ce89ad0e542860e |
| 599b40c9be4237ec4fe0ee5844939f3c |
| b7f7f71494e47b0a09caa2e73a8b65ab |
+----------------------------------+
5 rows in set (0.00 sec)

これにより「行単位で一致しているか」を簡単に確認できます。

また、現場では、MySQLの出力を直接OSコマンドに渡してテーブル全体の整合性を確認する方法もよく使われます。

以下はmysqlコマンドラインクライアントのpagerサブコマンドを使って、OSのmd5コマンドに渡してハッシュ値を取得する例です。pagerサブコマンドについては 第6回 mysqlコマンドラインクライアントにページャーを指定するをご確認ください。

mysql> pager md5sum
mysql> SELECT * FROM user ORDER BY user;
2a1b2fa62aaca511bd1740f52ab15d08  -
16 rows in set (0.00 sec)

これでテーブル全体のハッシュ値を取得し、プライマリとレプリカの結果を比較できます。もし差異が見つかった場合は、前述の行単位のハッシュで差分を特定するのが実用的です。

MD5()とSHA2()関数のそれぞれの特徴としては以下が挙げられます。

  • MD5() …軽量で速いが、セキュリティには弱い。チェックサムや一意性確認向いている
  • SHA2() …セキュリティ強度が高く、パスワードやデータ保護にも利用可能

FIELD()関数

FIELD関数は特定の文字列がカンマ区切りで指定した文字列の中から何番目に一致したかを「1から始まる位置番号」で返します。構文としては以下の通りです。

FIELD(str, str1, str2, str3, ...)

strが str1, str2, …の中で何番目に一致しているかを返し、一致しなければ0を返します。

次の例は文字列bの一致する位置情報を確認しています。

mysql> SELECT FIELD('b', 'a', 'b', 'c');
+---------------------------+
| FIELD('b', 'a', 'b', 'c') |
+---------------------------+
|                         2 |
+---------------------------+
1 row in set (0.00 sec)

FIELD関数の主な使いどころとして、ORDER BY句に用いるとことで任意の順番で並びを作ることができます。

mysql> SELECT task, priority
FROM todo_list
ORDER BY FIELD(priority, 'high', 'medium', 'low');

この例では、priorityが high → medium → low の順で並びます。通常のORDER BYだと辞書順となり「high, low, medium」と並んでしまうので、FIELD()で意図通りの並び替えが可能です。

CONNECTION_ID()関数

CONNECTION_ID()関数は現在のセッション(クライアント接続)に対して、MySQLサーバーが割り当てている一意の整数ID(コネクションID)を返します。SHOW PROCESSLIST;で表示される「Id」列と同じ値が返されます。

mysql> SELECT connection_id();
+-----------------+
| connection_id() |
+-----------------+
|               8 |
+-----------------+
1 row in set (0.00 sec)

この関数は、特定のクライアントセッションを識別する際に役立ちます。長時間実行中のクエリや不要なセッションを終了させるKILL <id>ときに利用されるほか、アプリケーションのログにCONNECTION_ID()を記録しておけば、performance_schemaやサーバーログと突き合わせてトラブルシューティングに活用できます。

他の利用方法としては、行へのアクセスが集中して「ホットスポット」となりロック競合が発生するケースに対して用いられることがあります。たとえば、記事ごとの閲覧数をカウントアップする処理を以下のように実装した場合です(ここでは説明を簡単にするためにUPDATE文としています。本来はINSERT INTO DUPLICATE UPDATE文が望ましいです⁠⁠。

mysql> UPDATE article_counter 
       SET counter=counter+1 
       WHERE article_id=1;

注目度の高い記事にアクセスが集中すると、article_id=1の行に更新が殺到し、ロックの競合によって処理が滞る可能性があります。この競合を分散させるための一案として、CONNECTION_ID()をキーの一部として利用する方法があります。テーブルにconnection_idカラムを追加し、次のように更新します。

mysql> UPDATE article_counter 
       SET counter=counter+1 
       WHERE article_id=1 AND connection_id=CONNECTION_ID();

こうすることで、セッションごとに別の行に分散され、同一行へのロック競合を回避できます。

注意点として以下があります。

  • この方法は コネクションプーリングを利用している場合に限り有効 です。都度接続を張る方式だと接続ごとにCONNECTION_ID()の値が変わり、行が増えすぎてしまいます。
  • アプリケーションや設計によっては「記事ごとに単一カウンタを維持する必要がある」ケースもあるため、その場合は別の手法(非同期集計、シャーディングなど)を検討してください。
  • あくまで「アクセス集中を緩和するテクニックのひとつ」として理解するのが安全です。

まとめ

今回は知っておくと得するかもしれないMySQLの組み込み関数として、MySQLの組み込み関数の中から4つの関数を紹介しました。

  • MD5() / SHA2():文字列をハッシュ化するための関数
  • FIELD():並び順制御や検索で便利
  • CONNECTION_ID():一意の整数ID(コネクションID)を返す

この他にも、MySQLには多種多様な関数が用意されています。興味のある方は公式ドキュメント 14.1 Built-In Function and Operator Referenceを参照してみてください。

おすすめ記事

記事・ニュース一覧