Cannot enable Query Store on SQL Azure database - sql-server

One of our Azure SQL databases ran out of space recently which I believe resulted in Query Store switching over to "READ_ONLY".
I increased the size of the database however this has not resulted in the status changing even though running this query:
SELECT desired_state_desc, actual_state_desc, readonly_reason, current_storage_size_mb, max_storage_size_mb
FROM sys.database_query_store_options
Suggests that there is enough space available:
desired_state_desc actual_state_desc readonly_reason current_storage_size_mb max_storage_size_mb
READ_WRITE READ_ONLY 524288 522 1024
I tried to alter the Query Store status to Read_Write by running this statement (as database server admin user):
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (OPERATION_MODE = READ_WRITE)
However, the statement failed with the following error:
User does not have permission to alter database 'QueryStoreDB', the database does not exist, or the database is not in a state that allows access checks.
Has anybody manged to switch SQL Azure Query Store to READ-WRITE so performance statistics start being collected again?

First, let’s try to clear the query store:
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE CLEAR;
GO
If that did not work, let’s run a consistency check.
ALTER DATABASE [DatabaseOne] SET QUERY_STORE = OFF;
GO
sp_query_store_consistency_check
GO
ALTER DATABASE [DatabaseOne] SET QUERY_STORE = ON;
GO
Try more options to troubleshoot this issue on this following article:

Related

SQL Server Permission Chaining

I have the following issue:
I have two different databases, db1 and db2. I have an application that loads data into db2 or db3. db1 has a few tables that the application uses to determine behavior, including which db the application should load data into.
Users need to have write access to db1 to operate the application (there is a console application that writes to tables in db1, operating with windows authentication).
Users should not have DML privileges to db2 and db3, with the exception of a few predetermined operations. We grant AD groups database roles to control access from and organization perspective. Specifically, I'm trying to build a stored procedure in db1 that operators can use to reverse data loaded to db2 or db3 with appropriate logging.
I'm attempting to use create proc ... execute as owner to accomplish this, but it does not seem to be working when I try to hit tables in db2/db3 (I'm thinking that "execute as owner" operates on db level users an not server level logins?). The following causes a permission error stating that the owner (myself) does not have permissions to db2/db3.
use db1
go
create proc dbo.wrapper #recordid int
as begin
/*
capturing user
*/
declare #usr varchar(255) = SUSER_SNAME()
exec dbo.inner #usr , #recordid
end
use db1
go
create proc dbo.inner #usr varchar(255), #recordid int
with execute as owner
as begin
/*
logic to determine whether to update db2 or db3 goes here
*/
insert db2.rolled_back
select * , #usr from db2.transactions where id = #recordid
delete from db2.transactions where id = #recordid
insert db3.rolled_back
select * , #usr from db3.transactions where id = #recordid
delete from db3.transactions where id = #recordid
end
Is there a way to get this to work? I've heard that certificate signing could do this, does anyone have any experience using certificate users. Our DBA's would rather not have to maintain certificates, so if there is a way to get this to work without certificates that would be best.
Any advice would be helpful.
Thank You!
I'm going to cover the cross database chaining side of thing here. note that there are certainly security considerations when using this method. For example someone with permissions to create objects in one database can give themselves access to data in another database with the owner, when they themselves have no access to the other database. The security concerns, however, are out of scope of this answer.
Firstly, let's create a couple of test databases.
USE master;
GO
CREATE DATABASE Chain1;
CREATE DATABASE Chain2;
Now I'm going to CREATE a LOGIN, which is disable and make that the owner of these 2 databases. The databases having the same owner is important, as otherwise the chaining won't work.
CREATE LOGIN ChainerOwner WITH PASSWORD = N'SomeSecurePassword123';
ALTER LOGIN ChainerOwner DISABLE;
GO
ALTER AUTHORIZATION ON DATABASE::Chain1 TO ChainerOwner;
ALTER AUTHORIZATION ON DATABASE::Chain2 TO ChainerOwner;
I'm also going to create a LOGIN which we're going to use to test on:
CREATE LOGIN SomeUser WITH PASSWORD = N'SomeSecurePassword123';
Great, now I can create a few objects; a table in Chain1, a PROCEDURE in Chain2 that accesses the TABLE, and a USER in both databases for SomeUser. In Chain1 the USER will be given no permissions, and in Chain2 the user will be given the permsision to EXECUTE the PROCEDURE:
USE Chain1;
GO
CREATE TABLE dbo.SomeTable (I int IDENTITY,
S varchar(10));
INSERT INTO dbo.SomeTable (S)
VALUES ('abc'),
('xyz');
GO
CREATE USER SomeUser FOR LOGIN SomeUser;
GO
USE Chain2;
GO
CREATE PROC dbo.CrossDBProc #I int AS
BEGIN
SELECT I,
S
FROM Chain1.dbo.SomeTable
WHERE I = #I;
END;
GO
CREATE USER SomeUser FOR LOGIN SomeUser;
GO
GRANT EXECUTE ON dbo.CrossDBProc TO SomeUser;
GO
Great, all the objects are created, now let's try to EXECUTE that PROCEDURE:
EXECUTE AS LOGIN = 'SomeUser';
GO
EXEC dbo.CrossDBProc 1; --This fails
GO
REVERT;
GO
This fails, with a permission error:
The SELECT permission was denied on the object 'SomeTable', database 'Chain1', schema 'dbo'.
This is expected, as there is no ownership chaining. let's, therefore enable that now.
USE master;
GO
ALTER DATABASE Chain1 SET DB_CHAINING ON;
ALTER DATABASE Chain2 SET DB_CHAINING ON;
Now if I try the same again, the same SQL works:
USE Chain2;
GO
EXECUTE AS LOGIN = 'SomeUser';
GO
EXEC dbo.CrossDBProc 1; --This now works
GO
REVERT;
GO
This successfully returns the result set
I
S
1
abc
So, yes you can chain cross database, but it requires some set up, and (again) there are security considerations you need think about.
Clean up:
USE master;
GO
DROP DATABASE Chain1;
DROP DATABASE Chain2;
GO
DROP LOGIN ChainerOwner;
DROP LOGIN SomeUser;

