Symptoms
Consider the following scenario:
-
A linked server is configured between a local server and a remote server that both have Microsoft SQL Server 2012 instances.
-
The local server is configured by using one collation, such as a case-insensitive collation.
-
The remote server has an object that is configured in a different collation from the local server, such as case-sensitive collation.
-
A connection is made from Microsoft JDBC driver for SQL Server, Microsoft ODBC driver for SQL Server, SQL OLE DB provider, or SQL Native Client to the local server.
-
The driver executes a Transact-SQL update query as a prepared statement that calls the sp_prepexec stored procedure on the local server.
-
The query updates a table on the remote server. This includes a column object that uses a different collation from the local server.
In this scenario, you may experience slow performance of the query execution. If you check the execution plan of the update query, you may see that a remote scan is performed on the table in the remote server without filtering. Therefore, the query may perform many reads when it scans the remote table and then retrieves all rows back to the local server.
For example, the query is prepared on the local server that has default case-insensitive collation, and the remote server has a table T1 that contains a column that are case-sensitive. The update will scan all rows of T1.
DECLARE @p1 INT
EXEC sp_prepexec @p1 output, N'@P0 NVARCHAR(16), @P1 NVARCHAR(16)',
N'UPDATE RemoteServer.RemoteDatabase.dbo.T1 SET COL1=@P0 WHERE COL2=@P1',
N'a', N'a'
SELECT @p1
Cause
The issue occurs because the prepared update query will scan the remote table when the collation does not match on both servers.
Resolution
After you apply the hotfix, you need to enable trace flag 4199 on the local server that hosts the linked server. For how to enable the traceflag, please refer to the More information section.
Note The hotfix only applies to the local server that hosts the linked server and optimizes the prepared statements. This hotfix does not apply to the remote server.
The issue was first fixed in the following cumulative update of SQL Server.
Cumulative Update 6 for SQL Server 2012 SP1 /en-us/help/2874879
Each new cumulative update for SQL Server contains all the hotfixes and all the security fixes that were included with the previous cumulative update. Check out the latest cumulative updates for SQL Server:
Hotfix information A supported hotfix is available from Microsoft. However, this hotfix is intended to correct only the problem that is described in this article. Apply this hotfix only to systems that are experiencing this specific problem.
If the hotfix is available for download, there is a "Hotfix download available" section at the top of this Knowledge Base article. If this section does not appear, submit a request to Microsoft Customer Service and Support to obtain the hotfix.
Note If additional issues occur or if any troubleshooting is required, you might have to create a separate service request. The usual support costs will apply to additional support questions and issues that do not qualify for this specific hotfix. For a complete list of Microsoft Customer Service and Support telephone numbers or to create a separate service request, visit the following Microsoft website:
http://support.microsoft.com/contactus/?ws=supportNote The "Hotfix download available" form displays the languages for which the hotfix is available. If you do not see your language, it is because a hotfix is not available for that language.
PrerequisitesTo apply this hotfix, you must have SQL Server 2012 installed.
Registry informationYou do not have to change the registry after you apply this hotfix.
Hotfix replacement informationThis hotfix does not replace any other hotfixes.
Status
Microsoft has confirmed that this is a problem in the Microsoft products that are listed in the "Applies to" section.
Workaround
To work abound the issue, use one of the following methods:
-
Do not use the prepared statements in the client application source code. You can use ad-hoc statements or callable statements such as stored procedures instead if the driver supports those interfaces.
-
Use matching collation on both servers.
More Information
To enable the trace flag, add startup parameter -T4199 or DBCC TRACEON(4199,-1) before the prepared statement is compiled to enable the behavior.
You can use one of the following methods to enable the Trace flag:
-
Before you start SQL Server, use Microsoft SQL Server Configuration Manager, right-click the affected instance, and add the startup parameter -T4199 so that it persists across restarts and across all connections to the instance in the future.
-
Dynamically enable the setting at runtime once the service gets started, and globally for all connections "(-1)." Be sure to free the procedure cache if you plan to do testing with the switch turned on or turned off.
Use the following to enable the setting globally and dynamically:
DBCC TRACEON(4199,-1)
DBCC TRACESTATUS(-1)
DBCC FREEPROCCACHE Use the following to disable the setting globally and dynamically:
DBCC TRACEOFF(4199,-1)
DBCC TRACESTATUS(-1)
DBCC FREEPROCCACHE