Transaction locking in Sql Server - sql-server

We have an old version of Cognos 7 running on Sql Server 2000 Enterprise.
It is issuing very badly constructed sql commands that are creating many locks which are escalating and blocking the server.
The targeted database is built once a day and then only used for selection.
As the Cognos queries can't be changed (short of upgrading to Cog 10), what can I do to improve this situation?
If I mark the database Read Only will this prevent the locks?

Locking does not happen in read-only databases, so this would (probably) help, assuming that locks are the only cause.
If you can issue a new query at the start of a session you could also change the transaction isolation level to read uncommitted, which would cause selects to ignore locks.

Related

SQL Transactional Replication - initial snapshot places table locks?

When the initial snapshot is being generated while configuring SQL Server
Transactional Replication, does anyone know if the snapshot agent places locks on the tables (articles) you have selected? I have some tables that contain 2+ millions rows and wanted to know if SQL Server actually places table locks to prevent updates while the publishing database is online. If locks are placed, then I want to run the initial snapshot during off peak hours in production.
Thanks!
In Transactional replication or any other type of replication the starting point is a snapshot of the database. The initial step of creating the snapshot is exactly the same in any type of the replication.
SQL Server does not obtain any kind of locks at all when creating a snapshot, it literally is a snapshot of the database at a certain point in time and creating snapshot does not interfere with any transactions. Uncommitted transactions are rolled back in the snapshot once it is created.
To read more about how database snapshot works read this article from MSDN How Database Snapshots Work
If you're running on an edition of SQL Server that supports database snapshots (as in create database [foo]... as snapshot of [bar]), then you can optionally use those as the basis of the snapshot. Check the #sync_method parameter of sp_addpublication. The caveat is that you still probably want to do it during a non-busy time of the day because of how database snapshots work (i.e. copy-on-write will slow down any write activity), but you won't be contending on locks.
Starting SQL Server 2005, the default #sync_method value for sp_addpublication is "concurrent", which means the tables are not locked during snaphsot agent run. Note this is not entirely true - the snapshot agent places schema locks on the tables, but the duration of that lock is mere seconds at most.
So if you set #sync_method = "concurrent", then no, updates, in theory, will not be blocked. If #sync_method = "native" (default in SQL Server 2000) or "character", then yes, updates will be blocked.

Using SAVE TRANSACTION with a linked server

Inside a transaction that have a savepoint I have to make a join with a table that is in a linked server. When I try to do it, I get the error message:
“Cannot use SAVE TRANSACTION within a distributed transaction”
The remote table data rarely changes. It is almost fixed. Is is possible to tell SqlServer to exclude this table from the transaction? I've tried a (NOLOCK) hint, but it isn't possible to use this hint for a table in a linked server.
Does anyone knows about a workaround? I'm using the ole SqlServer 2000.
One thing that you could do is to make a local copy of the remote table before you start the transaction. I know that this may sound like a lot of overhead, but remote joins are frequently a performance problem anyway and the SOP fix for that is also to make a local copy.
According to this link, the ability to use SAVEPOINTs in a Distributed transaction was dropped in SQL 7.
To allow application migration from Microsoft SQL Server 6.5 when
savepoints inside distributed transactions are in use, Microsoft SQL
Server 2000 Service Pack 1 introduces a trace flag that allows a
savepoint within a distributed transaction. The trace flag is 8599 and
can be turned on during the SQL Server startup or within an individual
session (that is, prior to enabling a distributed transaction with a
BEGIN DISTRIBUTED TRANSACTION statement) by using the DBCC TRACEON
command. When trace flag 8599 is set to ON, SQL Server allows you to
use a savepoint within a distributed transaction.
So unfortunately, you may either have to drop the bounding ACID transaction, or change the SPROC on the remote server so that it doesn't use SAVEPOINTs.
On a side note (Although I have seen that you have tagged it SQL SERVER 2000) but to make a point that SQL SERVER 2008 has remote proc trans Option for this.
In this case if the distributed table is not too large I would copy it to a temp table. If possible, include any filtering to get the number of rows to a minimum. Then you can proceed normally. Another option since the data changes rarely is copy the data to a permanant table and checking if anything has changed to prevent sending to much data over the network every time you run the transaction. You could only pull over the recent changes.
If you wish to handle transaction from UI level and you have Visual Studio 2008/.net fx 3.5 or + framework then you can wrap your logic with TransactionScope Class. If you dont have any frontends and you are working only on Sql Servers kindly ignore my answer...

