概要
golang-migrateはGoエコシステムで広く使われているデータベースマイグレーションツールであり、SQLスクリプトに基づいてデータベースオブジェクトのバージョン移行とロールバックをサポートします。本記事では、golang-migrateを使用してOceanBaseデータベースのMySQLモードテナントに接続し、マイグレーションの作成、実行、検証、およびロールバックを完了する方法について説明します。
バージョン互換性
- OceanBaseデータベース ≥ V4.2.5
- OBProxy ≥ V4.3.1
前提条件
golang-migrateを使用する前に、次のことを確認してください:
- Go環境がインストール済みであること。Goのインストールについては、Go公式インストールドキュメントを参照してください。
- OceanBaseデータベースのデプロイが完了し、MySQLモードのユーザーテナントが作成されていること。ユーザーテナントの作成方法の詳細については、テナントの作成を参照してください。
手順
ステップ1:OceanBaseデータベースの接続文字列を取得する
OceanBaseデータベースのデプロイ担当者から接続文字列を取得します。例:
obclient -h$host -P$port -u$user_name -p$password -D$database_name
パラメータ説明:
$host:接続IPアドレス。ODP接続はODPアドレスを使用し、直接接続はOBServer IPを使用します。$port:接続ポート。ODPのデフォルトは2883、直接接続のデフォルトは2881です。$database_name:データベース名。
注意
テナントに接続するユーザーには、データベースに対する CREATE、INSERT、DROP および SELECT 権限が付与されていなければなりません。その他のユーザー権限の詳細については、MySQLモードの権限分類を参照してください。
$user_name:接続アカウント。ODP形式:ユーザー@テナント#クラスタまたはクラスタ:テナント:ユーザー。直接接続形式:ユーザー@テナント。$password:アカウントのパスワード。
接続文字列の詳細については、OBClientを使用してOceanBaseテナントに接続するを参照してください。
例:
obclient -hxxx.xxx.xxx.xxx -P2881 -utest_user001@mysql001 -p****** -Dtest
ステップ2:migrateコマンドラインツールをインストールする
この記事では、golang-migrate V4.15.2バージョンのインストールを例に説明します。操作は以下のとおりです:
# (オプション)Goモジュールプロキシを設定する
export GOPROXY=https://goproxy.cn,direct
# MySQLドライバを含むmigrateコマンドラインツールをインストールする
go install -tags 'mysql' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.15.2
# Go実行ファイルのディレクトリを現在のセッションのPATHに追加する
export PATH="$PATH:$(go env GOPATH)/bin"
# インストールが成功したかどうかを確認する
migrate -version
永続的に有効にする必要がある場合は、$(go env GOPATH)/bin をシェル起動ファイル(例:~/.zshrc または ~/.bashrc)に追加してください。
ステップ3:マイグレーションファイルを作成する
プロジェクトディレクトリで以下のコマンドを実行し、migrationsディレクトリを作成して一連のマイグレーションファイルを生成します:
migrate create -ext sql -dir migrations -seq init_oceanbase_test
ls -la migrations/
実行が成功すると、migrationsディレクトリに以下のファイルが生成されます:
000001_init_oceanbase_test.up.sql 000001_init_oceanbase_test.down.sql ここで:
- up.sql ファイルはデータベースのアップグレード操作を定義するために使用されます。
- down.sql ファイルはデータベースのロールバック操作を定義するために使用されます。
ステップ4:マイグレーションSQLを作成する
マイグレーションファイル migrations/000001_init_oceanbase_test.up.sql と migrations/000001_init_oceanbase_test.down.sql を編集し、データベースのアップグレードとロールバックのSQLをそれぞれ記述します。
この例でのマイグレーション内容は以下の通りです:
- テーブル、外部キー、インデックスを作成します。
- 初期化データを挿入します。
- 列を追加します。
- ビューを作成します。
- ロールバック時に関連オブジェクトを削除します。
upマイグレーション(000001_init_oceanbase_test.up.sql):
-- ユーザーテーブルを作成
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
status TINYINT DEFAULT 1 COMMENT '1:active, 0:inactive',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ユーザーテーブル';
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_users_created_at ON users(created_at);
-- 注文テーブルを作成
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
order_no VARCHAR(32) NOT NULL UNIQUE,
amount DECIMAL(10,2) NOT NULL DEFAULT 0.00,
status TINYINT DEFAULT 0 COMMENT '0:pending, 1:paid, 2:cancelled',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='注文テーブル';
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_order_no ON orders(order_no);
CREATE INDEX idx_orders_status ON orders(status);
INSERT INTO users (username, email, password_hash) VALUES
('oceanbase_admin', 'admin@demo.com', 'hashed_password_admin'),
('oceanbase_user1', 'user1@demo.com', 'hashed_password_user1'),
('oceanbase_user2', 'user2@demo.com', 'hashed_password_user2');
INSERT INTO orders (user_id, order_no, amount, status) VALUES
(1, 'ORD202401001', 99.99, 1),
(2, 'ORD202401002', 149.50, 0),
(3, 'ORD202401003', 299.00, 1);
-- 商品テーブル、ALTER、ビュー
CREATE TABLE products (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
sku VARCHAR(64) NOT NULL UNIQUE,
name VARCHAR(200) NOT NULL,
price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
stock INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品テーブル';
INSERT INTO products (sku, name, price, stock) VALUES
('SKU-001', 'サンプル商品A', 19.90, 100),
('SKU-002', 'サンプル商品B', 59.00, 50);
ALTER TABLE users ADD COLUMN last_login_at TIMESTAMP NULL DEFAULT NULL COMMENT '最終ログイン時間';
CREATE INDEX idx_products_stock ON products(stock);
CREATE OR REPLACE VIEW v_user_order_stats AS
SELECT
u.id AS user_id,
u.username,
COUNT(o.id) AS order_count,
COALESCE(SUM(o.amount), 0) AS total_amount
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.username;
downマイグレーション(000001_init_oceanbase_test.down.sql):
-- ロールバック時は、ビューと依存関係を削除してからテーブルを削除します。順序はupと逆です。
DROP VIEW IF EXISTS v_user_order_stats;
ALTER TABLE users DROP COLUMN last_login_at;
DROP TABLE IF EXISTS products;
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS users;
ステップ5:OceanBaseへの移行を実行する
(オプション)ODPパラメータを設定する
ODPプロキシポートを介してOceanBaseデータベースに接続する場合は、まずシステムテナントで以下のODPパラメータを設定してください:
ALTER PROXYCONFIG SET proxy_id=1; ALTER PROXYCONFIG SET client_session_id_version=2; ALTER PROXYCONFIG SET enable_single_leader_node_routing = false;パラメータ説明:
proxy_id:ODPインスタンスID。単一ODPインスタンスの場合は1に設定できますが、複数のODPインスタンスをデプロイする場合は、各インスタンスに異なるproxy_idを割り当てる必要があります(例:1、2、3)。client_session_id_version:Client Session IDの生成アルゴリズムを設定します。enable_single_leader_node_routing:標準のOceanBase 2.0プロトコル通信を強制します。
データベース接続をテストする
OBClientまたはMySQLクライアントを使用してターゲットデータベースに接続し、ネットワークとアカウントが正常であることを確認します。例:
obclient -h$host -P$port -u$user_name -p$password -e "SELECT VERSION();"実行結果の例は次のとおりです:
5.7.25-OceanBase-v4.2.5.0アップグレード移行を実行する
以下のコマンドを実行して、移行スクリプトをOceanBaseデータベースに適用します:
migrate -path migrations -database "mysql://$user_name:$password@tcp($host:$port)/$database_name?charset=utf8mb4&parseTime=True&loc=Local" upパラメータ説明:
$host:OceanBaseデータベースの接続IPアドレス。$port:OceanBaseデータベースの接続ポート。ODPを使用して接続する場合、デフォルトポートは2883です。OBServerに直接接続する場合、デフォルトポートは2881です。$user_name:OceanBaseデータベースのユーザー名。$password:OceanBaseデータベースのユーザーパスワード。$database_name:OceanBaseデータベースの名前。
注意
ユーザー名やパスワードに特殊文字が含まれている場合は、事前にURLエンコードしてください。
現在の移行バージョンを確認する
以下のコマンドを実行して、現在データベースに適用されている移行バージョンを確認します:
migrate -path migrations -database "mysql://$user_name:$password@tcp($host:$port)/$database_name?charset=utf8mb4&parseTime=True&loc=Local" version実行結果が
1の場合、現在最初の移行バージョンが適用されています。移行をロールバックする
最近の移行をロールバックする必要がある場合は、以下のコマンドを実行します:
migrate -path migrations -database "mysql://$user_name:$password@tcp($host:$port)/$database_name?charset=utf8mb4&parseTime=True&loc=Local" down 1down 1を実行すると、移行バージョンは0に戻ります。業務テーブルとビューは削除され、schema_migrationsテーブルのみが保持されます。その後、upコマンドを再度実行して移行を再適用できます。
結果の検証
OceanBaseターゲットデータベースに接続し、以下のコマンドを実行して移行結果を確認します:
obclient -h$host -P$port -u$user_name -p$password -D$database_name -e "
SHOW TABLES;
DESCRIBE users;
SELECT * FROM v_user_order_stats LIMIT 5;
SELECT * FROM schema_migrations;
"
移行が成功した場合、期待される結果は以下のとおりです:
- テーブル
users、orders、productsおよびschema_migrationsが存在します。 - ビュー
v_user_order_statsが存在します。 usersテーブルにはlast_login_at列が含まれています。schema_migrationsテーブルには現在の移行バージョンが記録されています。
よくある質問
Q1:migrateコマンドが見つかりません?
原因:GoのbinディレクトリがPATHに追加されていません。
解決策:echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.bashrc または echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.bashrc を実行してから source ~/.bashrc を実行するか、完全パスで migrate を呼び出します。
Q2:接続文字列のユーザー名に@が含まれており、migrateを実行するとエラーが発生します?
原因:データベース接続URLでは、@は予約文字です。ユーザー名に@が含まれており、URLエンコードが行われていない場合、接続文字列の解析に失敗します。
解決策:ユーザー名の @ を %40 に置き換えてからデータベースURLに入力します。例えば、user@tenant を user%40tenant のように書き換えます。