オラクルデータベースのデータベース・リンクが2019年6月23日以降に機能しなくなる？

# ■ 要約

#####　データベース・リンク（dblink接続）が2019年6月23日以降に失敗する可能性があります。 　-- 2020/7/4 追記）下に記載した2020年7月の事例もご参照ください。
　そのために、古いバージョンのOracleデータベースでデータベース・リンクを使用している場合はパッチ適用が必要な場合があります。

`	※古いバージョンとは、
	10g リリース 2 (10.2.0.5 以下)
	11g リリース 1 (11.1.0.7 以下)
	11g リリース 2 (11.2.0.3 以下)
	12c リリース 1 (12.1.0.1)`

　パッチ適用を行わないと、これらの古いバージョンのデータベースから新しい（またはパッチが適用された）バージョンのデータベースへのデータベース・リンク（dblink接続）が2019年6月23日以降に失敗する可能性があります。

`	※新しいバージョンとは、
	11g リリース 2 (11.2.0.4)
	12c リリース 1 (12.1.0.2)
	12c リリース 2 (12.2.0.1)
	18c
	19c`

`	※パッチとは、
	サポートの DOC に説明があります。
	Oracle Database 12.1.0.1 および 11.2.0.3 以下のリリースに対する推奨パッチと、2019年6月までに実施いただきたい対策について (ドキュメントID 2378443.1)`
	
#####　問題が発生する可能性があるのは、古いバージョンのデータベースと新しい（またはパッチが適用された）バージョンのデータベースを接続するデータベース・リンクであり、2つの古いバージョンのデータベースを接続するデータベース・リンクではこの問題は発生しません。

　発生条件に合致するバージョン同士の組み合わせであっても、2019年6月23日後のデータベース・リンク利用時に、即時に使用不能になることはありません。
2019年6月以降の任意の時点でエラーが発生する可能性があるということです。

#####　データベースクライアントとデータベースサーバーとの相互運用性には影響ありません。

　16K/秒を超えるトランザクション(SCN増加)を発生させ続ける高負荷データベース以外では、運用を続けても、事象が発生しない可能性が高いと考えられます。

#####　約16K/秒以上のトランザクション(SCN増加)が発生する可能性があるかどうかで、以下のようにご判断できると考えられます。

#####・発生する可能性がある
　将来的に本事象が発生する可能性があるため、該当パッチの適用やバージョンアップを推奨します。  もしくは、データベースリンクの不使用を検討ください。

#####・発生する可能性がない
  　本事象が発生する可能性は極めて低いため、対応を見送ることも可能と思われます。  ただし、安全の為に定期的なCurrent SCNの状況確認の実施を推奨します。  定期的に確認することで、予兆の検知と早期対処が可能となります。

`	    SQL> select version, to_char(sysdate,'YYYY/MM/DD HH24:MI:SS') DATE_TIME,
	    2    dbms_flashback.get_system_change_number current_scn
	    3    from v$instance;`

#####・外部のデータベースとデータベースリンクする可能性がある（2020/7/5 追記)
　接続する外部のデータベースが新しい（またはパッチが適用された）バージョンのデータベースであり、高負荷なデータベースである等の理由で SCN が大きい場合、接続したデータベースが SCN の大きい外部のデータベースと同じ値に引き上げられてしまいます。
　そして、その引き上げられたデータベースと接続したデータベースもまた引き上げられるというSCNの伝搬によりシステムを止めてしまうなどの大きな影響を与える可能性もあるので、該当パッチの適用やバージョンアップを推奨します。
　もしくは、外部のデータベースとデータベースリンクの不使用を検討ください。
　フルマネージド型のクラウド・サービスなどを利用して、オンプレのデータベースと接続する場合には注意が必要と考えられます。


# ■ 詳細

###１）SCN（System Change Number）基本

　SCNはある時点におけるデータベースのコミットされたバージョンを定義するスタンプです。Oracleでは、すべてのコミットされたトランザクションに一意なSCNを割り当てます。SCNの値は、データベースが更新された論理的な時点をあらわし、この値はデータベースに対する変更を記録するためにOracleによって利用されます。

