So you may have read about CF 8's new ability to return generated keys. For SQL Server 2000 and greater this means that the driver attempts append the SELECT SCOPE_IDENTITY() statement to end of insert statements. If you want to get an idea of how this is done you can take a look at the source for the jTDS JDBC driver. While the jTDS driver isn't what ships with ColdFusion, you can bet that CF's SQL Server driver from DataDirect is doing something similar. In fact you can actually confirm this using SQL Profiler.
Take the following simple test table:
CREATE TABLE TestTable (
ID int IDENTITY (1, 1) NOT NULL ,
TestText nvarchar (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
Running the following on ColdFusion code:
<cfquery name="testInsert" datasource="scratch_wrapped" result="testResult1">
INSERT INTO TestTable (TestText)
VALUES (<cfqueryparam value="This is a test." cfsqltype="cf_sql_varchar">)
Results in this:
I've pointed out where the "select SCOPE_IDENTITY()" was appended to the prepared statement in the SQL Profiler trace above.
The above example demonstrates a prepared statement, but you can also get automatically generated keys with certain update statements as well. (See this article for some examples.) Now this is a great feature when you need it, but what if you don't? We are in the process of upgrading a fairly large application to CF 8 and this seems to be causing some major issues. Here is what is happening:
Our application runs on three instances of CF 8 Enterprise. After doing extensive functional testing in a test environment we updated the first production server CF 8 and everything seemed to be fine. However, after we upgraded the second server we started to see some database blocking issues. We run SeeFusion and after the upgrade we started to see the following error fill up our JRun logs:
Thinking maybe the issue had something to do with SeeFusion I removed it from the two upgraded servers but we still saw blocking. In fact we actually had a client/server distributed deadlock which brought down our production site for a few minutes. At this point I still wasn't sure what was causing the issue but my boss pointed out that since upgrading we were seeing about 3 times the amount of network traffic going into and out of our database server. This combined with the error message from SeeFusion led me to take a closer look at the changes to cfquery and ColdFuison JDBC drivers.
I did some experimenting and, from what I can tell, ColdFusion tries to return generated keys whether or not you have specified a result attribute for your cfquery tag.
Take, for example, the following query where I add the SELECT SCOPE_IDENTITY() statement and don't specify a result attribute:
<cfquery name="testInsert" datasource="scratch_wrapped">
INSERT INTO TestTable (TestText)
VALUES ('This is a test.')
This causes SeeFusion to log the following to the cfusion-out.log file:
2008-01-28 13:18:50 SeeFusion: ----Statement: exception start ----
2008-01-28 13:18:50 SeeFusion: java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Auto-generated keys were not requested, or the SQL was not a simple INSERT statement.
at macromedia.jdbc.base.BaseExceptions.createException(Unknown Source)
at macromedia.jdbc.base.BaseExceptions.getException(Unknown Source)
at macromedia.jdbc.base.BaseStatement.getGeneratedKeys(Unknown Source)
2008-01-28 13:18:50 SeeFusion: ----Statement: exception end ----
If you notice, there is a call to coldfusion.server.j2ee.sql.JRunStatement.getGeneratedKeys(). This query is not a simple insert so this error is thrown and silently handled by ColdFusion. Judging by the number of similar "Auto-generated keys" errors in my cfusion-out.log there appear to be quite a few query conditions that can throw this error.
As for the the issue we are seeing, our application does a lot of logging so it runs several simple inserts for every page request. Some of these use cfqueryparam and some do not. My best guess is that the added overhead of appending SELECT SCOPE_IDENTITY() to some of those logging queries, along with overhead of throwing and silently handling the "Auto-generated keys" error above is slowing things down enough that we are seeing these SQL Server blocking issues. I'd love to be able to disable the autoGeneratedKeys behavior in CF 8 to confirm this, but so far I haven't been able to figure out how. If anyone knows please let me know.
The good news is the blocking issue does not seem to be related to SeeFusion; SeeFusion was simply relaying an error message that CF 8 ignores. As reported by Dan G. Switzer, II, there is a fix for this. So if you find that your version of SeeFusion is reporting these errors be sure to update to the latest and greatest, which as of this writing is 4.0.7. (And thanks to the Webapper team for answering my SeeFusion questions and getting this new build to me last week!)
Also, I'm not sure if this would be considered a ColdFusion bug or not, but we have opened a ticket with Adobe to see what we can figure out. I'll be sure to post a follow up as I learn more.