Home  |  Articles  |  Scripts  |  Consultancy  |  FAQs  |  Links

 

Upgrading Databases to SQL Server 2008 - a few lessons learned
article by Paul Ibison

Introduction

When upgrading a database from SQL Server 2000 to SQL Server 2008 there are many considerations. BOL does a good job of documenting the general process and other blogs will mention a script like the one below which can be used after the restore has completed to finish the job.

use Yourdbname
go
EXEC sp_changedbowner 'sa'
ALTER DATABASE yourdbname SET COMPATIBILITY_LEVEL = 100
dbcc updateusage(0)
exec sp_updatestats

This article lists some of the many extra issues and considerations we discovered during an upgrade project which were not so straightforward or simple to find. Some of these relate to replication issues but many are general ones you might find useful...

If merge replication is involved you'll have to:

(a) upgrade the scripts to SQL 2008 syntax and then make sure that the publication compatibility of the replication scripts is set to SQL 2008 on the publication, assuming all the subscribers are SQL 2008. NB this is NOT the same as setting the compatibility level for the databases. If this is not done, you'll not be able to use the new @replicate_ddl article property, drop merge articles or to replicate the new datatypes.

(b) make sure that the merge replication history on SQL 2005/8 is deleted. The MSmerge_history table may not be cleared up by the cleanup agent as there is a known bug in SQL 2005/8 that causes this when using the continuous schedule. When the merge agents are set to run continuously the stored procedure (sp_MShistory_cleanup) that does the delete relies on the MSMerge_sessions table to work out the records to be deleted. If you are running the agents continuously, there is only a single session until and unless the agent is restarted and the history records will not be deleted. The only way around this is to periodically stop and restart the Merge Agents if you use the continuous schedule.

(c) edit the properties for the merge articles. When you are scripting out merge publications, be sure to change certain defaults for the articles as required, especially because on SQL 2008 "compensating changes" are off by default, and identity range management is on by default.

Issues related to TSQL syntax

(a) start out by using the Upgrade Advisor to determine the required syntax changes. Some of these will be more subtle than they seem, especially the *= ones. We can't assume that a "straight swap" of *= with "Left Outer Join" will produce the same behaviour. Advise the application team that each *= one will need examining separately because of the following issues.

SELECT t.*
FROM dbo.titles t, dbo.sales s
WHERE t.title_id *= s.title_id
AND s.title_id IS NULL


-- this ANSI-89 syntax seems like it should simply translate to the following

SELECT t.*
FROM dbo.titles t
LEFT OUTER JOIN dbo.sales s
ON t.title_id = s.title_id
WHERE s.title_id IS NULL


-- try running them on a box with the Pub database though and you will see different rowcounts returned!!!!
-- the two alternative syntaxes below will work.
-- NB this is only an issue if the code in the WHERE clause refers to the table on the LHS of the *=

SELECT t.*
FROM dbo.titles t
LEFT JOIN (SELECT *
FROM dbo.sales
WHERE title_id IS NULL) s
ON t.title_id = s.title_id

SELECT t.*
FROM dbo.titles t
LEFT JOIN dbo.sales s
on s.title_id IS NULL
and t.title_id = s.title_id


(b) manually recreate the SQL programming objects - stored procedures, views, functions etc. The Upgrade Advisor won't give an exhaustive list of required changes so script out the procedures and other code, delete them on the SQL 2008 box and then recreate them back on the SQL 2008 database - this syntax checking is more comprehensive than the Upgrade Advisor and will pick up things like reserved keywords which might otherwise be missed (definitely the case on SQL 2005).

(c) be careful with your union statements as there is an issue with data type precedence and the UNION operator which might cause unexpected errors. Please see this article which explains the issues you might encounter.

(d) if the application uses user-defined datatypes in the tempdb and model databases, they must be scripted out from the old server and added in to the SQL Server 2008 box. Be careful though as using sp_addtype will add the type and assign the correct security privileges, while if your script uses the CREATE TYPE syntax this will not add the security and you'll need to subsequently issue the GRANT REFERENCES permissions for this to work.

(e) if the new server is 64-bit and it tries to use linked servers to a 32-bit SQL Server you might hit this issue. There's a simple proc referred to in the link which needs adding to the master database on the SQL 2000 box which will fix the problem.

(f) if xp_sendmail is used then try to get the application team to use database mail (SMTP) instead. If this is not possible, then be careful here as only 32-bit will work, so if the build is 64-bit MAPI will not work!!!!

(g) if you use user-defined functions and your UDF is not marked as "SchemaBound", there could be a huge performance loss because incorrect join operators may be used - see these articles for more info: 1, 2.

DTS packages - my preference is to try to get any packages removed from the database server, placed on an application server and run by an alternative scheduler e.g. Autosys. If this is not possible and the packages aren't going to be upgraded to SSIS i.e. they'll continue to be used as DTS packages then install the legacy components to allow the use of dtsrun.exe. Check this thoroughly as so far I have not been able to get the DTS designer components working on all SQL 2008 DTS packages (in some cases the icons are not visible despite all hacks mentioned on the newsgroups) but they worked fine for SQL 2005 DTS packages. In this case in your migration environment you might need to advise the application team to maintain a separate SQL Server 2000 server to hold the DTS packages which can be used to edit the packages if needed.

Check for any DBCC CHECKDB "DATA_PURITY" errors before going live. The DATA_PURITY checks are more rigorous on SQL 2008 and the DBCC CHECKDB check might flag up some alerts you normally don't see. So, restore the user databases onto SQL 2008 beforehand and run DBCC CHECKDB with DATA_PURITY - this will outline which data will need fixing before the migration.

Database properties need deciding upon. Discuss with the application team whether they want to use READ_COMMITTED_SNAPSHOT or not! Then check what is the standard policy being used for PAGE_VERIFY and TRUSTWORTHY.

When importing the logins be wary of the standard sp_help_revlogin. If this is used on SQL 2000 the sp_addlogin script which is produced has some flaws. The main on is that the CREATE LOGIN command which is run behind the scenes has a default of true for the policy checks and this means that password strength will be enforced and some logins might fail to be created. Better to use the modified version: sp_help_revlogin_2000_to_2005

When transferring jobs:

(a) make sure that any references to servernames are updated:

update msdb.dbo.sysjobsteps
set output_file_name = replace(output_file_name,'oldservername','newservername')
update msdb.dbo.sysjobsteps
set command = replace(command,'oldservername','newservername')


(b) be careful in the TSQL steps of user jobs. If there is a step which runs TSQL and this TSQL is formatted as follows:

exec myproc go

there will be problems in the case where the procedure "myproc" takes a parameter which is optional: in the case of the example above the "go" statement will then be interpreted as a literal value. This will error if the parameter is an incompatible datatype e.g. integer, or at worst it will be passed in as a legitimate value. So, this needs to be rewritten with a carriage return to work properly:

exec myproc
go