　SCNはCOMMITするたびに増加する正の整数値であり、時刻には依存していません。よって、SCN -> 時刻、時刻 -> SCN への変換は行うことができません。(DB起動中には、現在のSCNが5分毎に SMON_SCN_TIME表にその時刻のSCN情報が1行ずつアップデートされています。）


###２）SCN（System Change Number）詳細

　SCNは6バイト(48ビット)の数値で最大値は 281,474,976,710,656 であり、SCN_BASEとSCN_WRAP の2つの要素でもあらわされます。
　SCN_BASEは4バイト(32ビット)、SCN_WRAPは2バイト(16ビット)の数値で、SCN_BASEがその最大値(2の32乗 = 4294967296)に達すると、SCN_WRAPが1つ増加し、SCN_BASEは0にリセットされます。SCN_WRAPがその最大値(2の16乗 = 65536)に達するまで、これが繰り返されます。
　また、12.2以降のリリースで compatibleが12.2以上に設定されている場合は、SCNは8バイトに拡張されています。


###３）データベース・リンクとは

　データベース・リンクとは、異なるDB間で接続を確立し、他DB内のデータ参照や更新を 行う機能 であり、他のデータベース上の表への直接アクセス(select、delete、update)できます。

　リモートマテリアライズド・ビュー(Mview) でもデータベース・リンクを使用しています。


###４）SCN（System Change Number）はデータベース・リンク間のデータベースで同じ値に引き上げられる動作をする

　データベース・リンク経由でアクセスされるデータベース間では、以下のタイミングで SCN の同期が行われ、SCN の小さいデータベースが SCN の大きいデータベースと同じ値に引き上げられる動作が行われます。

  ・ リモート問合せの最初と最後
  ・ リモート・トランザクションの最初と最後
  ・ データベース・リンクの接続が確立される時

　データベース間で比較し、バージョンや接続元・接続先に関わらず、大きいSCNの値に同期するところがポイントです。


###５）SCNに対して現行で使用できる上限値

　現行で使用できるSCN値の上限値というのがあり、1988年1月1日から経過秒数毎に16,384（16K /秒）という増加率(SCNレート)で値が増加 していくようです。
　そして、データベースの Current SCN は、システムのトランザクション(COMMIT)数に応じて増加していきますが、この上限値を超えることはできないようです。これは、データベースの現在の最大SCN制限として知られています。 

　こうすることで、Oracle DatabaseはSCNを長期間にわたって配給し、バージョン12.2.0.1以下を使用しているすべてのOracle Databaseで500年以上のデータ処理が可能になります。 
　12.2.0.1から互換性を12.2に設定した場合は、SCNが96K/秒の速度で消費されても、Oracle Databaseでは300万年近くのデータ処理が可能になるようです。(※具体的なレートの値は非公開)
　今回のパッチは、データベースのこの最大SCN制限を増加させて、12.2.0.1と同じにするようです。

 ※ 実装においてはオラクル社非公開の部分もある為、実際とは異なる可能性もあります。

・2020/7/8 追記）
 ※ System Change Number (SCN), Headroom, Security and Patch Information (ドキュメントID 1376995.1)が参考になります。



###６）発生する可能性のある事象

　特定のパッチが適用済みのデータベースでは、2019年6月23日以降、最大SCN制限の増加率である 「SCNレート」が従来の16K/秒 から高いSCNレートへ自動で切り替わるようです。(※具体的なレートの値は非公開であるが、ドキュメントID 1376995.1より、最低でも96K/秒以上であることは推測でき、実際はかなり大きな値であることが2020/7に経験したORA-19706エラー発生時のCuttent SCNの値により確認できている。-2020/7/8 追記と本文修正)

　そのため、Current SCNの値が従来SCNレート以上に増加したパッチ適用済みのデータベースと、従来SCN レートのデータベースとで データベース・リンク を行うと、両方のデータベースの Cuttent SCN を同期させる必要があるために、従来SCNレートで動作しているデータベース側の最大SCN制限を Cuttent SCN が超えてしまう場合もあります。
　そうなることにより、エラーが発生し処理が失敗する可能性があります。

 ※ 実装においてはオラクル社非公開の部分もある為、実際とは異なる可能性もあります。


###７）ご参考までに

11.2.0.4 では、次のような隠しパラメータがありました。

~~~
PARAMETER                                                    DESCRIPTION                                                VALUE
-----------------------------------------------------------  ---------------------------------------------------------  ----------------------
_external_scn_rejection_threshold_hours                      Lag in hours between max allowed SCN and an external SCN   24
_max_reasonable_scn_rate                                     Max reasonable SCN rate                                    32768
_bug19777862_c3_external_scn_rejection_threshold_hours       Lag in hours between max allowed SCN and an external SCN   4464
_bug19777862_low_scn_headroom_warning_threshold_days         low SCN headroom warning threshold in days                 90
~~~

###2020/7/4 追記）2020年7月に発生した事例

　2020年7月に、古いバージョン(※上記参照)のデータベースである11.2.0.3(従来SCNレートのDB)から、新しいバージョン(※上記参照)のデータベースである11.2.0.4へのデータベース・リンク（dblink接続）がORA-19706エラーで失敗しました。

 >エラーコード: ORA-19706
 詳細: SCNが無効です。
 原因: 入力されたSCNが正の整数でないか、または大きすぎます。
 アクション: 入力したSCNを確認し、有効なSCNであることを確認してください。 

その他のサーバーで、Oracleがトランザクションに対して計算しているシステム変更番号（SCN）が不合理な数値であることを示している ORA-600[2252] なども発生しました。

※ Database Link Fails with ORA-02068 and ORA-00600 \[2252] (ドキュメントID 145878.1) にORA-600[2252]エラーが書かれています。
  
　Current SCNの値が従来SCNレート以上に増加した新しいバージョンのデータベースと、従来SCNレートのデータベースとで エータベースリンクを行うと、従来SCNレートで動作しているデータベース側の最大SCN制限を Cuttent SCN が超えてしまうことが原因です。

　新しいバージョンのデータベースである11.2.0.4のサーバのトランザクション量は決して多くは無く約16K/秒以上のトランザクション(SCN増加)が発生することは全くありませんでした。

しかし、当該サーバの Cuttent SCN は、36,000,000,000,000 を超えていました。

　最大SCN制限の確認方法の公開情報は見当たりませんが、2019年6月23日以前の環境の最大SCN制限は、1988/1/1から経過秒数毎に16K/secという増加率(SCNレート)で値が増加していくそうです。

　この計算だと、2020/07/1 あたりの従来SCNレートでの最大SCN制限は、おおよそ 16,792,289,280,000 と推測できます。

 >   2020/7/1-1988/1/1＝32.5年
    年間の秒数(うるう年等は考慮せず)=31536000秒
    - 2020/7/1 の最大SCN制限
     16k/sec*31536000秒*32.5年=16,792,289,280,000

では、なぜ従来SCNレートの最大SCN制限を超えたのか？

　CURRENT_SCN は、データベースリンクで処理を実行した際に、接続データベース間で値を比較し、大きい方の CURRENT_SCN の値に同期されます。

　最近になって当該データベースは、外部のデータベースとでデータベースリンク接続を行っていました。その外部のデータベースが高いCURRENT_SCN となっていたため、値が同期された時に当該データベースも高い値に同期されてしまったと推測できました。
（それは、データベースリンクを行った日のアラートログを見るとCURRENT_SCNが一気に増加していたことからです。）

　なお、エラーが発生した場合、データベースリンクを利用する処理は失敗(ロールバック)するが、各データベースで独立した処理は継続可能です。 
　再度 データベースリンクを実行した場合、時間経過により最大SCN制限が増加し、Current SCNが制限を下回っていれば、処理は成功します。

####補足）今回の事象発生でのレッスンズラーンドとして

　最近は、フルマネージド型のクラウド・サービスなどを利用することも多くなってきています。
　使いやすいデータベースが提供され、問合せのパフォーマンスも高速で、データベース管理も不要だと提案され、POC等を実施することもあると思いますが、その時にSCNの伝搬により基幹システムを止めてしまうなどの大きな影響を与える可能性もあるので安易な接続には注意が必要だと分かりました。
　なお、定期的にパッチを適用し新しいリリースで運用を行っていた場合は今回の事象は発生しません。しかし、全てが新しいシステムというわけではなく古いシステムも存在している企業も少なくはないと思います。直接は接続しなくてもSCNが伝搬していくことを考えて、接続によりSCNが伝搬していく可能性がある全てのシステムを考慮することが必要です。

#####・2020/7/7 追記）Oracle12cプラガブル・データベースのRedoログファイルについて

　Oracle12c のコンテナ・データベース(以下、CDB)と各プラガブル・データベース(以下、PDB)では、Redoログファイルが共用されています。つまり、CURRENT_SCNは、各PDBごとではなくCDB全体で値を管理しています。
　フルマネージド型のクラウド・サービスは、PDBを利用していることが多いと思われます。よって、接続する外部のデータベースがPDBであることは十分考えられます。
　そのような場合は、接続先のPDBが非常に低負荷なデータベースであったとしても、(直接は関わりも無い他社が利用している)他のPDBの中で高負荷なデータベースがひとつでもあれば、同じマルチテナントの中での全てのPDBのCURRENT_SCNは十分に上昇していると考えらます。
　そのような点でもフルマネージド型のクラウド・サービスなどを利用して、オンプレのデータベースから接続する場合には考慮が必要と考えられます。



以上