MySQL/MariaDB初心者でも安心!「errno: 121 Duplicate key on write or update」エラーの基礎知識と解決のヒント
MySQL/MariaDB で errno: 121 "Duplicate key on write or update" エラーが発生する原因と解決策
MySQL/MariaDB でテーブルを作成する際、CONSTRAINT
を使用して主キーやユニークキーを定義することがあります。しかし、CONSTRAINT
で定義した制約に違反するようなデータ挿入や更新操作を実行しようとすると、errno: 121 "Duplicate key on write or update"
エラーが発生します。
エラーの原因
このエラーが発生する主な原因は以下の2つです。
主キー/ユニークキーに重複する値を挿入/更新しようとしている
解決策
このエラーを解決するには、以下の方法があります。
重複する値を挿入/更新しない
主キー/ユニークキーの値を変更する
例
以下の例は、主キーに重複する値を挿入しようとした場合のエラーと、IGNORE
オプションを使用することでエラーを回避する方法を示しています。
-- 主キーに重複する値を挿入しようとするとエラーが発生
INSERT INTO users (id, name) VALUES (1, 'John Doe');
-- エラーメッセージ: Duplicate key on write or update
-- IGNORE オプションを使用することでエラーを回避
INSERT IGNORE INTO users (id, name) VALUES (1, 'Jane Doe');
- このエラーは、
UPDATE
文でも発生します。 CONSTRAINT
で定義した制約以外にも、NOT NULL
制約や外部キー制約など、様々な制約違反によってこのエラーが発生する可能性があります。- エラーメッセージの詳細を確認することで、エラーの原因を特定することができます。
補足
この説明は、MySQL/MariaDB の基本的な動作を理解していることを前提としています。もし、MySQL/MariaDB の基本的な知識がない場合は、まずそちらを学習してからこの説明を読むことをお勧めします。
例1:主キーに重複する値を挿入
この例では、users
テーブルに主キー id
を持つレコードを2つ挿入しようとします。2番目のレコードの id
は1ですが、これは1番目のレコードと重複するため、エラーが発生します。
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255)
);
INSERT INTO users (id, name) VALUES (1, 'John Doe');
INSERT INTO users (id, name) VALUES (1, 'Jane Doe');
出力
ERROR 121 (Duplicate key on write or update): Duplicate entry '1' for key 'PRIMARY'
以下のいずれかの方法で解決できます。
- 2番目のレコードの
id
を変更する INSERT
文にIGNORE
オプションを使用する
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255)
);
INSERT INTO users (id, name) VALUES (1, 'John Doe');
INSERT IGNORE INTO users (id, name) VALUES (1, 'Jane Doe');
1 row affected
この例では、users
テーブルの email
列がユニークキーであることを想定しています。email
列に同じ値を持つレコードを2つ更新しようとすると、エラーが発生します。
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255) UNIQUE
);
INSERT INTO users (id, name, email) VALUES (1, 'John Doe', '[email protected]');
INSERT INTO users (id, name, email) VALUES (2, 'Jane Doe', '[email protected]');
UPDATE users SET email = '[email protected]' WHERE id = 1;
ERROR 121 (Duplicate key on write or update): Duplicate entry '[email protected]' for key 'email'
- 更新しようとしているレコードの
email
を変更する
この例では、orders
テーブルと products
テーブルがあり、orders
テーブルの product_id
列は products
テーブルの id
列を参照する外部キー制約であることを想定しています。orders
テーブルに存在しない product_id
を持つレコードを挿入しようとすると、エラーが発生します。
CREATE TABLE products (
id INT PRIMARY KEY
);
CREATE TABLE orders (
id INT PRIMARY KEY,
product_id INT,
FOREIGN KEY (product_id) REFERENCES products(id)
);
INSERT INTO products (id) VALUES (1);
INSERT INTO orders (id, product_id) VALUES (1, 2);
ERROR 145 (Constraint violation): Cannot insert value '2' into 'product_id'. 'product_id' doesn't exist in table 'products'
- 挿入しようとしているレコードの
product_id
を、products
テーブルに存在する値に変更する - 外部キー制約を削除する(非推奨)
これらの例は、errno: 121 "Duplicate key on write or update"
エラーの一般的な原因と解決策を示しています。エラーが発生した場合は、エラーメッセージの詳細を確認し、適切な解決策を選択してください。
- このサンプルコードは、MySQL/MariaDB 8.0.26 で動作確認しています。
- 実際のデータベーススキーマやデータは、状況によって異なる場合があります。
MySQL/MariaDB で errno: 121 "Duplicate key on write or update" エラーを解決するその他の方法
ユニークインデックスを使用する
主キー以外にも、ユニークインデックスを使用して列の重複を防止することができます。ユニークインデックスは、主キーと同様に、列の値が一意であることを保証します。
以下の例では、users
テーブルの email
列にユニークインデックスを作成します。
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
UNIQUE KEY email_idx (email)
);
INSERT
文や UPDATE
文を排他ロックで実行することで、他のトランザクションが同じ行を更新/挿入するのをブロックすることができます。
以下の例では、users
テーブルの id = 1
のレコードを排他ロックで更新します。
BEGIN TRANSACTION;
UPDATE users SET name = 'Jane Doe' WHERE id = 1 FOR UPDATE;
COMMIT;
アプリケーションロジックを変更して、重複するデータを挿入/更新しないようにすることができます。
以下の例は、レコードを挿入する前に、同じレコードが存在しないかどうかをチェックする擬似コードです。
function insertUser(name, email):
if existsUser(email):
error("Email already exists")
return
INSERT INTO users (name, email) VALUES (name, email);
競合解決メカニズムを使用する
データベースによっては、ロックや分散トランザクションなどの競合解決メカニズムを提供している場合があります。これらのメカニズムを使用して、並行実行されるトランザクション間の競合を解決することができます。
注意事項
上記で紹介した方法は、いずれも状況によって適切かどうかを判断する必要があります。例えば、排他ロックを使用すると、データベースのパフォーマンスが低下する可能性があります。また、アプリケーションロジックを変更する場合は、コードが複雑になる可能性があります。
最適な解決策を選択するには
- エラーが発生する頻度と影響範囲
- データベースのパフォーマンス要件
- アプリケーションのアーキテクチャ
などを考慮する必要があります。
errno: 121 "Duplicate key on write or update"
エラーは、様々な原因で発生します。適切な解決策を選択するには、エラーの原因を特定し、状況を考慮する必要があります。
mysql mariadb