JPOUG 2019へ参加したときのこと [コミュニティ]

 去る7/23に月島でJPOUGというOracleのコミュニティが開催された。JPOUGとは日本のOracleコミュニティである。Oracle Databaseを中心とした情報交換を目的として、年に数回、セミナなどを開催している。今回は15分で好きなことを話すという催しであり、今回で8回目だそうだ。今回はここで、1セッション講演させて頂いたときの話である。

  JPOUG in 15 minutes #8

 社外での講演自体自分にとって初めての経験だったので、この話を頂いたときは引き受けるか一瞬迷った。しかし、どんな世界なのか興味があったのと、もともと社内外問わずOracleにまつわるDBAの生活の質を向上に貢献したいという思いもあり、引き受けすることにした。テーマは本Blogでも記載している「トランケートについて知っておくべきこと」。誰でも知っていると思っていることの裏に奥深い世界があること、開発や運用上それが役立つことがあるということをを少しでも伝えたかったからだ。

 会場には50名ほどであろうか、仕事が終わってだんだん席が埋まってくる。講演者は自分含め6人(1人は体調不良とのことでキャンセル)、休憩の後に私の時間となったが、その頃には会場は一杯になっていた。ここ連日、終電まで仕事をしていることが多く、発表の練習をする時間がなかったのが心配だった。というのも15分という時間は曲者で、油断するとついつい余計な事を話過ぎてしまうのだ。用意した資料は通常の自分では30分~45分はかかる内容だっただけに、ポイントを絞って余計なことを話さないように気をつけた。内容は概ね本Blogに記載した以下のトピックである。
 
 ・トランケートについて知っておくべきこと
 ・トランケートの非同期グローバル索引メンテナンスについて
 ・遅延カーソルインバリデーション

 発表後、懇親会でコミュニティの方とお話しすることができた。正直、あまり人付き合いは得意な方ではないのだが、技術の話になれば初対面の方でも通じ合える世界があることを痛感した。この中で、「トランケートで15分も話すことがあるのか?この人大丈夫か?」と思った、と率直な感想を聞けたのが面白かった。というのも、自分は15分にどう納めるかを必死に考えていたからだ。Blogは一方通行で記事の内容が誰にどう伝わっているのかわからないが、このように生のフィードバックがあると励みになる。また、このBlogの存在も急にアクセス数が増えて驚いた。一瞬しか投影していないのに。

 今後、また機会があれば参加していきたいと思った。内容が同じでもBlogに記載するのとface to faceで伝えるのとは違う。内容は悩ましいが、私が話すとしたら基本アーキテクチャの話やチューニング事例、運用(効率化)ネタあたりが良さそうである。逆にトラブル(不具合)系やExaなどのエンタープライズ系はあまり良くないかもしれない。クラウドも流行りではあるがそもそも自分が興味がない。新機能紹介はOracleさんにお任せで良いだろう。このような経験をつめば、いつかOOWで話をすることができるか。。。一瞬、帰りの電車で夢みたいなことを考えてしまった。

なお、資料は準備ができたらそのうち公開しようと思っている。少しお時間頂きたい。

2019/7/30:追記 以下に公開:
https://www.slideshare.net/KazuhiroTakahashi5/oracle-158890029

以上
nice!(1)  コメント(0) 

遅延カーソルインバリデーション [SQL・DDL]

以前、トランケートについて知っておくべきことで述べたように、DDLは(data_object_idの変更とともに)関連するオブジェクトの共有カーソルを即時に無効化していた。しかし、実はOracle12cR2からは、可能なものは無効化を回避し、避けられないものはローリング無効化を行うことができるようになっている。このあたりの挙動は実は設計や運用上、きわめて影響の大きい内容の割には、あまり詳しく説明したドキュメントがパブリックになっていないような気がする。津島博士によるドキュメントは参考になるが、トランケートの際の挙動が記載されていない。そこで、実際に自分で確かめてみようと考えた。

トランケートの場合、以下のようにdeferred invalidationオプションをつけることにより、共有カーソルの無効化を(可能な限り)回避することができる。

例) alter table scott.sales truncate partition sales_q1_2006 update global indexes deferred invalidation;

実際に検証してみた結果、deferred invalidationオプションにより、以下のような効果があることがわかった。

・フルテーブルスキャン、またはローカルインデックスによるレンジスキャンではカーソルの無効化を回避できる
・グローバル索引によるレンジスキャンではカーソルは即時無効化される

※詳細なログは以下参照:
https://community.oracle.com/people/Kazuhiro/blog/2019/05/31/partition-truncate-with-deferred-invalidation?customTheme=mosc

パーティション表による過去パーティションメンテナンスによりトランケートやドロップ運用を行うことは多いと思うが、このオプションによりグローバル索引を使用していなければカーソルの無効化、ひいてはハードパースを避けられるということで、こんなすばらしい機能改善はないと思う。個人的には華々しく宣伝しているオプティマイザの適応なんとか最適化とかより、ずっと広く世の中のDBAの幸せに貢献する機能であるように思う。

なお、オプションをつけない場合の挙動はCURSOR_INVALIDATION初期化パラメータに依存するが、デフォルトは12.2も19cもIMMEDIATEである。これはDEFERREDになる日が来れば、このオプションをもはや気にする必要はないだろう。(参考:Oracle Database Reference Manual 19c, CURSOR_INVALIDATION)

ただ、実際に商用で使った経験がないため、副作用についての留意は必要だと思っている。以下でコミュニティに問い合わせをしてみてはいるので、そのうちワールドワイドでなんらかの知見が得られることを期待したい。

