web-dev-qa-db-ja.com

サブスクリプションの初期化でエラー「オプション "INLINE = ON"はこの関数では無効です」がスローされる

シナリオSQLエステートをSQL Server 2019にアップグレードし、本番環境になるものをセットアップしました。

From:SQL2008R2 Standard/Windows Server 2008R2-Primary Server/Secondary Server(Windows Fail-over Cluster)&Reports Server(Transactional Replication)。

To:SQL2019 Standard/Windows Server 2019-Primary Server/Secondary Server(Always-On)&Reports Server(Transactional Replication)

2008R2からのバックアップは2019年に復元され、互換性レベルは最新に設定されました。常時接続のセットアップは比較的スムーズに行われ、現在のアプリケーションに対する初期テストでは互換性の問題は示されていません。

問題は、純粋にトランザクションレプリケーションの設定にあります。レプリケーションが必要なデータベースは2つあり、それぞれ1つのパブリケーションがプライマリおよびパブリッシャーおよびディストリビューターです。

問題レポートサーバー上の各DBのサブスクリプションの初期化中に、関数の作成ポイントに到達し、以下のエラーが生成されるまで、正常に実行されます。

最初のデータベース:

メッセージ:オプション「INLINE = ON」は、この機能では無効です。関数のINLINEオプションでサポートされる構成については、ドキュメントを確認してください。コマンドテキスト:CREATE FUNCTION [dbo]。[f_clienttels-Mirror Copy ce2d3663eb494f3589bd5000dad1bf1f](@ ClientID [int])RETURNS varchar WITH INLINE = ON、EXECUTE AS CALLER AS BEGIN ......

2番目のデータベース:

メッセージ:ステートメント "CREATE/ALTER FUNCTION"に無効なオプションが指定されました。キーワード「with」付近の構文が正しくありません。このステートメントが共通テーブル式、xmlnamespaces句、または変更追跡コンテキスト句の場合、前のステートメントはセミコロンで終了する必要があります。 「)」付近の構文が正しくありません。コマンドテキスト:CREATE FUNCTION [dbo]。[GetGroupAndDescendantGroupsSelective-ミラーコピー46f329d5eed444428f45b052f07c7ea8](@ GroupId [int])RETURNS TABLE WITH INLINE = ON AS RETURN(WITH GroupsCTE AS(........).

これらは両方とも異なるエラーですが、両方とも「INLINE = ON」オプションと関係があると思います。これらの関数のどちらにもこのオプションはありません。サブスクリプションから記事を削除すると、これらの関数は明示的にインラインオプションを使用しません。次の関数で同じエラーが発生するだけです(関数がCTEで始まる場合はCTEエラー、そうでない場合はINLINE = ONエラー)。

そのため、レプリケーションは、レプリケーションの前に関数に「WITH INLINE = ON」を挿入してから、追加したときにエラーを表示しています。

私はすべてのインスタンスに最新のCU4更新15.0.4033.1をパッチし、両方のサーバーでこれらの機能をテストし(機能する)、データベース内のすべての機能/プロシージャを検証し、すべて正常であることを確認しました。現在の2008R2環境では、数か月前にパブリケーションを再作成する必要があり、これらのエラーは発生しませんでした。今のところ回避策として、サブスクライバーで関数を手動で作成し、すべての関数の記事をパブリケーションから削除しています。

これに対する解決策の助けをいただければ幸いです。このエラーへの唯一の参照(1番目のDBから)は、それが文書化されていないこと(下記のリンク)について言及しているだけで、他のフォーラムの投稿にはそれが記載されていません。

16203-オプション「INLINE = ON」は、この機能では無効です。関数のINLINEオプションでサポートされる構成については、ドキュメントを確認してください。

From: Brent Ozar-What's New in SQL Server 2019’s sys.messages:More Unounced Features

マイクロソフトとの有効なサポート契約は結んでいませんが、ライセンスを提供したサプライヤを介してそれらに連絡を取ろうとしているので、彼らが私たちに戻ってきたらここでアップデートを提供します。

必要に応じてさらに情報を提供できます。

3
Ollie

これらの調査結果の投稿が遅れたことをお詫びし、私は1か月以上も前からマイクロソフトのサポートに転送しました(ある時点で、レプリケーションは関数とストアドプロシージャをレプリケートするように設計されておらず、修正としてそれらをレプリケートするだけではないという?!!)、私は彼らに実験からの大量の証拠を送った後、彼らは最終的にそれが本当にバグであることを最終的に認めました。このバグは実際にはSQLエンジンのデータベースの復元/アップグレードプロセスにあり、トランザクションレプリケーション自体に最初に現れたものではありません。

原因/調査

これの根本的な原因は、データベースが以前のバージョンのSQL(私の場合は2008R2)から新しいSQL 2019インスタンスに復元されるときに、デフォルトでinline_typeで関数にフラグを立てるように見えることです= 1insys.sqlmodules(これはGUIの関数プロパティで「インライン化のためにマークされている」として明示されます) 。 inlinableと呼ばれるフラグがテーブルにあります。これは、最初に調査したときに、レプリケーションがinline_type代わりに、inlinableは回避策の後もtrueのままであり、レプリケーションを妨げません。

私は次の手順でこの結論に達しました:

  • 2008R2からデータベースを復元し、互換性を150に設定:inline_type = 1およびinlinable = 1で100以上の関数が復元されたため、レプリケーションが開始されると、これらの関数で...

16203-オプション「INLINE = ON」は、この機能では無効です。

このオプションは、inline_typeフラグがあるため、レプリケーションによって自動的に適用されます。

OR

ステートメント "CREATE/ALTER FUNCTION"に無効なオプションが指定されました。キーワード「with」付近の構文が正しくありません。

2番目のエラーの理由は、レプリケートされたコードでINLINE = ONが自動的に宣言されるため、関数にCTEが含まれていると構文が無効になるためです。

  • 復元されたデータベースのクローン:上記と同じ結果
  • データベースの互換性レベルを140/130/120/110に設定します(2019年のインライン化前の変更):上記と同じ結果。
  • 最初にレプリケーションサブスクライバでデータベースを復元およびアップグレードする:上記と同じ結果。
  • INLINE = OFFを手動で設定すると、問題は修正されず、一部の関数では無効な構文として報告されます。
  • ALTER DATABASE SCOPED CONFIGURATION SET TSQL_SCALAR_UDF_INLINING = Off:上記と同じ結果。
  • プッシュではなくプルとしてサブスクリプションを作成する:上記と同じ結果。
  • 関数の1つを削除して再作成する:再作成された関数は成功し、次の関数で失敗します。
  • 生成されたスクリプトから完全にデータベースを再作成:レプリケーションでエラーなしで動作します。

回避策

このための唯一の実行可能な回避策は、復元/アップグレード後にすべての関数を再作成して、フラグが正しく設定されるようにすることです。 注:すべての関数に誤ってフラグが付けられるわけではありません。一部はinline_type= 1で正当にフラグを立てる必要があります。回避策はこれらを正しく設定しますそのため、以下のスクリプトに引っかかっても害にはなりません。

私はすばやくダーティなPowerShell(下記)を介してこれを行いましたが、同様の問題に関するMicrosoftの記事の一部が示唆していますsp_refreshsqlmoduleこれは最初は機能しませんでしたインスタンス、しかし私には論理的な理由が見当たらないので、これの代わりに最初のインスタンスで試してみる価値があります。

#Recreate all function to fix inlining issue
#BACKUP DATABASE FIRST! Small Potential for dropped functions to not recreate!
$SQLServer = "YOURSERVER\Instance"
$SQLDatabase = "YourDatabase"
$Constring = "server='$SQLServer';database='$SQLDatabase';trusted_connection=true;"
$GetFunctionsSQL = "SELECT m.definition,o.name  FROM sys.sql_modules m INNER JOIN 
sys.objects o ON m.object_id = o.object_id WHERE m.inline_type = 1 AND o.type IN ('FN','IF','TF')"
$con = New-Object "System.Data.SqlClient.SqlConnection"
$con.ConnectionString = $Constring
$cmd = New-Object "System.Data.SqlClient.SqlCommand"
$cmd.Connection = $con
$cmd.CommandText = $GetFunctionsSQL
$sda = New-Object "System.Data.SqlClient.SqlDataAdapter"
$sda.SelectCommand = $cmd
$dt = New-Object System.Data.Datatable
Try {
   $sda.Fill($dt)    >> $null
}
catch {
   Write-Error "$_"
}
foreach ($r in $dt.Rows) {
   $nme = $r["name"]
   $def = $r["definition"]
   Write-Host "Processing $nme"
   $con = New-Object "System.Data.SqlClient.SqlConnection"
   $con.ConnectionString = $Constring
   $cmd = New-Object "System.Data.SqlClient.SqlCommand"
   $cmd.Connection = $con
   $cmd.CommandText = "drop function $nme"
   Try {
      $cmd.Connection.Open()
      $res = $cmd.ExecuteNonQuery()
   }
   catch {
      Write-Error "$_"
   }
   if ($res -eq "-1") {
      Write-Host "Reacreating..."
      $cmd.Connection.Close()
      $cmd.Connection = $con
      $cmd.CommandText = "$def"
      Try {
         $cmd.Connection.Open()
         $res = $cmd.ExecuteNonQuery()
      }
      catch {
         Write-Error "$_"
      }
      $cmd.Connection.Close()
   }
}

最終的な解決

この正確なシナリオを実際に解決するには、SQLエンジン/データベースの復元コード内で根本的な原因を修正する必要があります。マイクロソフトは、これに対する修正がSQL Server 2019 CU6 Updateに実装されることを確認しています。

最後に、CU6で予定されているこの問題に対するHotfixリクエストを上げることができます。これは2020年7月または8月にリリースされる予定です。

3か月待たなければならないときにHotfixと呼ばれることに同意します。

これが他の誰かを助け、マイクロソフトのサポートに連絡するとき、あなた自身の調査の多くをプロンプトなしで行い、彼らに送る準備ができているというレッスンとして役立つことを願っています、それは本当にプロセスをスピードアップするのに役立ちました。

0
Ollie

この記事を参照 SQL 2019にアップグレードした後、UDFを削除して再作成することが唯一の解決策でした。

SQL 2019へのアップグレード後、Sys.sql_modulesのinline_Type列は1になります。UDFを削除して再作成すると、Inline_typeは0になり、レプリケーションの初期化は正常に機能します。

4
SqlSan

一部のスカラーUDFを含むパブリケーションをSQL 2016からSQL 2019に移行しているときにこの問題が発生しました。パブリッシャーデータベースのデータベース設定を変更しても問題は解決しませんでした。また、サブスクライバーには古いバージョンのSQL Serverが含まれているため、 "WITH INLINE = OFF"を追加することは関数定義のオプションではありません。したがって、私の解決策は、関数定義内に次のコードを追加して、udfをインライン化できないようにすることです。

--Junk code to force is_inlineable to 0 
DECLARE @dummy DATETIME; SELECT @dummy = GETDATE()

Sys.sql_modulesで選択を行うと、is_inlineableは0と表示され、スナップショットスクリプトが正常に生成されます。

3
Kevin Daymont