問題発生
IDをDBに保持しているが、IDがintを超えた値を持つアプリが発生し、オーバーフローでクラッシュした。
問題の原因
- DB(データベース)では、MySQLを使用
- MySQLでは、データに「文字列」「整数」などの"型"を設定し保存することで、DBの効率性と品質を向上
- 問題が発生したのは「int」型で、これは整数型の一種であり、整数値を4バイト(32ビット)で保存する
- 4バイト(32ビット)で保存している都合上、最大値は2,147,483,647までしか保存できない
- アプリのIDが2,147,483,647を超えたため、オーバーフローエラーが発生し、クラッシュが発生
対応策
IDを保存するデータ型を「int」から「bigint」に変更する。
「bigint」は8バイト(64ビット)で整数を保存し、最大値が9,223,372,036,854,775,807まで拡張される。
これにより、オーバーフローの問題が発生しなくなる。ただし、ストレージ容量が増加する。
MySQLの整数型について
- TINYINT
- 符号付き: -128から127まで
- 符号なし: 0から255まで
- 1バイト(8ビット)を使用
- SMALLINT
- 符号付き: -32,768から32,767まで
- 符号なし: 0から65,535まで
- 2バイト(16ビット)を使用
- MEDIUMINT
- 符号付き: -8,388,608から8,388,607まで
- 符号なし: 0から16,777,215まで
- 3バイト(24ビット)を使用
- INT
- 符号付き: -2,147,483,648から2,147,483,647まで
- 符号なし: 0から4,294,967,295まで
- 4バイト(32ビット)を使用
- BIGINT
- 符号付き: -9,223,372,036,854,775,808から9,223,372,036,854,775,807まで
- 符号なし: 0から18,446,744,073,709,551,615まで
- 8バイト(64ビット)を使用
"INT"の最大値が2,147,483,647である理由
-
INT型の最大値
- 4バイト(32ビット)の整数を格納できる
- 32ビットを使って、符号付き整数(正数と負数の両方を含む)を表現する
- 最初の1ビット(最上位ビット)は符号ビットとして使われ、残りの31ビットで数値を表現する
符号付き整数の場合
- 最上位ビットが0の場合は正の数を、1の場合は負の数を示す
- 残りの31ビットで表現できる整数の最大値は、2の31乗から1を引いた値
- 2^31 - 1 = 2,147,483,648 - 1 = 2,147,483,647
したがって、INT型の最大値は2,147,483,647となります。
同様に、負の数の最小値は、最上位ビットが1で、残りのビットがすべて0です。
これは以下のように計算できます。
-2^31 = -2,147,483,648
よってINT型の範囲は-2,147,483,648から2,147,483,647となる
※整数 2,147,483,647 を32ビット符号付き整数として表現するには、2進数(バイナリ)で次のようになる
→01111111 11111111 11111111 11111111
※整数 -2,147,483,647 を32ビット符号付き整数として表現するには、2進数(バイナリ)で次のようになる
→11111111 11111111 11111111 11111111
デフォルトでBIGINTで記録しない理由
-
データベースで全ての整数型をデフォルトでBIGINT型にすると、必要以上に大きなストレージ容量やリソースを消費することになる
- 特に大規模なデータベースや高いパフォーマンスが求められるシステムでは問題となることが考えられる
- 1つデータを保存するのに、INTと比較して2倍のデータ量が消費される
-
例)整数 2,147,483,647 を32ビットと64ビットで表示した場合
- 32ビット符号付き整数: 01111111 11111111 11111111 11111111
- 64ビット符号付き整数: 00000000 00000000 00000000 00000000 01111111 11111111 11111111 11111111
-
例)1から2,147,483,647までのIDを保存する場合
- 32ビットで保存する場合: 2,147,483,647(個) x 4(バイト) = 8,589,934,588バイト
- 64ビットで保存する場合: 2,147,483,647(個) x 8(バイト) = 17,179,869,176バイト
-
リソース消費量の違い
- 64ビットで保存した場合のストレージ容量は、32ビットで保存した場合のストレージ容量の2倍になる
- 17,179,869,176(バイト) - 8,589,934,588(バイト) = 8,589,934,588バイト
- つまり、1から2,147,483,647までのIDを64ビットで保存する場合、32ビットで保存する場合に比べて、約8.59GB(8,589,934,588バイト)の追加ストレージが必要になる
このため、データベースのストレージ容量やリソースは限られており、ストレージとリソースの効率性を良くするため、多くのアプリケーションでは、INTを使用することが多いです。