https://community.oracle.com/thread/4281580

以上

nice!(0)  コメント(0) 

19cにアップグレードしてTO_DATEで困った話 [SQL・DDL]

2019年5月1日、日本が令和を迎えるとき、私はExadataを12.2から19cへアップグレードする作業を行っていた。プロジェクトは開発期間とはいえ運用開始に向けての試験が詰まっていおり、この10連休というまたとない長期間DBを停止されるタイミングを狙ったという訳である。個人的にDBのアップグレードという作業は(長年Oracleにかかわってきたものの)初めての経験であり、そもそも可能な限り「避けるべきもの」、という位置づけであった。しかし、今回どうしてもとなったのは、長期保守の観点でやはりターミナルである19cに上げたい、ということとなったのである。あるいみ、DBの元号変更をこのGWに経験した訳である。

一言にアップグレードといっても、実際の作業をイメージするのは難しいかもしれない。DBのアップグレードは通常DB/GIを上げることを指すが、Exadataの場合これに加え、ESS(IBSW含む)、ZFS、EMを含めて整合性の取れた形にする必要がある。また、DB/GIとESSのバージョンは依存関係があるため、ESSだけ先走ってあげてしまうと、サポートされていない組み合わせになることもある。
そのため今回は一度DBにRUを当てて、ESSを上げられる状態にし、ESSを上げ、再びDB/GIを上げてという手順を取った。当然、この前後にミドルの落とし上げやOS・DBのバックアップ等の作業を含めると、かなりの作業量となる。手順を確立する上で、アップグレードの事前検証は必須であるが、それがあったとしても、環境差異を完全に吸収することはできないため、ある程度のリスクは想定しなければならないだろう。連休中などサポートが手薄な状況で最後に頼れるのはいつも人である。

さて、全体的にアップグレードにより12.2で踏んでいたORA-600系の不具合やいくつかのExadataのクリティカルイシューが修正されたことは純粋に喜ばしいことであった。以前このBlogでも紹介したスマートスキャンの結果不正についてもこのバージョンで修正されていることを確認している。Oracleの不具合の多さ、品質に疑問を感じることも少なくないが、一方でかなりの不具合は既に修正が出ていることが多いため、パッチを当てることができさえすれば問題を事前に回避することはできると思っている。あくまでもパッチを適用できれば、の話であるが。

一方、アップグレードにより発生した新たな問題もあった。Oracleコミュニティに投稿したが、19cでTO_DATEのフォーマットのマッチングのチェック仕様の一部が変更されたのである。以下を見てほしい。

*12.2.0.1
SQL> select TO_DATE('20190520','YYMMDD') from dual;

TO_DATE('20190520
-----------------
20190520 00:00:00

*19.2.0.0
SQL> select TO_DATE('20190520','YYMMDD') from dual;
select TO_DATE('20190520','YYMMDD') from dual
*
ERROR at line 1:
ORA-01843: not a valid month

基本的に上記で指定しているYYMMDDはYYYYMMDDと記述すべきであり、19cでエラーになる・ならないに関わらずこのような曖昧な記述は避けるべきである。しかし、実はSQLリファレンスマニュアルにYYのマッチングに失敗したらYYYYを試すという挙動が記載されている。これは自分も知らなかったので正直驚いた。

---
SQL reference manual / String-to-Date Conversion Rules

The following additional formatting rules apply when converting string values to date values
...

-If a match fails between a datetime format element and the corresponding characters in the date string, then Oracle attempts alternative format elements, as shown in Table 2-20.

Table 2-20 Oracle Format Matching
original format element:'YY' --> additional format elements to try in place of the original: 'YYYY'
---

この挙動、興味深いのは19cにおいて TO_DATE('20120520','YYMMDD')はエラーにならないのである。20→YY、12→MMにマッチングさせるところで、月のチェックが通るためと思われる。このため、データの内容に応じてエラーになる・ならないが変わるのである。また、TO_DATE('2019/05/20','YY/MM/DD')は19cでもエラーは出ない。/により曖昧さが排除されている結果と思われる。同様な関数としてTO_TIMESTAMPが気になるが、こちらは12c・19cの挙動に変更はなさそうであった。どうやらコード(実際は構文を解析するパーサだとは思うが)が異なるためらしい。

なお、多くの日本で稼動しているOracleDatabaseにおいて、Table 2-20 Oracle Format Matchingに記載されているYY→YYYY以外のフォーマットマッチングについて、同様の事象が発生するのはRR→RRRRのみである。それは、上記のNLS_LANGが日本語の場合、MONとMONTHのフォーマットに違いはなく、いずれも「7月」といった文言を変換できる。また、TO_DATE('7月','MONTH')は必ずエラーとなる挙動は12c,19c変わらずである。

OracleとしてはこのTO_DATEの挙動変更はあくまで「仕様」であり、不具合ではないというスタンスらしい。このため、19cへのマイグレーションにおいてはSQLの非互換として意識しておく必要がある。しかし、この手の細かな仕様変更はリリースノートに記載されていないから厄介である。なぜこの事象に気がついたか、経験のあるDBAなら察していただけるであろう。世の中のSQLが、このようなOracleのニッチな仕様を前提として動いていないことを祈るばかりである。


※2021/2/11追記
当時、My Oracle Support Community へ投稿したときの記事がこちら(a different TO_DATE behavior in 19c)。コミュニティの有識者の中では不具合ではないか、同じ事象に遭遇した、という声があった。


以上
nice!(0)  コメント(0)