So we've got a bunch of apps running on our SQL servers, and today we realised that a number of them had a bunch of Partition Schemes/Functions that we didn't create.
The partition schemes and functions were called ifts_comp_fragment_data_space_{hash} and ifts_comp_fragment_partition_function_{hash} respectively.
Digging deeper, we realised that they are marked as system entries (is_system set to 1 in sys.partition_schemes) which means we can't even delete them.
After some research we found out that SQL server will create them to partition the fulltext catalogs if they become too large, or something like that see here. The problem is - we just deleted all the catalogs, and these were left abandoned, with NO way of clearing them out.
I wouldn't worry too much, except I NEED to delete them, since I'm trying to export our DB as a .bacpac file, and that crashes complaining that the DB contains partition schemes/functions and they're not supported.
Is there ANY way of forcing the SQL server to drop those objects, or any other alternative that I could do?
You can change that is_system flag from 1 to 0 and then drop the partition scheme like any other. To do this:
First allow updates on your server:
exec sp_configure 'allow updates', 1
go
reconfigure with override
go
Shutdown your SQL server
Start it back up in Single User mode by running "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn\sqlservr.exe -m" from a console with elevated privs.
Login to the server using the SQL Server DAC http://technet.microsoft.com/en-us/library/ms178068(v=sql.105).aspx
If we do an SP_HELPTEXT on the sys.partition_schemes view, you'll see that the is_system column is based on a status flag in the sys.sysclsobjs table. "sysconv(bit, o.status & 0x4) AS is_system,"
So to change the flag, we have to look at what the current value of the status is and unmark the 4 bit. My value was 4 so I updated it to 0.
update sys.sysclsobjs set status = 0 where name =
'ifts_comp_fragment_data_space_033D368C'
Now you can shutdown the single user mode SQL Server process by just closing your console window and start your sql server windows service. Then just login as you normally would and drop the partition scheme.
Finally, set your 'allow updates' setting back to 0.
This might need to be planned downtime for a production server.
DISCLAIMER This probably isn't a Microsoft supported way of doing this, you may want to test on some non-prod servers before diving in.
Related
We have an ERP application that uses a SQL server database. Although the application is not in use currently, its log file increases constantly and is currently at 28GB. I took a full backup couple of weeks back to truncate the log file when it was 85GB and now it is back to 28GB. I've setup the log file size to be 20GB with 100MB increment and unrestricted growth.
Why the log file size is increasing when the application is not in use, how can I see the transactions that are causing it to increase and how can I manage it better? Does setting up a server trace is useful in this case?
Check the output of sys.dm_exec_requests and sys.dm_exec_sessions to find out what queries are running and what/who's connected to your database.
If that doesn't help you, then you could certainly set up a server trace or an extended events session - if you really think no one is connecting and querying, you could verify that using something like this:
IF EXISTS (SELECT * FROM sys.server_event_sessions WHERE name = 'EE_Queries')
DROP EVENT SESSION EE_Queries ON SERVER;
GO
CREATE EVENT SESSION EE_Queries ON SERVER
ADD EVENT sqlserver.sql_statement_completed
(ACTION (sqlserver.sql_text,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.nt_username, sqlserver.username)
WHERE sqlserver.database_id = /* fill in your DB_ID() here */)
ADD TARGET package0.asynchronous_file_target
(SET FILENAME = N'C:\logs\EE_Queries.xel', METADATAFILE = N'C:\logs\EE_Queries.xem')
WITH (max_dispatch_latency = 1 seconds);
GO
ALTER EVENT SESSION EE_Queries ON SERVER STATE = START;
which would log all queries going on against your database - just replace the comment portion with the DB_ID() of the database you want to track. That will start an extended events session that tracks all queries, including the text of the query, the app name, the host name, and the username (NT and/or SQL user name) of the user that's running the query. That should clue you in pretty quickly. Just be careful with that events session in a production environment on a busy database - it will likely degrade performance and may fill up the disk quickly if you have lots of queries. Output of that extended event locally:
I'm having a very strange problem with a fresh install I have of SQL Server 2008 Express edition (yeah it's a bit old now, but whatever). When I connect via SQL Server Management Studio, I can both read and edit data (update or insert), but when I connect via my web application's data access layer, which uses SqlConnection and SqlCommand to try and update and insert data in tables, no changes occur in the database. The strange thing is that the code runs as if no error had occurred though; no exceptions are thrown, and my update statement causes SqlCommand.ExecuteNonQuery to return 1, indicating that supposedly 1 row has been updated. However, it hasn't. The application can, however, read data from the database via select statements.
Does anyone have any idea what's going on here? I even tried tracing SQL Server using ExpressProfiler, and its output seemed to indicate that the update should have occurred:
exec sp_executesql N'UPDATE Match SET TicketsSold=#ticketsSold WHERE MatchId=#matchId',N'#matchId int,#ticketsSold int',#matchId=1,#ticketsSold=1234
go
Yet TicketsSold stays at the same value (123) it was at before, and does not update to 1234. Is there some kind of "silent" read-only mode SQL Server 2008 Express could be running in? I'm baffled as to why the database isn't being updated.
By the way, this is a proper SQL Server database I created in SSMS, not some attached MDF file that resides in the same directory as my web application. The database is not set to "read-only" in database options, and I'm pretty sure that the user that the web application is logging in as has read/write permission on the MDF file; it is logging in as the same user I am logging in as using SSMS - with integrated Windows security - and I am able to update/insert as that user via SSMS.
Thanks to shf301 in the comments - I was creating a transaction but forgetting to call .Commit before the end of the using block. :-D I put that in and now it works.
I have a SQL Server 2005 database that has been deleted, and I need to discover who deleted it. Is there a way of obtaining this user name?
Thanks, MagicAndi.
If there has been little or no activity since the deletion, then the out-of-the-box trace may be of help. Try running:
DECLARE #path varchar(256)
SELECT #path = path
FROM sys.traces
where id = 1
SELECT *
FROM fn_trace_gettable(#path, 1)
[In addition to the out-of-the-box trace, there is also the less well-known 'black box' trace, which is useful for diagnosing intermittent server crashes. This post, SQL Server’s Built-in Traces, shows you how to configure it.]
I would first ask everyone who has admin access to the Sql Server if they deleted it.
The best way to retrieve the information is to restore the latest backup.
Now to discuss how to avoid such problems in the future.
First make sure your backup process is running correctly and frequently. Make transaction log baclup evey 15 mintues or half an hour if it is a higly transactional database. Then the most you lose is a half an hour's worht of work. Practice restoring the database until you can easily do it under stress.
In SQL Server 2008 you can add DDL triggers (not sure if you can do this in 2005) which allow you to log who did changes to structure. It might be worth your time to look into this.
Do NOT allow more than two people admin access to your production database - a dba and a backup person for when the dba is out. These people should load all changes to the database structure and code and all of the changes should be scripted out, code reviewed and tested first on QA. No unscripted, "run by the seat of your pants" code should ever be run on prod.
Here is bit more precise TSQL
SELECT DatabaseID,NTUserName,HostName,LoginName,StartTime
FROM
sys.fn_trace_gettable(CONVERT(VARCHAR(150),
( SELECT TOP 1
f.[value]
FROM sys.fn_trace_getinfo(NULL) f
WHERE f.property = 2
)), DEFAULT) T
JOIN sys.trace_events TE ON T.EventClass = TE.trace_event_id
WHERE TE.trace_event_id =47 AND T.DatabaseName = 'delete'
-- 47 Represents event for deleting objects.
This can be used in the both events of knowing or not knowing the database/object name. Results look like this:
I'm trying to perform some offline maintenance (dev database restore from live backup) on my dev database, but the 'Take Offline' command via SQL Server Management Studio is performing extremely slowly - on the order of 30 minutes plus now. I am just about at my wits end and I can't seem to find any references online as to what might be causing the speed problem, or how to fix it.
Some sites have suggested that open connections to the database cause this slowdown, but the only application that uses this database is my dev machine's IIS instance, and the service is stopped - there are no more open connections.
What could be causing this slowdown, and what can I do to speed it up?
After some additional searching (new search terms inspired by gbn's answer and u07ch's comment on KMike's answer) I found this, which completed successfully in 2 seconds:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
(Update)
When this still fails with the following error, you can fix it as inspired by this blog post:
ALTER DATABASE failed because a lock could not be placed on database 'dbname' Try again later.
you can run the following command to find out who is keeping a lock on your database:
EXEC sp_who2
And use whatever SPID you find in the following command:
KILL <SPID>
Then run the ALTER DATABASE command again. It should now work.
There is most likely a connection to the DB from somewhere (a rare example: asynchronous statistic update)
To find connections, use sys.sysprocesses
USE master
SELECT * FROM sys.sysprocesses WHERE dbid = DB_ID('MyDB')
To force disconnections, use ROLLBACK IMMEDIATE
USE master
ALTER DATABASE MyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Do you have any open SQL Server Management Studio windows that are connected to this DB?
Put it in single user mode, and then try again.
In my case, after waiting so much for it to finish I had no patience and simply closed management studio. Before exiting, it showed the success message, db is offline. The files were available to rename.
execute the stored procedure
sp_who2
This will allow you to see if there is any blocking locks.. kill their should fix it.
In SSMS: right-click on SQL server icon, Activity Monitor. Open Processes. Find the processed connected. Right-click on the process, Kill.
In my case I had looked at some tables in the DB prior to executing this action. My user account was holding an active connection to this DB in SSMS. Once I disconnected from the server in SSMS (leaving the 'Take database offline' dialog box open) the operation succeeded.
anytime you run into this type of thing you should always think of your transaction log. The alter db statment with rollback immediate indicates this to be the case. Check this out: http://msdn.microsoft.com/en-us/library/ms189085.aspx
Bone up on checkpoints, etc. You need to decide if the transactions in your log are worth saving or not and then pick the mode to run your db in accordingly. There's really no reason for you to have to wait but also no reason for you to lose data either - you can have both.
Closing the instance of SSMS (SQL Service Manager) from which the request was made solved the problem for me.....
To get around this I stopped the website that was connected to the db in IIS and immediately the 'frozen' 'take db offline' panel became unfrozen.
Also, close any query windows you may have open that are connected to the database in question ;)
I tried all the suggestions below and nothing worked.
EXEC sp_who
Kill < SPID >
ALTER DATABASE SET SINGLE_USER WITH Rollback Immediate
ALTER DATABASE SET OFFLINE WITH ROLLBACK IMMEDIATE
Result: Both the above commands were also stuck.
4 . Right-click the database -> Properties -> Options
Set Database Read-Only to True
Click 'Yes' at the dialog warning SQL Server will close all connections to the database.
Result: The window was stuck on executing.
As a last resort, I restarted the SQL server service from configuration manager and then ran ALTER DATABASE SET OFFLINE WITH ROLLBACK IMMEDIATE. It worked like a charm
In SSMS, set the database to read-only then back. The connections will be closed, which frees up the locks.
In my case there was a website that had open connections to the database. This method was easy enough:
Right-click the database -> Properties -> Options
Set Database Read-Only to True
Click 'Yes' at the dialog warning SQL Server will close all connections to the database.
Re-open Options and turn read-only back off
Now try renaming the database or taking it offline.
For me, I just had to go into the Job Activity Monitor and stop two things that were processing. Then it went offline immediately. In my case though I knew what those 2 processes were and that it was ok to stop them.
In my case, the database was related to an old Sharepoint install. Stopping and disabling related services in the server manager "unhung" the take offline action, which had been running for 40 minutes, and it completed immediately.
You may wish to check if any services are currently utilizing the database.
Next time, from the Take Offline dialog, remember to check the 'Drop All Active Connections' checkbox. I was also on SQL_EXPRESS on local machine with no connections, but this slowdown happened for me unless I checked that checkbox.
SSMS, especially if running it from your own desktop remotely and not directly within the database server, can be a reason for the long delays in detaching a database. For some reason SSMS may not be able to disconnect any existing "connections" to the database.
We found the process was almost instant when we did it directly from the database server itself. And in fact it killed the attempt from my own desktop SSMS session, and it "took over" and detached the database.
Nothing else suggested here worked.
Thanks
In my case i stopped Tomcat server . then immediately the DB went offline .
Is it possible to set up somehow Microsoft SQL Server to run a stored procedure on regular basis?
Yes, in MS SQL Server, you can create scheduled jobs. In SQL Management Studio, navigate to the server, then expand the SQL Server Agent item, and finally the Jobs folder to view, edit, add scheduled jobs.
If MS SQL Server Express Edition is being used then SQL Server Agent is not available. I found the following worked for all editions:
USE Master
GO
IF EXISTS( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[MyBackgroundTask]')
AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[MyBackgroundTask]
GO
CREATE PROCEDURE MyBackgroundTask
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- The interval between cleanup attempts
declare #timeToRun nvarchar(50)
set #timeToRun = '03:33:33'
while 1 = 1
begin
waitfor time #timeToRun
begin
execute [MyDatabaseName].[dbo].[MyDatabaseStoredProcedure];
end
end
END
GO
-- Run the procedure when the master database starts.
sp_procoption #ProcName = 'MyBackgroundTask',
#OptionName = 'startup',
#OptionValue = 'on'
GO
Some notes:
It is worth writing an audit entry somewhere so that you can see that the query actually ran.
The server needs rebooting once to ensure that the script runs the first time.
A related question is: How to run a stored procedure every day in SQL Server Express Edition?
Yes, if you use the SQL Server Agent.
Open your Enterprise Manager, and go to the Management folder under the SQL Server instance you are interested in. There you will see the SQL Server Agent, and underneath that you will see a Jobs section.
Here you can create a new job and you will see a list of steps you will need to create. When you create a new step, you can specify the step to actually run a stored procedure (type TSQL Script). Choose the database, and then for the command section put in something like:
exec MyStoredProcedure
That's the overview, post back here if you need any further advice.
[I actually thought I might get in first on this one, boy was I wrong :)]
Probably not the answer you are looking for, but I find it more useful to simply use Windows Server Task Scheduler
You can use directly the command sqlcmd.exe -S "." -d YourDataBase -Q "exec SP_YourJob"
Or even create a .bat file. So you can even 2x click on the task on demand.
This has also been approached in this HERE
I'll add one thing: where I'm at we used to have a bunch of batch jobs that ran every night. However, we're moving away from that to using a client application scheduled in windows scheduled tasks that kicks off each job. There are (at least) three reasons for this:
We have some console programs that need to run every night as well. This way all scheduled tasks can be in one place. Of course, this creates a single point of failure, but if the console jobs don't run we're gonna lose a day's work the next day anyway.
The program that kicks off the jobs captures print messages and errors from the server and writes them to a common application log for all our batch processes. It makes logging from withing the sql jobs much simpler.
If we ever need to upgrade the server (and we are hoping to do this soon) we don't need to worry about moving the jobs over. Just re-point the application once.
It's a real short VB.Net app: I can post code if any one is interested.
You could use SQL Server Service Broker to create custom made mechanism.
Idea (simplified):
Write a stored procedure/trigger that begins a conversation (BEGIN DIALOG) as loopback (FROM my_service TO my_service) - get conversation handler
DECLARE #dialog UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION #dialog
FROM SERVICE [name]
TO SERVICE 'name'
...;
Start the conversation timer
DECLARE #time INT;
BEGIN CONVERSATION TIMER (#dialog) TIMEOUT = #time;
After specified number of seconds a message will be sent to a service. It will be enqueued with associated queue.
CREATE QUEUE queue_name WITH STATUS = ON, RETENTION = OFF
, ACTIVATION (STATUS = ON, PROCEDURE_NAME = <procedure_name>
, MAX_QUEUE_READERS = 20, EXECUTE AS N'dbo')
, POISON_MESSAGE_HANDLING (STATUS = ON)
Procedure will execute specific code and reanable timer to fire again.
You can find fully-baked solution(T-SQL) written by Michał Gołoś called Task Scheduler
Key points from blog:
Pros:
Supported on each version (from Express to Enterprise). SQL Server Agent Job is not available for SQL Server Express
Scoped to database level. You could easiliy move database with associated tasks (especially when you have to move around 100 jobs from one enviromnent to another)
Lower privileges needed to see/manipulate tasks(database level)
Proposed distinction:
SQL Server Agent (maintenance):
backups
index/statistics rebuilds
replication
Task Scheduler (business processes):
removing old data
preaggregations/cyclic recalculations
denormalization
How to set it up:
get source code from section: "Do pobrania" - To download
(enabling broker/setting up schema tsks/configuration table + triggers + stored procedure)/setting up broker things)
set up configuration table [tsks].[tsksx_task_scheduler] to add new tasks (columns names are self-descriptive, sample task included)
Warning: Blog is written in Polish but associated source code is in English and it is easy to follow.
Warning 2: Before you use it, please make sure you have tested it on non-production environment.
Using Management Studio - you may create a Job (unter SQL Server Agent)
One Job may include several Steps
from T-SQL scripts up to SSIS Packages
Jeb was faster ;)
You should look at a job scheduled using the SQL Server Agent.