« 2013年10月 | メイン | 2013年12月 »

2013年11月 アーカイブ

2013年11月 6日

JPOUG が db tech showcase 東京 2013 に出ます!

昨年に引き続き、db tech showcase 東京 2013 に JPOUGが参加します。テーマは「特濃」

ultra_deep_jpoug.jpg

db tech showcase 2013 会場(秋葉原 UDX) 、JPOUGボードメンバーがお得意のテクノロジ、今語りたいテクノロジについて濃ーい内容のセッションを行います。

私は、「Corruption And Revive : 破壊と復活」というタイトルで、様々な破損に関するお話をさせていただく予定です。

データベースのもっとも基本的であり重要な責務は格納されたデータを安全に保管することですが、ごく稀にOS/ハードウェアなどの外的な要因やBugにより、データが破損し失われることがあります。しかし、Oracle Database 12cには優れた破損検出、データ復旧機能があるため、このような状況においてもデータを復旧できます。 本セッションでは、あまり一般的に語られることが少ないテクニックを織り込んだデモを用いて、これらについて説明します。

内容は現在鋭意準備中ですが、Oracle Databaseが破損という古くて新しい問題に対して、どのようにアプローチしてきたかについても、触れることができるかもしれません。 ご興味があればご参加ください!

今回のdb tech showcase 東京 2013 のテーマは

「be a Database Tongalist ~とんがったデータベースエンジニアになれ~」

とんがったデータベースエンジニアな人、とんがったデータベースエンジニアになりたい人は、今すぐ参加登録!

「OSS-DB最前線 ~2013秋~」 でお話しさせていただきました

2013年11月1日(金)に品川で開催された LPI-Japan様主催「OSS-DB最前線 ~2013秋~」にて「OSS-DB Silver ポイント解説セミナー」の講師を務めさせていただきました。

今回セミナーでは、OSS-DB Silver試験範囲のうち、SQLに関する箇所を説明させていただきました。資料はSlideshareにアップロードしてあります。

今回の資料は、大部分が7/21に担当させていただいたセミナー資料からの抜粋です。このため、SQL以外のOSS-DB Silver試験範囲について学習を進めたい場合は、 7/21のセミナーの資料が参考になるはずです。必要に応じてあわせてご確認いただければ幸いです。

2013年11月30日

(全部俺) Oracle ACE Director Tanel Poder Advent Calendar 2013 やりますよ

Oracle DatabaseのInternalに興味があるならば、知らない人はいない Oracle ACE Director Tanel PoderさんについてのAdvent Calendar やりますよ。執筆者は全部俺。

想定している内容は以下の通りです。

  • TP Scriptに含まれるSQLスクリプトの紹介
  • blogエントリの翻訳
  • その他

Thanks, Tanel!

2013年11月21日

今年もやります! JPOUG Advent Calendar

ITエンジニアにとっての年末の風物詩といえば、Advent Calendarです。今年もJPOUG Advent Calendarやりますよ!

ぜひ JPOUG Advent Calendar 2013 on Zusaarからエントリしてください!

私も12月2日にブログ書く予定です!内容は・・・未定です・・・。(db tech showcase 特濃JPOUGが終わってちょっと気が抜けています :-) )

2013年11月16日

db tech showcase 東京 2013 特濃JPOUG - 私のセッション資料を公開しました

db tech showcase 東京 2013 の最終日、セッションルームAを午後13:00-16:45の間、JPOUGメンバーでの「特濃」なセッションを行わせていただきました! ご参加いただいた皆様ありがとうございました!(様子を眺めていた感じでは、4セッション「とおし」で聴講されていた方が多かったような?)

私は"Currption And Revive"というタイトルで、ブロック破損と修復について発表させていただきました。セッション資料は以下のURLで公開しております。

セッションを聴講いただいた皆様、貴重な機会を提供いただいたインサイトテクノロジーの皆様ありがとうございました!

