How to permanently set database to SINGLE_USER Mode? - sql-server

I implemented log shipping using dbatools command and was testing it out today. What ive noticed is when i query the restored/standby database, like a select on a table, the restore of transaction log fails until i disconnect from the instance.
Message
2021-09-24 23:00:23.60 *** Error: Could not apply log backup file '\\devops\c$\Users\devops_user\Documents\DBLogShipping\Backups\LogShippingFiles\test12345\test12345_20210924225000.trn' to secondary database 'test12345'.(Microsoft.SqlServer.Management.LogShipping) ***
2021-09-24 23:00:23.60 *** Error: Exclusive access could not be obtained because the database is in use.
RESTORE LOG is terminating abnormally.(.Net SqlClient Data Provider) ***
I found out that by setting the database to SINGLE_USER mode:
USE master
GO
ALTER DATABASE test12345
SET SINGLE_USER
--This rolls back all uncommitted transactions in the db.
WITH ROLLBACK IMMEDIATE
GO
the restore job will actually work fine whilst querying the database, so no need to disconnect from the server. I mean that is great! However, when i disconnected and reconnected later to the instance, I saw the SINGLE_USER mode disappeared...it looks like it reverted back to the default multi_user mode?
Is there a way to permanently have the database set in SINGLE USER mode?

Related

user: dbo unable to drop database

I have a SQL agent job whereby we do a restore of a full backup of production data on a nightly basis. We are setting up a new server and when I attempt to run the job on the new server I receive an error on the job of
3701 - Cannot drop database because it does not exist or you do not have permission.
This is confounding me because we are using the dbo user to accomplish this step and the database is listed in sys.databases catalog view. I have tried altering the database to put it into single_user to no avail.
The first step of the job kills all connections and that passes. I am not sure where this error is coming from because everything looks in accord to me. We can also drop the database manually through logging in as the sa.

SQL Server create user, that can use all dbs but sa can restrict him on some db

I need lock functionality on db to some user, while sa making changes on this db.
Example:
user create some databases:
database1
database2
database3
As sa i want to restrict user to making changes in database1, but user can still make changes in database2-3.
ALTER DATABASE database1 SET SINGLE_USER WITH ROLLBACK IMMEDIATE
isn't an option.
upd. Why isn't an option? Because:
I execute ALTER DATABASE database1 SET SINGLE_USER WITH ROLLBACK IMMEDIATE from java code using hibernate -> i got lock, ok. But when transaction commits other user can connect to database. I want do something like:
1. acquire lock
2. do anything, even restart my java application
3. release lock

SQL Server 2012 unable to turn off Snapshot Isolation

Using the code below I'm unable to turn off snapshot isolation. I'm using a SQL Server 2012 box. I can create brand new empty db, turn snapshot isolation on, but I can't turn it back off.
The "allow_snapshot_isolation OFF" line just spins it's wheels.
ALTER DATABASE SNAP SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE SNAP SET allow_snapshot_isolation OFF
ALTER DATABASE SNAP SET read_committed_snapshot off
ALTER DATABASE SNAP SET MULTI_USER
Are you sure that no other transactions were ran on the database? Remeber about implicit transactions which are used eg. by JDBC drivers (when you setAutocommit to false).
Snapshot isolation cannot be turn off if any of the previous transactions is pending. This is, because it has to be sure that any other transaction will not try to use previous row versions. However, it is possible to make queries spanning through more than one database so setting snapshot isolation is not only taking care of transaction on one database.
You can check if this is the case by using sp_who2 and SELECT * FROM sys.sysprocessesand searching for your altering process. sp_who2 will be showing that the process is suspended and by using sys.sysprocesses you will probably find out that its lastwaiting type is 'DISABLE_VERSIONING'.
So your solution is to rollback all transactions (or close conections in case of implicit transactions).
Be awared, that if you are using a connection pooling from some program, you may have, for example, 40 implicit transactions opened in two or three dbs. If they were opened after the snapshot mode had been turned on then turning it off will be impossible until they end.
I followed below for the same issue I was getting
USE master;
GO
ALTER DATABASE MYDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
ALTER DATABASE MYDB MODIFY NAME = MYDB_1;
GO
ALTER DATABASE MYDB_1 SET READ_COMMITTED_SNAPSHOT OFF;
GO
ALTER DATABASE MYDB_1 MODIFY NAME = MYDB;
GO
ALTER DATABASE MYDB SET MULTI_USER;
I ran the MSSQL query below to turn off ALLOW_SNAPSHOT_ISOLATION for master database:
ALTER DATABASE master SET ALLOW_SNAPSHOT_ISOLATION OFF;
GO;
Then, I got this error below:
SNAPSHOT ISOLATION is always enabled in this database.
And, I ran the MSSQL query below to turn on READ_COMMITTED_SNAPSHOT for master database:
ALTER DATABASE master SET READ_COMMITTED_SNAPSHOT ON;
GO;
Then, I got this error below:
Option 'READ_COMMITTED_SNAPSHOT' cannot be set in database 'master'.
Because the documentation says below:
The ALLOW_SNAPSHOT_ISOLATION option is automatically set ON in the
master and msdb databases, and cannot be disabled.
Users cannot set the READ_COMMITTED_SNAPSHOT option ON in master,
tempdb, or msdb.