SQL Server error 4928 - no replication or CDC

I'm trying to rename a column but I'm getting this error:
Msg 4928, Level 16, State 1, Procedure sp_rename, Line 547
Cannot alter column 'appraisal_id' because it is 'enabled for Replication or Change Data Capture'.
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
No replication is configured. At some point CDC was enabled on the database and a few tables (including the table I'm trying to rename a column on), but it is currently disabled on the database. I'm assuming it was disabled on the database without first disabling it on each table, and that's causing this problem. I would say this is a SQL Server bug.
As a workaround, I can re-enable CDC on the database, disable it on the table, and then disable it on the database, then I can rename the column.
I'm trying to find out which tables have this problem (our database has 3500 tables), so I can fix this once and for all and avoid this in future. I don't see anything in any of the system tables (I checked sys.tables, sys.objects, sysobject, sys.columns, syscolumns) that indicates this table has CDC enabled. All the relevant columns (is_published, is_schema_published, is_merge_published, is_tracked_by_cdc) have value 0.
Any idea where SQL Server stores this information ?
I'm using SQL 2008 and 2008 R2; the problem occurs on both.
You can reproduce the problem with the script below:
CREATE DATABASE TestCDC
GO
USE TestCDC
GO
CREATE TABLE dbo.fish(
fish_id int NOT NULL
, name nvarchar(100) NOT NULL
, CONSTRAINT XPKfish PRIMARY KEY (fish_id))
GO
EXECUTE sp_cdc_enable_db
GO
EXECUTE sys.sp_cdc_enable_table
#source_schema = N'dbo'
, #source_name = 'fish'
, #capture_instance = 'my_capture'
, #role_name = NULL
, #filegroup_name = NULL
GO
EXECUTE sp_cdc_disable_db
GO
EXECUTE sp_rename 'dbo.fish.name', 'fish_name'
I'm assuming you have figured this out since but I just came across this problem again and perhaps people would like a good answer on this thread.
It seems that if you disable CDC on the database level it does disable it everywhere but these errors keep occurring.
In order to overcome this problem the trick is to:
Activate CDC on the DB level
EXECUTE sp_cdc_enable_db
GO
Activate CDC on the table
EXEC sys.sp_cdc_enable_table
#source_schema = N'dbo',
#source_name = N'MyTable',
#role_name = N'MyRole',
#supports_net_changes = 1
GO
Disable CDC on the table
EXEC sys.sp_cdc_disable_table
#source_schema = N'dbo',
#source_name = N'MyTable',
#capture_instance = N'dbo_MyTable'
GO
Disable CDC on the DB level
EXECUTE sp_cdc_disable_db
GO
I don't have access to an instance with CDC enabled to test this, but based on the text of the internal procedure used to enable cdc (usefully made accessible here), it might be that one or more tables in the cdc schema contain the information - I'd suggest cdc.change_tables as a starting point.
In sys.tables, there are two columns that will tell you whether the server thinks the table is replicated or enabled for cdc (regardless of the database status for those features). Do the ff:
select name, is_tracked_by_cdc, is_replicated
from sys.tables
where is_tracked_by_cdc = 1
or is_replicated = 1
If either is true, you will have to enable the database feature in question (e.g. CDC), disable the feature for any tables that have it, then re-disable the feature at the database level.

While Restoring the Sql Server Data base Status is Stuck

I am facing one problem ie.
I create one data base...
and then I restored it...
the back up is from the existing data base only..
after successfully restored old one ie. parent one is showing that
"BRPL_Payroll _31-01-2014" (Restoring.........)
like above it is showing....
and then i execute the below query..
RESTORE DATABASE BRPL_Payroll _31-01-2014 ;WITH RECOVERY
but here it is showing that incorrect syntax at '-'
I think my data base name is having some date 31-01-2014
how can i execute the above query...
You can easily restore a database Using the UI and before pressing OK to restore you select Script and SQL-Server will show you the script (Query) you need to run in order to execute the step.
If you don't have direct access I can give you a restore script which works to restore a database from file. But you have to replace of course the path to your DB and your DB Name :
USE [master]
ALTER DATABASE [YURDATABASENAME] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [YURDATABASENAME] FROM DISK = N'C:\your\backup\path\backup.bak' WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 5
ALTER DATABASE [YURDATABASENAME] SET MULTI_USER
GO

Dropping SQL Server database: handling concurrent connections

During my integration tests, I try to drop database using:
USE master
ALTER DATABASE TestXyz SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE TestXyz
However, quite often (given the number of tests) one of the application background processes manages to get between SET SINGLE_USER and DROP DATABASE, which makes it single user of the database and breaks the DROP.
I can not use RESTRICTED_USER, as the application currently has db_owner permission (due to a large amount of legacy code, some of which requires it, so it will not be changed just for the tests).
I can not use OFFLINE as it does not delete database files from the disk.
How would you solve this problem?
OK plan b... iterate a drop of connections and rename the DB to get it away from the applications domain. Then drop it. To handle iterating through connections a try catch on the rename will hopefully allow it to run until it is able to drop the connection. Example code below creates a DB TestDB; renames it to testdb2 in the while loop before dropping it after the loop has succeeded.
-- Setup a scratch Db for testing
create database testdb
go
use testdb
while exists (select name from sys.databases where name = 'testdb')
Begin
DECLARE #DbName nvarchar(50) SET #DbName = N'testdb'
DECLARE #EXECSQL varchar(max) SET #EXECSQL = ''
SELECT #EXECSQL = #EXECSQL + 'Kill ' + Convert(varchar, SPId) + ';'
FROM MASTER..SysProcesses
WHERE DBId = DB_ID(#DbName) AND SPId <> ##SPId
EXEC(#EXECSQL)
Begin try
EXEC sp_renamedb 'testdb', 'testdb2'
end try
Begin Catch
print 'failed to rename'
End Catch
end
drop database testdb2
Try this once:
Stop application services and run your query.
Stop application services and restart SQL Server Services and then run your query.
I have finally solved it using the following approach:
ALTER LOGIN MyAppUser DISABLE
ALTER DATABASE TestXyz SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DROP DATABASE TestXyz
ALTER LOGIN MyAppUser ENABLE
Since I can use different login for test database management process, this allows me to block application from accessing the DB. (The reason for SINGLE_USER here is just to kick already connected users. I haven't checked if ALTER LOGIN already does that, but I assume it does not).
Alternative option is to delete MyAppUser from the database before dropping it, however I thought about it only now and do not have code for it.

How long should SET READ_COMMITTED_SNAPSHOT ON take?

How long should it take to run
ALTER DATABASE [MySite] SET READ_COMMITTED_SNAPSHOT ON
I just ran it and it's taken 10 minutes.
How can I check if it is applied?
You can check the status of the READ_COMMITTED_SNAPSHOT setting using the sys.databases view. Check the value of the is_read_committed_snapshot_on column. Already asked and answered.
As for the duration, Books Online states that there can't be any other connections to the database when this takes place, but it doesn't require single-user mode. So you may be blocked by other active connections. Run sp_who (or sp_who2) to see what else is connected to that database.
Try this:
ALTER DATABASE generic SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
OK (I am the original questioner) so it turns out this whole time I didn't even have the darn thing enabled.
Here's the ultimate code to run to enable snapshot mode and make sure it is enabled.
SELECT is_read_committed_snapshot_on, snapshot_isolation_state_desc,snapshot_isolation_state FROM sys.databases WHERE name='shipperdb'
ALTER DATABASE shipperdb SET allow_snapshot_isolation ON
ALTER DATABASE shipperdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE shipperdb SET read_committed_snapshot ON
ALTER DATABASE shipperdb SET MULTI_USER
SELECT is_read_committed_snapshot_on, snapshot_isolation_state_desc,snapshot_isolation_state FROM sys.databases WHERE name='shipperdb'
This works even with connections active (presumably you're fine with them getting kicked out).
You can see the before and after state and this should run almost immediately.
IMPORTANT:
The option READ_COMMITTED_SNAPSHOT above corresponds to IsolationLevel.ReadCommitted in .NET
The option ALLOW_SNAPSHOT_ISOLATION above corresponds to IsolationLevel.Snapshot in .NET
Great article about different versioning
.NET Tips:
Looks like Isolationlevel.ReadCommitted is allowed in code even if not enabled by the database. No warning is thrown. So do yourself a favor and be sure it is turned on before you assume it is for 3 years like I did!!!
If you're using C# you probably want the ReadCommitted IsolationLevel and not Snapshot - unless you are doing writes in this transaction.
READ COMMITTED SNAPSHOT does optimistic reads and pessimistic writes. In contrast, SNAPSHOT does optimistic reads and optimistic writes. (from here)
bool snapshotEnabled = true;
using (var t = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadCommitted
}))
{
using (var shipDB = new ShipperDBDataContext())
{
}
}
In additional you may get an error about being 'unable to promote' a transaction. Search for 'promotion' in Introducing System.Transactions in the .NET Framework 2.0.
Unless you're doing something special like connecting to an external database (or second database) then something as simple as creating a new DataContext can cause this. I had a cache that 'spun up' its own datacontext at initialization and this was trying to escalate the transaction to a full distributed one.
The solution was simple :
using (var tran = new TransactionScope(TransactionScopeOption.Suppress))
{
using (var shipDB = new ShipperDBDataContext())
{
// initialize cache
}
}
See also Deadlocked article by #CodingHorror
Try this code:
if(charindex('Microsoft SQL Server 2005',##version) > 0)
begin
declare #sql varchar(8000)
select #sql = '
ALTER DATABASE ' + DB_NAME() + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE ;
ALTER DATABASE ' + DB_NAME() + ' SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE ' + DB_NAME() + ' SET MULTI_USER;'
Exec(#sql)
end
I tried the command:
ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON
GO
against a dev box but the it took 10+ minutes and so I killed it.
I then found this:
https://willwarren.com/2015/10/12/sql-server-read-committed-snapshot/
and used his code block (which took about 1:26 to run):
USE master
GO
/**
* Cut off live connections
* This will roll back any open transactions after 30 seconds and
* restricts access to the DB to logins with sysadmin, dbcreator or
* db_owner roles
*/
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK AFTER 30 SECONDS
GO
-- Enable RCSI for MyDB
ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON
GO
-- Allow connections to be established once again
ALTER DATABASE MyDB SET MULTI_USER
GO
-- Check the status afterwards to make sure it worked
SELECT is_read_committed_snapshot_on
FROM sys.databases
WHERE [name] = 'MyDB '
Try use master database before altering current database.
USE Master
GO
ALTER DATABASE [YourDatabase] SET READ_COMMITTED_SNAPSHOT ON
GO
I didn't take a second for me when i changed my DB to single user
All you need to do is this:
ALTER DATABASE xyz SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
No need to put the database into single user mode.
You will rollback uncommitted transactions though.
Try Shut off the other SQL services so that only the SQL server service is running.
Mine ran for 5 minutes then I cancelled it because it was obvious nothing was happening. Its a brand new server so there are no other users connected. I shut off the SQL Reporting Services and then ran it again.. took less than a second to complete.
With "ROLLBACK IMMEDIATE" it took about 20-30 seconds on my db which is 300GB.
ALTER DATABASE DBNAME SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE

Resources