2013年11月11日

物理破損とAutomatic Block Media Recovery

引き続き、来週の特濃JPOUG | Japan Oracle User Groupの準備をしつつ、いろいろ検証しております。物理破損関連で、面白い機能を見つけたので紹介します。

データへのアクセス時に物理破損を検知すると、ORA-1578が発生します。このとき、シングル環境の場合は一般に以下の方法で破損を修復します。

  • 破損ブロックを含むデータファイルをリストア+リカバリ
  • RMANブロックメディアリカバリ (BMR) : 9.1-10.2ではBLOCKRECOVERコマンド、11.1以降は RECOVER BLOCKコマンドを使用する

しかし、11.2以降のData Guardのフィジカルスタンバイ環境で、リアルタイム問い合わせを有効にしている場合は、これらの方法を使用する必要がありません。破損が発生していないスタンバイデータベースのブロックが自動的にプライマリデータベースに転送され、このブロックのデータをもとにブロックリカバリが実行されます。これを Automatic Block Media Recovery(Auto BMR) と呼びます。

なお、破損データにアクセスするSQLを実行したアプリケーションにはORA-1578が返されず、リカバリされた正常なデータが返されます。アプリケーションには、物理破損があったことすらわからない形になります。

Auto BMRを使用するには、スタンバイデータベースをリアルタイム問い合わせモードにする必要があります。すなわち、スタンバイデータベースを読み取り専用でオープンしているし、この状態で管理リカバリモードを有効にしている必要があります。また、リアルタイム問い合わせモードを使用するためには、Active Data Guard オプションのライセンスが必要ですので、必然的にAuto BMRもActive Data Guard オプションのライセンスが必要になります。

以下に、Auto BMRが実行されたときのプライマリデータベースのアラートログを抜粋します。ABMRというバックグラウンドプロセスが、Auto BMR処理を実行していることがわかります。

Sat Nov 09 05:33:20 2013
Hex dump of (file 5, block 134) in trace file /u01/app/oracle/diag/rdbms/c101p/c101p/trace/c101p_ora_3658.trc

Corrupt block relative dba: 0x01400086 (file 5, block 134)
Bad check value found during multiblock buffer read
Data in bad block:
 type: 6 format: 2 rdba: 0x01400086
 last change scn: 0x0000.0008a633 seq: 0x1 flg: 0x06
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0xa6330601
 check value in block header: 0xddb4
 computed block checksum: 0x1a05

