はじめに
小さな店が受け取り場所を追加します。旧版の購入クライアントは注文 ID、顧客、整数のセント、メモを渡し、新版は受け取りコードも渡します。既存の注文と商品明細の関係は、引き続き使える必要があります。既定値は列を省略する操作との互換性を保ちますが、過去の顧客が実際にどこで受け取ると決めたかは分かりません。
expand.sql と拡張済みの実際の注文テーブルを用意し、準備済みの両クライアントを使い、データのトランザクションと MySQL DDL の実際の境界を観察します。前提は、基本的なターミナル操作、MySQL の SELECT/WHERE、INSERT/UPDATE、列、主キー、既定値です。Python やアプリ開発は不要です。この独立した単元は専用の Oracle MySQL と Terminal を提供します。一般のデータベースサービスは無関係です。
作業するのは /home/labex/project/pickup-desk だけです。説明された受け取り列を orders に追加し、実演では隔離した ddl_demo だけを更新・拡張できます。元のすべての注文 ID、顧客、金額、メモ、商品明細、受け取り場所、承認テーブル、提供されたツールを保全してください。追加できるのは、以下に指定された練習用の 3 注文だけです。これは制御された保守時間内の作業であり、オンライン、ロックなし、停止時間ゼロの移行ではありません。作者の所要時間の見積もりは読解と通常のミスを含みますが、初心者で計測したものではありません。
両クライアントを使える状態でスキーマを拡張する
このステップでは、通常の旧クライアントの注文を作り、互換性のある受け取り列を追加し、両バージョンのクライアントが作る実際の注文を読みます。
Terminal のシェルプロンプトから始めます。cd は現在のディレクトリを移動し、絶対パスはどの開始ディレクトリからでも使えます。./shop はそのディレクトリの準備済みコマンドを実行します。これらはシェルコマンドであり、MySQL プロンプトへの入力ではありません。
cd /home/labex/project/pickup-desk
./shop status
./shop points
元の注文ヘッダーは 101 / Sam / 2100、102 / Sam / 3400、103 / Lee / 0 で、それぞれメモと商品明細があります。2 つの Sam の注文は別の識別情報を持ちます。金額は整数のセントで、ゼロも有効です。status と show は実際の保存値を読み、レコードを移行したり、受け取り選択を代入したりはしません。
準備済みの旧クライアントは old order_id customer total_cents sku quantity を受け取ります。明示的な旧列名でヘッダーを挿入し、同じネイティブトランザクションで商品明細を挿入します。成功時はコミットし、ネイティブ SQL エラーではバッチを止めて接続を閉じ、保留中のデータ変更をロールバックします。許可された通常注文を作り、読みます。
./shop old 201 Mina 1600 MUG 1
./shop show 201
ヘッダーは ID 201、Mina、1600、Created by legacy client を含み、明細は MUG、数量 1 です。返された pickup_column: false は、このフィールドがまだ導入されていないことを示します。新クライアントは同じ引数の後に受け取りコードを取ります。次は、未知の列 pickup_code を示すネイティブエラー 1054 と非ゼロの終了ステータスで、意図的に失敗する想定です。ヘッダーも明細も残してはいけません。
./shop new 203 Pia 1900 CARD 2 garden
./shop show 203
読み取りではヘッダー・商品明細が空です。列の不在はスキーマエラーであり、未知の受け取りコードでも、正常な空の購入結果でもありません。
明示的な既定値 counter を持つ、NULL を許す新列を追加します。ALTER TABLE は定義を変更し、ADD COLUMN はフィールドを追加します。VARCHAR(16) は短い受け取りコードを保存します。NULL は、この拡張段階で明示的な不明値を一時的に許します。DEFAULT 'counter' は、旧クライアントが列を省略した場合の互換値です。拡張後は既存行にも現れるため、過去の選択の証明ではありません。次の独立した実習では、最終ルールを厳格化する前に、承認済みの履歴を扱います。
完全な SQL ファイルを保存します。cat > expand.sql はこの 1 ファイルを置き換えます。引用符付きヒアドキュメントマーカー 'SQL' は、最後の単独行 SQL までをシェルにそのままコピーさせます。各 SQL 文はセミコロンで終わります。
cat > expand.sql <<'SQL'
ALTER TABLE orders ADD COLUMN pickup_code VARCHAR(16) NULL DEFAULT 'counter';
SQL
apply は、コースの移行ロールを使う 1 つのネイティブ MySQL バッチ接続で、保存したファイルを変更せず実行します。不足した SQL の推測、過去データの補完、修復はしません。
./shop apply expand.sql
./db -e "SHOW COLUMNS FROM orders;"
./db はこのコース専用のデータベースに接続し、-e は続く引用符内の SQL を実行して終了します。二重引用符は空白とセミコロンを 1 つのシェル引数に保ちます。受け取り列の型、NULL 許可、既定値を読みます。varchar(16)、YES、counter です。他の元のフィールドも残ります。
旧クライアントを再度使い、先ほど拒否された新注文も再試行します。
./shop old 202 Omar 1800 BAG 1
./shop new 203 Pia 1900 CARD 2 garden
./shop show 201
./shop show 202
./shop show 203
./shop status
201 と 202 は実際の保存済み既定値 counter、203 は garden を持ちます。すべてのヘッダーと実際の商品行が残ります。元の 3 注文は拡張時の既定値 counter を表示しますが、過去の全注文がそこで受け取られたとは言えません。準備済みの承認対応表は変更しません。
通常の ./shopp の入力ミスでは、ls を実行し、正しい名前の ./shop を使います。SQL が構文エラーなら、cat expand.sql を確認して保存した文全体を直し、列がまだない場合だけ適用します。拡張の再実行でエラー 1060 が出たら、列はすでに存在します。列の削除やデータベースのリセットではなく、SHOW COLUMNS を確認します。成功した注文を繰り返すと ID 重複エラーになるため、別の ID を作らず、既存注文を show で読みます。指定された許可注文と元データを保ってください。
ロールバックで取り消せないものを観察する
このステップでは、注文システムを保全しつつ、別の実演テーブルでネイティブな ALTER の境界を観察します。
Terminal の /home/labex/project/pickup-desk で続けます。ddl_demo は、すべての注文と別に設けた、明示的に使い捨ての 1 行の教材テーブルです。初期メモは original です。
./db -e "SELECT * FROM ddl_demo;"
トランザクションは、COMMIT または ROLLBACK までデータ変更をまとめます。START TRANSACTION は開始、UPDATE は選択行の変更、ROLLBACK は通常、未コミットのデータ変更の破棄です。ALTER TABLE を含む MySQL DDL(データ定義言語)には暗黙のコミット境界があります。ALTER は定義変更前に先行作業をコミットし、後のユーザーの ROLLBACK では取り消せません。アトミック DDL の復旧と、ユーザーが DDL をロールバックできることは別です。
次のファイルは、この実演メモだけを意図的に変更してから、NULL を許す整数列 extra を追加します。その後 ROLLBACK を要求します。実行前に、メモと新列が残るか予想してください。
cat > ddl-demo.sql <<'SQL'
START TRANSACTION;
UPDATE ddl_demo SET note='committed before ALTER' WHERE id=1;
ALTER TABLE ddl_demo ADD COLUMN extra INT NULL;
ROLLBACK;
SQL
./shop apply ddl-demo.sql
./db -e "SELECT * FROM ddl_demo;"
./db -e "SHOW COLUMNS FROM ddl_demo;"
行のメモは committed before ALTER のままで、extra は NULL です。SHOW COLUMNS にも extra が残ります。先行するデータ UPDATE は ALTER によってコミットされ、新定義も残ります。ROLLBACK が成功しても、取り消されてはいません。作り物の出力ファイルではなく、実際のサーバーの動作です。
実際の注文を再度読みます。
./shop show 101
./shop show 201
./shop show 203
元のヘッダー値、メモ、商品明細、保存済み受け取りコードは残っています。この実演を注文メモに対して行わないでください。実際の移行では、トランザクションで行うデータ補完と、後の厳格化 DDL を分け、保守と修復の境界をそれに合わせて計画します。すべての ALTER を BEGIN に入れても、自動ロールバックは得られません。
実演ファイルは、説明された初期定義から 1 回実行するスクリプトです。誤って 2 回実行すると、extra はすでに存在します。実際の定義と行を確認し、2 回目を新規実行に見せるためにテーブルを削除しないでください。最初の適用成功前の入力ミスは、完全なブロックをコピーして直します。この単元の到達点は、互換性のある拡張と正直な DDL 観察であり、継続的な本番トラフィック下での配備を主張するものではありません。
まとめ
互換性のある注文テーブルの拡張を用意し、実際の旧・新クライアントの書き込みを観察し、元の注文詳細を保全しました。隔離したネイティブな実験で、ROLLBACK が成功しても ALTER と、その前にコミットされたデータ変更を取り消せない理由を確認しました。過去の受け取り選択には、次に学ぶ承認済みの対応表がまだ必要です。



