前回(DB2のインストール )新しくDB2をインストールしましたので、早速バックアップとリカバリコマンドを使ってみたいと思います。
まずは現状の確認を。データベース全体を見ていくと大変なので、"staff"テーブルを対象としていきます。
テーブルの設計については"DESCRIBE TABLE table_name"で確認することができます。
中身については全件選択してみましょう。"SELECT * FROM STAFF"
35レコードあります。
では、データベースのバックアップです。"BACKUP DATABASE SAMPLE TO backup_directory"
バックアップファイルはコマンドに指定したフォルダーに作成されます。
今回は下記のファイル名で作成されました。
"SAMPLE.0.DB2.NODE0000.CATN0000.20090923183402.001"
ファイル名の意味は下記の通りになります。
Alias.Type.Instance.Node.Catalogue.YYYYMMDDHHMMSS.Sequence
<IBM Developer Worksの「IBM DB2 UDBとOracleのバックアップおよびリカバリーの比較: 第 1 回」を参照>
それでは、どきどきしながらも、サクッとテーブルを消します。
"DROP TABLE STAFF"
ちゃんと消えてます。
消えました・・・
でも、バックアップをとっているので安心です。すかさずテーブルを復旧してみましょう。
"RECOVERY DATABASE SAMPLE TO END OF LOGS"
SQLエラーが出たのでInformation Centerを見てみた。
「
SQL1260N
データベース name は、ノード node-list でのロールフォワード・リカバリー用に構成されていません。
説明
指定されたデータベースは指定されたノードで、ロールフォワード・リカバリー用に構成されません。 ",..." がノード・リストの終わりに表示されている場合、ノードの完全なリストを見るには管理通知ログを調べてください。
データベースは指定のノードでロールフォワードされません。
(注: パーティション・データベース・サーバーを使用している場合、 ノード番号は、エラーの発生しているノードを示しています。 そうでない場合、これは関係のないものなので無視してください。)
ユーザーの処置
指定ノードでリカバリーが必要か確認して、 次にこのノードでデータベースの最新のバックアップ・バージョンをリストアしてください。
」
RECOVERYコマンドは"RESTORE DATABASE + ROLLFORWARD"なので、ROLLFORWARDしてくれようとしたんだと思います。次回確認しようと思います。
テーブルとデータは以前の通りに戻っているでしょうか?
戻っていますね。よかった。
BACKUPコマンドは、バックアップした場所の物理的な場所を覚えているため、RECOVERYコマンドを実行するときにバックアップファイルを指定する必要がありません。
ただ、バックアップファイルを移動したりしてコマンドを実行したときと違う場所に移動した場合にはRECOVERYコマンドが失敗します。
Information Centerを見てみた。
「
SQL2542N
指定されたソース・データベースの別名 database-alias とタイム・スタンプ timestamp に一致する、データベース・イメージ・ファイルがありません。
説明
バックアップ・イメージ・ファイルのファイル名は、データベース別名とタイム・スタンプのコンポーネントで構成されています。ファイル名は、ソース・データベース別名と、Database Restore 呼び出しに指定されたタイム・スタンプ・パラメーターから作成されます。 指定されたソース・データベースの別名とタイム・スタンプに一致する ファイル名が、ソース・ディレクトリーに存在しません。
以下の状態が適用される可能性があります。
1.バックアップへのパスがリストア・コマンドで誤って指定された。
2.バックアップ・イメージ、またはバックアップ・イメージがあるディレクトリーにアクセスする許可がない。
3.自動増分リストア操作を実行しており、データベース履歴内のタイム・スタンプとロケーションに基づいて必要イメージが見つからなかった。
4.パーティション・データベース環境でデータベースをリストアしており、そのデータベースがもう存在せず、さらにリストアされる最初のデータベース・パーティションがカタログ・パーティションではない。
5.TSM メディアからリストアしようとしており、現在のインスタンスにより使用される TSM API クライアント構成はバックアップ・イメージにアクセスできない。
ユーザーの処置
上記の状態に対する適切な応答は以下のとおりです。
1.データベース・バックアップ・イメージが、メディア・ソースに 存在することを確認してください。 結果的に一致するバックアップ・イメージへの正しいパスおよび正しいタイム・スタンプを指定して、操作を 再サブミットしてください。 リストア・コマンドの使用についての詳細は、DB2 インフォメーション・センターで、"using restore database utility" などの語句を使用して検索してください。
2.バックアップ・イメージ、およびバックアップ・イメージがあるディレクトリーにアクセスする許可があることを確認してください。
3.データベース履歴を調べて対応するバックアップ項目を確かめてから、 リストされているロケーションがバックアップ・イメージの実際のロケーションに一致することを確認してください。 データベース履歴を更新して、結果が一致するように操作をやり直すか、 または RESTORE INCREMENTAL ABORT コマンドを発行して、処理中に作成されたリソースをすべてクリーンアップしてください。
4.パーティション・データベースをリストアするときには、常にカタログ・パーティションを最初にリストアしてください。パーティション・データベース環境でのリストアについての詳細は、DB2 インフォメーション・センターで、"restore utility partitioned database" などの語句を使用して検索してください。
5.イメージを TSM から取得できるかを検査するには、db2adutl ユーティリティーに QUERY オプションを付けて使用します。別のサーバー上の別のインスタンスから取得したバックアップ・イメージをリストアする場合、オプション NODENAME、OWNER を必ず使用してください。またオプションで、バックアップ・イメージが最初にとられた TSM ノードの TSM 設定に対応する PASSWORD を使用してください。イメージを取得できることの確認が完了すると、同じオプションを RESTORE コマンドのオプション・ストリングに渡すことができます。db2adutl ユーティリティーについての詳細は、DB2 インフォメーション・センターで、"db2adutl" などの語句を使用して検索してください。
」
フォルダーへの定期バックアップであればバックアップファイルが見あたらないと言うことはないのでしょうが、テープから戻す場合には出やすいのかもしれませんね。
ログファイル・ヒストリーファイルを指定する項目があるので指定間違いの際にも出るでしょう。ログファイル・ヒストリーファイルをいじったパターンも試してみることにします。
まずは現状の確認を。データベース全体を見ていくと大変なので、"staff"テーブルを対象としていきます。
テーブルの設計については"DESCRIBE TABLE table_name"で確認することができます。
中身については全件選択してみましょう。"SELECT * FROM STAFF"
35レコードあります。
では、データベースのバックアップです。"BACKUP DATABASE SAMPLE TO backup_directory"
バックアップファイルはコマンドに指定したフォルダーに作成されます。
今回は下記のファイル名で作成されました。
"SAMPLE.0.DB2.NODE0000.CATN0000.20090923183402.001"
ファイル名の意味は下記の通りになります。
Alias.Type.Instance.Node.Catalogue.YYYYMMDDHHMMSS.Sequence
<IBM Developer Worksの「IBM DB2 UDBとOracleのバックアップおよびリカバリーの比較: 第 1 回」を参照>
それでは、どきどきしながらも、サクッとテーブルを消します。
"DROP TABLE STAFF"
ちゃんと消えてます。
消えました・・・
でも、バックアップをとっているので安心です。すかさずテーブルを復旧してみましょう。
"RECOVERY DATABASE SAMPLE TO END OF LOGS"
SQLエラーが出たのでInformation Centerを見てみた。
「
SQL1260N
データベース name は、ノード node-list でのロールフォワード・リカバリー用に構成されていません。
説明
指定されたデータベースは指定されたノードで、ロールフォワード・リカバリー用に構成されません。 ",..." がノード・リストの終わりに表示されている場合、ノードの完全なリストを見るには管理通知ログを調べてください。
データベースは指定のノードでロールフォワードされません。
(注: パーティション・データベース・サーバーを使用している場合、 ノード番号は、エラーの発生しているノードを示しています。 そうでない場合、これは関係のないものなので無視してください。)
ユーザーの処置
指定ノードでリカバリーが必要か確認して、 次にこのノードでデータベースの最新のバックアップ・バージョンをリストアしてください。
」
RECOVERYコマンドは"RESTORE DATABASE + ROLLFORWARD"なので、ROLLFORWARDしてくれようとしたんだと思います。次回確認しようと思います。
テーブルとデータは以前の通りに戻っているでしょうか?
戻っていますね。よかった。
BACKUPコマンドは、バックアップした場所の物理的な場所を覚えているため、RECOVERYコマンドを実行するときにバックアップファイルを指定する必要がありません。
ただ、バックアップファイルを移動したりしてコマンドを実行したときと違う場所に移動した場合にはRECOVERYコマンドが失敗します。
Information Centerを見てみた。
「
SQL2542N
指定されたソース・データベースの別名 database-alias とタイム・スタンプ timestamp に一致する、データベース・イメージ・ファイルがありません。
説明
バックアップ・イメージ・ファイルのファイル名は、データベース別名とタイム・スタンプのコンポーネントで構成されています。ファイル名は、ソース・データベース別名と、Database Restore 呼び出しに指定されたタイム・スタンプ・パラメーターから作成されます。 指定されたソース・データベースの別名とタイム・スタンプに一致する ファイル名が、ソース・ディレクトリーに存在しません。
以下の状態が適用される可能性があります。
1.バックアップへのパスがリストア・コマンドで誤って指定された。
2.バックアップ・イメージ、またはバックアップ・イメージがあるディレクトリーにアクセスする許可がない。
3.自動増分リストア操作を実行しており、データベース履歴内のタイム・スタンプとロケーションに基づいて必要イメージが見つからなかった。
4.パーティション・データベース環境でデータベースをリストアしており、そのデータベースがもう存在せず、さらにリストアされる最初のデータベース・パーティションがカタログ・パーティションではない。
5.TSM メディアからリストアしようとしており、現在のインスタンスにより使用される TSM API クライアント構成はバックアップ・イメージにアクセスできない。
ユーザーの処置
上記の状態に対する適切な応答は以下のとおりです。
1.データベース・バックアップ・イメージが、メディア・ソースに 存在することを確認してください。 結果的に一致するバックアップ・イメージへの正しいパスおよび正しいタイム・スタンプを指定して、操作を 再サブミットしてください。 リストア・コマンドの使用についての詳細は、DB2 インフォメーション・センターで、"using restore database utility" などの語句を使用して検索してください。
2.バックアップ・イメージ、およびバックアップ・イメージがあるディレクトリーにアクセスする許可があることを確認してください。
3.データベース履歴を調べて対応するバックアップ項目を確かめてから、 リストされているロケーションがバックアップ・イメージの実際のロケーションに一致することを確認してください。 データベース履歴を更新して、結果が一致するように操作をやり直すか、 または RESTORE INCREMENTAL ABORT コマンドを発行して、処理中に作成されたリソースをすべてクリーンアップしてください。
4.パーティション・データベースをリストアするときには、常にカタログ・パーティションを最初にリストアしてください。パーティション・データベース環境でのリストアについての詳細は、DB2 インフォメーション・センターで、"restore utility partitioned database" などの語句を使用して検索してください。
5.イメージを TSM から取得できるかを検査するには、db2adutl ユーティリティーに QUERY オプションを付けて使用します。別のサーバー上の別のインスタンスから取得したバックアップ・イメージをリストアする場合、オプション NODENAME、OWNER を必ず使用してください。またオプションで、バックアップ・イメージが最初にとられた TSM ノードの TSM 設定に対応する PASSWORD を使用してください。イメージを取得できることの確認が完了すると、同じオプションを RESTORE コマンドのオプション・ストリングに渡すことができます。db2adutl ユーティリティーについての詳細は、DB2 インフォメーション・センターで、"db2adutl" などの語句を使用して検索してください。
」
フォルダーへの定期バックアップであればバックアップファイルが見あたらないと言うことはないのでしょうが、テープから戻す場合には出やすいのかもしれませんね。
ログファイル・ヒストリーファイルを指定する項目があるので指定間違いの際にも出るでしょう。ログファイル・ヒストリーファイルをいじったパターンも試してみることにします。
先日勉強したDB2の管理コマンドを勉強するためにまずDB2をインストールした。
IBMのサイトからDB2-Expressをダウンロードし、任意のフォルダーに解凍。念のため、インストール前提条件を満たしているかを確認。
imageフォルダーにあるdb2prereqcheck.batをコマンドウィンドウで実行します(ダブルクリックでも動きますが、結果表示をした瞬間にウィンドウが閉じてしまいます・・・)。
"Installation Prereq is OK."
と表示されればシステム要件を満たしています。
それではsetup.exeを実行します。まずはランチパッド(LaunchPad)が起動しますが、ここではDB2の情報を教えてくれているだけなのでいきなり「製品のインストール」をクリックし、「新規インストール」ボタンをクリックしてしまいます。
やっとインストールのメニューが始まります。
ライセンス条項にはもちろん同意しましょう。
特にインストールにこだわりはないのでとりあえずは標準インストールをします。
何がインストールされるのかを確認するには「フィーチャーの表示(V)...」をクリックします。なぜかここだけテキストベースです。
応答ファイルを作成するかを選択できます。もし、この後何台にもインストールする必要があるのであれば、応答ファイルを作って、サイレントインストールするのが良いでしょう。
インストールフォルダーの選択。
DB2 Administration Server(DAS)のアカウント設定。
インスタンスの設定。
ポート番号や起動について設定できます。
インストール内容の確認。
インストールが終わりました。
Visual Studio用のアドインが用意されていました。今回は必要ないのでスルーします。
インストールが終了すると、ファースト・ステップが起動します。ローカルにインフォメーション・センターがインストールされず、インターネットにもつながらないのでエラーが出ましたが問題ないです。
自分で一からデータベースを作るのは大変なので、「SAMPLEデータベースの作成」ボタンを押して用意されているサンプルを使います。
SAMPLEデータベースの詳細設定を決めます。
1分半で終了です。
これでひとまずテスト環境ができました。
IBMのサイトからDB2-Expressをダウンロードし、任意のフォルダーに解凍。念のため、インストール前提条件を満たしているかを確認。
imageフォルダーにあるdb2prereqcheck.batをコマンドウィンドウで実行します(ダブルクリックでも動きますが、結果表示をした瞬間にウィンドウが閉じてしまいます・・・)。
"Installation Prereq is OK."
と表示されればシステム要件を満たしています。
それではsetup.exeを実行します。まずはランチパッド(LaunchPad)が起動しますが、ここではDB2の情報を教えてくれているだけなのでいきなり「製品のインストール」をクリックし、「新規インストール」ボタンをクリックしてしまいます。
やっとインストールのメニューが始まります。
ライセンス条項にはもちろん同意しましょう。
特にインストールにこだわりはないのでとりあえずは標準インストールをします。
何がインストールされるのかを確認するには「フィーチャーの表示(V)...」をクリックします。なぜかここだけテキストベースです。
応答ファイルを作成するかを選択できます。もし、この後何台にもインストールする必要があるのであれば、応答ファイルを作って、サイレントインストールするのが良いでしょう。
インストールフォルダーの選択。
DB2 Administration Server(DAS)のアカウント設定。
インスタンスの設定。
ポート番号や起動について設定できます。
インストール内容の確認。
インストールが終わりました。
Visual Studio用のアドインが用意されていました。今回は必要ないのでスルーします。
インストールが終了すると、ファースト・ステップが起動します。ローカルにインフォメーション・センターがインストールされず、インターネットにもつながらないのでエラーが出ましたが問題ないです。
自分で一からデータベースを作るのは大変なので、「SAMPLEデータベースの作成」ボタンを押して用意されているサンプルを使います。
SAMPLEデータベースの詳細設定を決めます。
1分半で終了です。
これでひとまずテスト環境ができました。
Club DB2ナイト・サークルに参加してきました。講師は生粋の(?)千葉っ子、高橋さん。
【管理ツール編】という募集だったのですが、実は【運用管理編】でした。
あまり詳しく知らないのに運用管理なんて・・・と思いましたが、勉強したことはたったの三つ。
・バックアップ(backup)
・表の再編成(reorg)
・統計情報の更新(runstats)
DB2の資格研修で勉強したことがあるのでおおよその動きを知っている言葉達だったので良かったです。
初っぱなに「ずきっ」と来た言葉。
『DB管理者の仕事で一番大切なのはバックアップです。で、RAIDはバックアップではありません。』
よ~く知っております。知っていますけどたぶんうちの現場では、外部ディスク装置を使い始めてからバックアップをとっていないのではないかなと思われます(災対機にデータを移行するためにダンプをとっていますが、それはバックアップに入るかしら?)。
バックアップの名称が少し気になりました。
通常、フルバックアップ(full backup)の後に差分バックアップ(incremental backup)と増分バックアップ(differential backup)を単独もしくは組み合わせで使うと思いますが、DB2ではここで言う差分バックアップを「デルタバックアップ(incremental delta)」と呼び、増分バックアップを「累積バックアップ(incremental)」と呼ぶんだそうです。
表の再編成はすぐにコマンドが出てくるくらい気になる作業です。たま~にこの言葉が聞こえてくるとうきうきしてきます。実作業を見たことはないんですが。
表の再編成には二種類あって、一つは、テーブルを一時領域にコピーし、再編成をしながら元の領域に戻していく「シャドー・コピー」。もう一つは、PCのデフラグのように空きスペースを少しずつ動かしながら行う「インプレース」。
統計情報の更新についてはかなり駆け足でしたが、DB2 9.1から自動runstatsはデフォルトONだそうです。
大規模DBなどにおいてアクセス・プランが変わってしまうのがいやであれば忘れずに自動化機能をOFFにするようにと注意がありました。"db2look -m"で統計情報のDDLをバックアップできるのでrunstatsする場合にはとっておくのも手だと言うことです。
大規模DBを触ったことがないのでイメージがつきませんが、アクセス・プランが変わることでどれくらいSQLのパフォーマンスが変わるのか体感してみたいです(そもそもここで言う大規模ってどのくらいのDBなのだろう?)。
この連休中にバックアップ・リストアくらいは試してみようかな。
【管理ツール編】という募集だったのですが、実は【運用管理編】でした。
あまり詳しく知らないのに運用管理なんて・・・と思いましたが、勉強したことはたったの三つ。
・バックアップ(backup)
・表の再編成(reorg)
・統計情報の更新(runstats)
DB2の資格研修で勉強したことがあるのでおおよその動きを知っている言葉達だったので良かったです。
初っぱなに「ずきっ」と来た言葉。
『DB管理者の仕事で一番大切なのはバックアップです。で、RAIDはバックアップではありません。』
よ~く知っております。知っていますけどたぶんうちの現場では、外部ディスク装置を使い始めてからバックアップをとっていないのではないかなと思われます(災対機にデータを移行するためにダンプをとっていますが、それはバックアップに入るかしら?)。
バックアップの名称が少し気になりました。
通常、フルバックアップ(full backup)の後に差分バックアップ(incremental backup)と増分バックアップ(differential backup)を単独もしくは組み合わせで使うと思いますが、DB2ではここで言う差分バックアップを「デルタバックアップ(incremental delta)」と呼び、増分バックアップを「累積バックアップ(incremental)」と呼ぶんだそうです。
表の再編成はすぐにコマンドが出てくるくらい気になる作業です。たま~にこの言葉が聞こえてくるとうきうきしてきます。実作業を見たことはないんですが。
表の再編成には二種類あって、一つは、テーブルを一時領域にコピーし、再編成をしながら元の領域に戻していく「シャドー・コピー」。もう一つは、PCのデフラグのように空きスペースを少しずつ動かしながら行う「インプレース」。
統計情報の更新についてはかなり駆け足でしたが、DB2 9.1から自動runstatsはデフォルトONだそうです。
大規模DBなどにおいてアクセス・プランが変わってしまうのがいやであれば忘れずに自動化機能をOFFにするようにと注意がありました。"db2look -m"で統計情報のDDLをバックアップできるのでrunstatsする場合にはとっておくのも手だと言うことです。
大規模DBを触ったことがないのでイメージがつきませんが、アクセス・プランが変わることでどれくらいSQLのパフォーマンスが変わるのか体感してみたいです(そもそもここで言う大規模ってどのくらいのDBなのだろう?)。
この連休中にバックアップ・リストアくらいは試してみようかな。
DB2
Club DB2 | IBMのDB2の人たちが開催している勉強会 |
Unofficial DB2 BLOG | Club DB2のメンバーの一人が作っているブログ |
先週の土曜日にIBMのDB2チームが開催しているClub DB2の『【土曜開催】 さわってみよう DB2 9.7』に参加してきました。
なぜかDB2の上位資格を持っている私ですが、実際にはほとんどDB2に触れたことがありません。試験対策本やDB2新機能の本を読んで楽しんでいるので多少は知っているつもり。
データベースってなんだか不思議な気がしてとても興味を持っているのですが、せいぜいSQLを書くくらいです(前の現場では4000行を超えるSQLを書いたことがあります)。
今回のハンズオンは題名からわかるとおり、どちらかというと初心者向けの会でした。会の流れとしては、まず「DBやSQLってどんな感じのものなの?」というお話を聞いて、後は用意されたテキストに沿ってSQLのお勉強+DB2と仲良くなる時間となっていました。終了時間までは何をしてもOK!
SQLはだいたい知っているのでテキストはすぐに終わりました。ですので、普段触ることのないDB2でいろいろ遊んでいました。
・fromテーブルの作成
DB2ではSQLの単語をテーブル名やカラム名に設定できると言うことを聞いていたので試してみました。
CREATE TABLE FROM(
SELECT SMALLINT,
FROM SMALLINT,
WHERE SMALLINT,
GROUP_BY SMALLINT,
ORDER_BY SMALLINT
);
そして、適当なデータを挿入し、SELECT。
SELECT FROM FROM FROM
とか
SELECT SELECT FROM FROM WHERE WHERE ORDER BY ORDER_BY
という実務で発見したらぶちぎれそうなSQLを実行して楽しみました。
・新ロック機能"CS with CC"の体験
何という言葉の短縮形だかは忘れてしまいましたが(CCは"Currently Committed")、Oracleに近い動きができるように追加されたらしいです。
DB2の元々の動きとしては、テーブルAのデータをUPDATEして未コミット状態でいる場合、ほかのユーザーがテーブルAをSELECTしてもロックがかかっている状態なのでデータの取得ができません。
今回新しく追加されたこの機能を有効にした後に上記と同じSQLを実行すると、変更前のデータを読み込んできてくれます。
これが良いか悪いかは現場によりますね。
・CLP Plus
なんだかOracleに迎合しているような気がしますが、SQL *Plusにかなり近い感じでオペレーションすることができます。
dual表を使用することもできますし、表示レイアウトをOracleのコマンドで設定することもできます("set pages"や"set lin"など)。
お勉強が終わったらIBMの人と、Club DB2に参加した人たちとの懇親会に行きました。
土曜日に勉強・・・という感じですが、達成感のある午後でした。
なぜかDB2の上位資格を持っている私ですが、実際にはほとんどDB2に触れたことがありません。試験対策本やDB2新機能の本を読んで楽しんでいるので多少は知っているつもり。
データベースってなんだか不思議な気がしてとても興味を持っているのですが、せいぜいSQLを書くくらいです(前の現場では4000行を超えるSQLを書いたことがあります)。
今回のハンズオンは題名からわかるとおり、どちらかというと初心者向けの会でした。会の流れとしては、まず「DBやSQLってどんな感じのものなの?」というお話を聞いて、後は用意されたテキストに沿ってSQLのお勉強+DB2と仲良くなる時間となっていました。終了時間までは何をしてもOK!
SQLはだいたい知っているのでテキストはすぐに終わりました。ですので、普段触ることのないDB2でいろいろ遊んでいました。
・fromテーブルの作成
DB2ではSQLの単語をテーブル名やカラム名に設定できると言うことを聞いていたので試してみました。
CREATE TABLE FROM(
SELECT SMALLINT,
FROM SMALLINT,
WHERE SMALLINT,
GROUP_BY SMALLINT,
ORDER_BY SMALLINT
);
そして、適当なデータを挿入し、SELECT。
SELECT FROM FROM FROM
とか
SELECT SELECT FROM FROM WHERE WHERE ORDER BY ORDER_BY
という実務で発見したらぶちぎれそうなSQLを実行して楽しみました。
・新ロック機能"CS with CC"の体験
何という言葉の短縮形だかは忘れてしまいましたが(CCは"Currently Committed")、Oracleに近い動きができるように追加されたらしいです。
DB2の元々の動きとしては、テーブルAのデータをUPDATEして未コミット状態でいる場合、ほかのユーザーがテーブルAをSELECTしてもロックがかかっている状態なのでデータの取得ができません。
今回新しく追加されたこの機能を有効にした後に上記と同じSQLを実行すると、変更前のデータを読み込んできてくれます。
これが良いか悪いかは現場によりますね。
・CLP Plus
なんだかOracleに迎合しているような気がしますが、SQL *Plusにかなり近い感じでオペレーションすることができます。
dual表を使用することもできますし、表示レイアウトをOracleのコマンドで設定することもできます("set pages"や"set lin"など)。
お勉強が終わったらIBMの人と、Club DB2に参加した人たちとの懇親会に行きました。
土曜日に勉強・・・という感じですが、達成感のある午後でした。