Reading datafile '/u01/app/oracle/oradata/c101p/tbs1.dbf' for corruption at rdba: 0x01400086 (file 5, block 134)
Reread (file 5, block 134) found same corrupt data (no logical check)
Starting background process ABMR
Sat Nov 09 05:33:20 2013
ABMR started with pid=35, OS id=3710
Sat Nov 09 05:33:20 2013
Automatic block media recovery service is active.
Sat Nov 09 05:33:20 2013
Automatic block media recovery requested for (file# 5, block# 134)
Sat Nov 09 05:33:21 2013
Automatic block media recovery successful for (file# 5, block# 134)
Sat Nov 09 05:33:21 2013
Automatic block media recovery successful for (file# 5, block# 134)

物理破損とチェックサム

引き続き、今週の特濃JPOUG | Japan Oracle User Groupの準備をしつつ、いろいろ検証しております。物理破損と論理破損の違いについて理解しておくと、セッションの内容がより理解できるかもしれません。物理破損の特徴を示す典型的な観点にフォーカスして、説明します。

Oracle Databaseは、データをデータファイルに格納します。皆さんがなじみにあるテキストファイル、CSVファイルやXMLファイルなどとと大きく異なるのは、データをファイルの先頭から順次書き込むのでのではなく、データファイルをデータブロックと呼ばれる固定サイズで区切り、そのデータブロックの中にデータを書き込む構造になっていることです。データブロックのフォーマットは以下の通りです。

131115_CorruptionAndRevive.jpg

行データ格納用領域に、ブロックの末尾からデータ(行)を格納してゆきますが、 制御、管理用の領域としてブロックの先頭部分にヘッダ、末尾部分にトレイラがあります。 このヘッダにチェックサム格納する領域(図ではChkValと表記)があります。

チェックサムという考え方は、データブロック固有のものではなく、IT一般のモノです。

データ格納時に計算したチェックサムの値と、データの読み取り時に計算したチェックサムの値を 比較することで、データが格納時から読み取り時までの間に修正されていないないか、すなわち、破損していないかをチェックすることができます。

110422_BlockCorrupt.jpg

※:昔のセミナーのスライドを流用、乱筆ご容赦ください

チェックサムを例にとりましたが、物理破損というのは、チェックサム値の正当性などの ブロックの基本構造に問題があるレベルの破損と位置づけられます。一方、論理破損とは、 ブロックの基本構造に問題がないが、意味的に問題がある(古い、整合性がない)レベルの破損です。

一般に、物理破損は検出が比較的容易ですが、論理破損の検出は困難です。

RDBMSのアーキテクチャから考える論理破損の検知

今週の特濃JPOUG | Japan Oracle User Groupに関連したお話です。

上記のエントリに記載した論理破損の厄介さを踏まえ、では「この厄介な論理破損をどうやって検知すればいいのだろうか?」という点を考えます。

原理的には、論理発生の発生原因はいろいろありますが、実際的な発生傾向を踏まえるとLost Writeに限定して議論しても問題ないはずです。Lost Writeは、データファイルに存在するブロックのうち、一部のブロックが古いままになっている状態と言えます。当然ですが、データファイルはRDBMSから見るとデータの格納場所として位置づけられるため、データファイルが想定どおり更新されていないと、正しいデータが得られるはずがないのは当然のことです。開発の現場に例えて言うなら、「設計書が間違っていたなら、成果物も間違うのは当たり前でしょ?」みたいな話です。

でも、設計書の変更履歴のところに設計書の記載内容に反した内容が書かれてれば、間違いに気づく可能性があるかもしれません。「あれ?変更履歴には列XXXX削除って書いてあるのに、何故本文には列XXXXが残っているんだ?ミスじゃない?」みたいに。

同じことはRDBMSにも言えます。RDBMSにおいて変更履歴に相当するのは、オンラインREDOログファイル(WALファイル、ログファイル、トランザクションログなど、製品によって呼び方は様々ですが)になります。オンラインREDOログファイルを用いてリカバリを実行すれば、データファイルのLost Writeに気づくことができる可能性があります。

上記の考え方を実装するに当たり、考慮すべき点は以下になるでしょう。

  • 早期検出のためには、頻繁にリカバリを行う必要があるが、現実的ではない
  • RDBMSでは、オンラインREDOログファイル(更新履歴)とデータファイルの整合性チェックを行うことができるのは一般に更新時のみ。あまり更新を行わないブロックについては、早期に破損を検出できないことになる。

これらの考慮点をふまえて、論理破損の早期検出のためにOracle Database 11gから組み込まれた機能が、Data Guard環境における DB_LOST_WRITE_PROTECT です。

論理破損は厄介だ - Lost Write

引き続き、今週金曜日の特濃JPOUG | Japan Oracle User Groupの準備をしつつ、いろいろ検証しております。その中で、あらためて論理破損の厄介さを痛感させられております。

"Lost Write"とは?

論理破損は、様々な要因により発生し、引き起こされる破損の状況も様々です。 論理破損を引き起こす1つの要因に"Lost Write"というストレージの問題があります。 これは、pwrite()等の更新系のシステムコールが正常に完了したにも関わらず、 実際には物理的な記憶領域は更新されていないというような、更新が実質的に失われてしまうような問題を指します。

"Lost Write"が発生すると、物理的な記憶領域におけるブロックは更新前の状態のままとなります。 したがって、Oracle Databaseから見るとブロックの形式にはまったく問題はなく、単に格納されている行データが古いだけ。という形になります。すなわち、物理破損を検出する機構では、この種の論理破損は検出できない位置付けになります。

"Lost Write"をエミュレートする

ddコマンドを使用して"Lost Write"をエミュレートしてみます。

SQL> create table tbl_lostwrite ( i number, s1 varchar(100)) pctfree 99 tablespace tbs2;

表が作成されました。

SQL> insert into tbl_lostwrite values(1, 'JPOUG');

1行が作成されました。

SQL> commit;

コミットが完了しました。

SQL> select dbms_rowid.rowid_block_number(rowid) "Block#" from TBL_lostwrite;

    Block#
----------
       133

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

システムが変更されました。

初期状態のデータファイルをバックアップしておき、そのあとUPDATEを実行します。

SQL> define dirpath=/u01/app/oracle/oradata/c101p/
SQL> host cp &dirpath/tbs2.dbf &dirpath/tbs2_old.dbf

SQL>
SQL> update tbl_lostwrite SET s1 = 'XXXXX' WHERE i = 1;

1行が更新されました。

SQL> commit;

コミットが完了しました。

SQL> SELECT * FROM tbl_lostwrite;

         I S1
---------- ----------------------------------------
         1 XXXXX

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

システムが変更されました。

当然のことながら、UPDATE実行後のSELECTでは、UPDATEにより更新されたデータが返ってきています。

上記の通り、今回はUPDATEによる更新処理は正常に実行されています。ここで、更新処理が失われた状態を疑似的に作り出してみます。これは、UPDATEにより更新されたブロックを、過去の状態に戻することで実現できます。

SQL> host dd if=&dirpath/tbs2_old.dbf of=&dirpath/tbs2.dbf bs=8192 skip=133 seek=133 count=1 conv=notrunc oflag=direct
1+0 records in
1+0 records out
8192 bytes (8.2 kB) copied, 0.00016607 s, 49.3 MB/s

SQL>
SQL> SELECT * FROM tbl_lostwrite;

         I S1
---------- ----------------------------------------
         1 JPOUG

すると、SELECT結果は、更新前の状態に戻ります。何もエラーが発生していない、すなわち、Oracle Databaseは"Lost Write"により引き起こされた論理破損に気づかないことに注意してください。

"Lost Write"による論理破損の検出

"Lost Write"による論理破損は、前回ご紹介した表と索引が不整合となっている論理破損と同様に、Oracle Databaseの機能を用いた破損検出がきわめて困難です。以下のように各種コマンドを実行しても、破損を検出できません。

RMAN> backup datafile 6;

backupが開始されました(開始時間: 13-11-09)
チャネル: ORA_DISK_1が割り当てられました
チャネルORA_DISK_1: SID=44 デバイス・タイプ=DISK
チャネルORA_DISK_1: フル・データファイル・バックアップ・セットを開始しています
チャネルORA_DISK_1: バックアップ・セットにデータファイルを指定しています
入力データファイル・ファイル番号=00006 名前=/u01/app/oracle/oradata/c101p/tbs2.dbf
チャネルORA_DISK_1: ピース1(13-11-09)を起動します
チャネルORA_DISK_1: ピース1(13-11-09)が完了しました
ピース・ハンドル=/u01/app/oracle/product/12.1.0.1/ee_1/dbs/0coognl4_1_1 タグ=TAG20131109T070507 コメント=NONE
チャネルORA_DISK_1: バックアップ・セットが完了しました。経過時間: 00:00:01
backupが完了しました(完了時間: 13-11-09)

RMAN> backup CHECK LOGICAL datafile 6;

backupが開始されました(開始時間: 13-11-09)
チャネルORA_DISK_1の使用
チャネルORA_DISK_1: フル・データファイル・バックアップ・セットを開始しています
チャネルORA_DISK_1: バックアップ・セットにデータファイルを指定しています
入力データファイル・ファイル番号=00006 名前=/u01/app/oracle/oradata/c101p/tbs2.dbf
チャネルORA_DISK_1: ピース1(13-11-09)を起動します
チャネルORA_DISK_1: ピース1(13-11-09)が完了しました
ピース・ハンドル=/u01/app/oracle/product/12.1.0.1/ee_1/dbs/0doognn8_1_1 タグ=TAG20131109T070616 コメント=NONE
チャネルORA_DISK_1: バックアップ・セットが完了しました。経過時間: 00:00:01
backupが完了しました(完了時間: 13-11-09)

RMAN> backup CHECK LOGICAL VALIDATE datafile 6;

backupが開始されました(開始時間: 13-11-09)
チャネルORA_DISK_1の使用
チャネルORA_DISK_1: フル・データファイル・バックアップ・セットを開始しています
チャネルORA_DISK_1: バックアップ・セットにデータファイルを指定しています
入力データファイル・ファイル番号=00006 名前=/u01/app/oracle/oradata/c101p/tbs2.dbf
チャネルORA_DISK_1: バックアップ・セットが完了しました。経過時間: 00:00:01
データファイル・リスト
=================
ファイル ステータス マーク済破損 空のブロック 調査済ブロック 高SCN
---- ------ -------------- ------------ --------------- ----------
6    OK     0              1145         1280            589437
  ファイル名: /u01/app/oracle/oradata/c101p/tbs2.dbf
  ブロック・タイプ 失敗ブロック 処理済ブロック
  ---------- -------------- ----------------
  データ       0              5
  索引      0              0
  その他      0              130

backupが完了しました(完了時間: 13-11-09)

RMAN> VALIDATE datafile 6;

validateが開始されました(開始時間: 13-11-09)
チャネルORA_DISK_1の使用
チャネルORA_DISK_1: データファイルの検証を開始しています
チャネルORA_DISK_1: 検証のためのデータファイルを指定しています
入力データファイル・ファイル番号=00006 名前=/u01/app/oracle/oradata/c101p/tbs2.dbf
チャネルORA_DISK_1: 検証が完了しました。経過時間: 00:00:01
データファイル・リスト
=================
ファイル ステータス マーク済破損 空のブロック 調査済ブロック 高SCN
---- ------ -------------- ------------ --------------- ----------
6    OK     0              1145         1280            589437
  ファイル名: /u01/app/oracle/oradata/c101p/tbs2.dbf
  ブロック・タイプ 失敗ブロック 処理済ブロック
  ---------- -------------- ----------------
  データ       0              5
  索引      0              0
  その他      0              130

validateが完了しました(完了時間: 13-11-09)

RMAN> exit


Recovery Managerが完了しました。

[oracle@ol64n19 ~]$ sqlplus rywatabe/rywatabe

SQL*Plus: Release 12.1.0.1.0 Production on 土 11月 9 07:06:54 2013

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

最終正常ログイン時間: ナレ 11キ・09 2013 06:50:54 +09:00


Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SQL> analyze table tbl_lostwrite validate structure cascade;

表が分析されました。

SQL> analyze table tbl_lostwrite validate structure cascade FAST;

表が分析されました。

なお、再度更新を実行しても、特にエラーは発生しません。

SQL> update tbl_lostwrite SET s1 = 'YYYYY' WHERE i = 1;

1行が更新されました。

SQL> commit;

コミットが完了しました。

2013年11月 7日

論理破損は厄介だ - 表と索引の不整合

現在、来週の特濃JPOUG | Japan Oracle User Groupの準備をしつつ、いろいろ検証しております。その中で、改めて論理破損の厄介さを感じております。

ごにょごにょして表と索引が不整合となっている状況を作ります。

SQL> SELECT i,s1 FROM tbl_index_mismatch;

         I S1
---------- ----------
         1 AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA
           AAAAAAAAAA


         I S1
---------- ----------
         2 BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB


SQL> SELECT /*+ index(tbl_index_mismatch idx_index_mismatch) */ i,s1 FROM tbl_index_mismatch WHERE i = 3;

         I S1
---------- ----------
         3 BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB
           BBBBBBBBBB

通常の運用で定期的に実行される可能性がある作業で、破損チェックを実行可能なのはRMAN backupぐらいかなと。

RMAN> BACKUP DATAFILE 7;

Starting backup at 05-NOV-13
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=45 device type=DISK
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00007 name=/u01/app/oracle/oradata/c101p/tbs3.dbf
channel ORA_DISK_1: starting piece 1 at 05-NOV-13
channel ORA_DISK_1: finished piece 1 at 05-NOV-13
piece handle=/u01/app/oracle/product/12.1.0.1/ee_1/dbs/09oo7nem_1_1 tag=TAG20131105T210630 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 05-NOV-13

ここで検出されないのは想定内。では、CHECK LOGICALでは・・・

RMAN> BACKUP CHECK LOGICAL DATAFILE 7;

Starting backup at 05-NOV-13
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00007 name=/u01/app/oracle/oradata/c101p/tbs3.dbf
channel ORA_DISK_1: starting piece 1 at 05-NOV-13
channel ORA_DISK_1: finished piece 1 at 05-NOV-13
piece handle=/u01/app/oracle/product/12.1.0.1/ee_1/dbs/0aoo7nes_1_1 tag=TAG20131105T210636 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 05-NOV-13

あれれ、成功しちゃった・・・。じゃ、念のためVALIDATE系のコマンドも実行してみます。

RMAN> BACKUP CHECK LOGICAL VALIDATE  DATAFILE 7;

Starting backup at 05-NOV-13
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00007 name=/u01/app/oracle/oradata/c101p/tbs3.dbf
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
7    OK     0              1141         1280            629681
  File Name: /u01/app/oracle/oradata/c101p/tbs3.dbf
  Block Type Blocks Failing Blocks Processed
  ---------- -------------- ----------------
  Data       0              5
  Index      0              1
  Other      0              133

Finished backup at 05-NOV-13

RMAN> validate datafile 7;

Starting validate at 05-NOV-13
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=53 device type=DISK
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
input datafile file number=00007 name=/u01/app/oracle/oradata/c101p/tbs3.dbf
channel ORA_DISK_1: validation complete, elapsed time: 00:00:01
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
7    OK     0              1141         1280            629681
  File Name: /u01/app/oracle/oradata/c101p/tbs3.dbf
  Block Type Blocks Failing Blocks Processed
  ---------- -------------- ----------------
  Data       0              5
  Index      0              1
  Other      0              133

Finished validate at 05-NOV-13

VALIDATE系のコマンドでもチェックできない。

ではしょうがない。負荷の高いコマンドですが、 ANALYZE TABLE VALIDATE STRUCTURE CASCADE を実行してみます。

SQL> set timing on
SQL> analyze table tbl_index_mismatch validate structure cascade;
analyze table tbl_index_mismatch validate structure cascade
*
ERROR at line 1:
ORA-01499: table/index cross reference failure - see trace file


Elapsed: 00:00:44.76

流石にこのコマンドであれば、破損を検出できます。しかし、高々2行のテーブルの破損チェックに 44秒かかるとはなかなか厳しい・・・

(おそらく11.2から導入された)FASTオプションを指定すると、処理時間が大幅に短縮されるが、破損が検出できない・・・

SQL> analyze table tbl_index_mismatch validate structure cascade FAST;

Table analyzed.

Elapsed: 00:00:00.00
SQL>

なかなか苦しい・・・

About 2013年11月

2013年11月にブログ「コーソル DatabaseエンジニアのBlog」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2013年10月です。

次のアーカイブは2013年12月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。