SQL Server: do readers wait on writers (for same data)?

I've read that in older versions of SQL Server .. it had a pessimistic locking strategy. I.e. readers wait on writers for access to the same data (row or page level), unlike Oracle.
Is this still the case in newer versions ? I've read that the locking strategy has been changed in recent versions.
What you heard of is the SNAPSHOT ISOLATION, available since SQL Server 2005. Snapshot isolation, aka. row-versioning, is the default behavior in Oracle. You can make it default in SQL Server too, by enabling READ_COMMITTED_SNAPSHOT on the database:
ALTER DATABASE [<dbname>] SET READ_COMMITTED_SNAPSHOT ON;
With row versioning SQL Server does not acquire data locks during reads. If concurrent writes occur, the read will fetch the previous version of the row. For more details, read Row Versioning-based Isolation Levels in the Database Engine.
You should not confuse row versioning and snapshot with dirty reads. Dirty reads offer inconsistent data which makes programming a challenge, to say the least (ie. you should not use it!). Snapshot reads offer always a transactionally consistent image of the data.
by default SQL server uses READ COMMITTED isolation level, which means it will wait on uncommited changes before it tries to read them.
http://msdn.microsoft.com/en-us/library/ms173763.aspx
note that if you don't care about the accuracy of the data returned, you can always set you isolation level to Read Uncommitted this will give you all the records evening the ones that have binding changes
You can also use snapshot isolation level, which will give you all the record, including the latest known version of data that are currently being modified, without the current modification.
The locking strategy is something that is handled on connection by connection basis - this is something that can be set by the application and withing SQL Server itself.
Read about the Transaction Isolation Levels for more details.

Better concurrency in Oracle than SQL Server?

Is it true that better concurrency can be achieved in Oracle databases than in MS SQL Server databases? In particular in an OLTP scenario, such as an ERP system?
I've overheard an SAP consultant making this claim, referring to Oracle locking techniques like row locking and multi-version read consistency and the redo log.
Out of the box, Oracle will have a higher transaction throughput but this is because it defaults to MVCC. SQL Server defaults to blocking selects on uncommitted updates but it can be changed to MVCC as well so that difference should basically go away. See Read Committed Isolation Level.
See Enabling Row Versioning-Based Isolation Levels.
When the ALLOW_SNAPSHOT_ISOLATION
database option is set ON, the
instance of the Microsoft SQL Server
Database Engine does not generate row
versions for modified data until all
active transactions that have modified
data in the database complete. If
there are active modification
transactions, SQL Server sets the
state of the option to PENDING_ON.
After all of the modification
transactions complete, the state of
the option is changed to ON. Users
cannot start a snapshot transaction in
that database until the option is
fully ON. The database passes through
a PENDING_OFF state when the database
administrator sets the
ALLOW_SNAPSHOT_ISOLATION option to
OFF.
He/She was probably referring to the facts that:
In Oracle readers do not block writers and writers do not block readers
Oracle does not maintain a list of row locks so there is no significant overhead in locking and locks never escalate to the table level.
Starting with SQL 2005 this is no longer true - you can enable snapshot isolation and your writers will not block your readers, just like in Oracle.
Sql Server has row locking, several different transaction isolation levels, and a transaction log that can be replayed.
Maybe he's referring to Access, which does not have these.
Or maybe he believes Oracle uses better defaults. He might have a better argument there, but with either DBMS if you're talking ERP you better have a DBA who knows enough about the system to keep it tuned properly.

Single User: Turn off locking for Microsoft SQL Server

I'm running an upgrade script against a database hosted in Microsoft SQL Server. It's taking a while. Some of the queries are not worth optimising any further, for various reasons.
I'm the only person using this database: Is there a way that I can tell SQL Server to not bother with transactions/locking?
For instance, on a DELETE ... WHERE, does SQL need to get exclusive locks on the rows it's about to delete? If so, can I tell it not to bother, since this is the only running query?
See SQL Query Performance - Do you feel dirty? (Dirty Reads).
Edit: This is just speculation, but if you are the only connection to the SQL Server, you could get exclusive lock at the table level using WITH (TABLOCKX). You are sacrificing concurrency, but it could get faster.
Turn off Autocommit (aka implicit transactions); you'll need to do a commit() at the end. The log file will grow correspondingly large, be sure you've got enough disk space.
Is tempdb on the same disk?

Resources