Set offline failed for database 'MyDB'

My program failed by this exception:
System.Data.SqlClient.SqlException:
The transaction log for database 'MyDB' is full.
To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases
I noticed that my tables doesn't load in SQL Management Studio and i cann't open database properties window
Then I try to change my log file to autogrowth by this statement:
ALTER DATABASE MyDB
MODIFY FILE
(NAME=MyDB_Log,MAXSIZE=2TB,FILEGROWTH=20MB);
this statement executed successfully but doesn't help me to recover my database
Then i try to set offline MyDB the operation failed by some exception
Then i set the database in single user mode but the exception still exists
Then i try this statement:
ALTER DATABASE MyDB SET EMERGENCY;
GO
ALTER DATABASE MyDB set single_user
GO
DBCC CHECKDB (MyDB, REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS;
GO
ALTER DATABASE MyDB set multi_user
GO
This statement failed too on first line.
And now i don't know what should I do.
Follow the following steps.
Open up SQL Management Studio and connect to your database server
Right-click your database
Click Properties
Click the Options link
Set the Recovery Model to Simple as follows
Click OK
Once this is complete, right click on the database again
Click Tasks>Shrink>Files
On the Shrink Database window select the file type as 'Log' . The file name appears in the filename drop down as databasename_log as follows:
The space used versus the space allocated displays. After you set the recovery model to Simple, the majority of the space in the transaction log released.
Ensure that the Release unused space radio button is selected.
Click OK on this window to shrink the transaction log.
You might also want to read through this short post
http://sqlity.net/en/556/t-sql-tuesday-25-%E2%80%93-sql-server-tips-tricks/

Booting users from SQL Server

I'm not sure how to even ask this question. We are running SQL Server 2008 R2. I'm not the admin, but a programmer. I need to write an application that updates some database stuff at night. I'm going to set a flag to disable logins to the database, but I want to make a particular database unavailable to anyone except me, even if someone is already logged in to the database. My program will run nightly, as a batch file, presumably with admin privileges.
I'm expecting to produce something like a script of SQL commands. I could take the database offline, except I need to make modifications to it myself. Not sure the best way to handle this.
You can basically just set the database to "single-user" mode and use it exclusively - this T-SQL will do this:
USE master;
GO
ALTER DATABASE AdventureWorks2012
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
(of course - replace AdventureWorks2012 with your own database name!)
This will make the database "single-user", e.g. only you have access to it, and it will boot off any users that's currently online, and will rollback all open transactions.
Read more about single user mode on MSDN!
This example sets the database to SINGLE_USER mode to obtain exclusive access. The termination option WITH ROLLBACK IMMEDIATE is specified in the first ALTER DATABASE statement. This will cause all incomplete transactions to be rolled back and any other connections to the AdventureWorks2012 database to be immediately disconnected.
Since you are using an administrative account to perform the updates, I'll assume the account is in one of these roles: db_owner, dbcreator, sysadmin. Use the ALTER DATABASE SET ... syntax to control database access during the DML operations.
The assumption is that database users you want to lock out aren't in the above mentioned roles.
USE master;
-- only allow members of db_owner, dbcreator, or sysadmin roles to access
-- database, allowing current transactions time to complete. if you want to
-- drop access immediately, add WITH ROLLBACK IMMEDIATE
ALTER DATABASE SET RESTRICTED_USER;
-- data load
-- return database to normal operating state
ALTER DATABASE SET MULTI_USER;

Resources