Powershell to Alter Database File Properties
So this time we've got like 85 DB files for our main DB. I know that's a lot but it's been spread across so many LUNs for so long and it's just grown and grown as it's filled up the LUNs. Now we finally got a couple really large LUNs and we're trying to consolidate the files. And now that we've moved most of them to a single LUN, we want to stop the autogrowth on most of them so they don't grow anymore before we empty them and then drop them. Because what's the point really in putting them all on a single LUN if you're not going to get rid of some of them. So we definitely don't want them to grow anymore before we can empty them.
The task at hand was to set all of these files (most of them really) to not autogrow. The choices were do it in the GUI, or write a T-SQL cursor to go through all the files and create an alter database command in dynamic SQL for each one. Neither of those is very attractive considering that there are so many files. Of the 2 of them though, the cursor is the more attractive solution. Then I thought of powershell. I hadn't specifically done anything like this in powershell before, but I figured I'd be able to get some love. I'm not going to teach you powershell here, or explain the script too much. I'm just gonna give you the code and if you have any questions you're free to write, but it's pretty straightforward. I'll be making a video on this tonight for those of you who like to see things in action.
PS SQLSERVER:\SQL\MYSQLBox\DEFAULT\Databases\MyDB\filegroups\data\files> gci | where{$_.Name -ne "MyDB_Data"} | %{$_.set_GrowthType("None"); Alter();}
OK, so a quick glance at the important parts.
1. Make sure you're in the right node. Notice I'm in data\files.
2. Here I'm filtering out the one file I don't want to be effected. So the main data file I want to still be able to grow. I'll talk about that more in a min.
3. Don't forget to use the Alter() at the end. Usually whenever an object has an alter method it wants you to use it. If you don't it'll change it in cache in your powershell session but you won't see the change persisted to the DB. So you're not really making the change to the object in SQL, just in your powershell pipeline. You can tell if something has an alter method by doing this at the cmdline 'gci | gm'. If there's an alter method there, then use it.
OK, you don't have to filter. If you find it too much trouble or if your files are named in such a way that it would be too hard to snipe a single file for some reason, then you can change them all and then just go back to the GUI to change the last one back to what it was.
So there you go. We have a nice 1-line script to alter as many files as you need. And you can clearly tack as many file changes on there as you need. And the best part about it is that the code doesn't really change if you need to do another file operation. All you do is change the method call. Ahhh, the power of powershell.
The xp_CMDShell Curse
I interviewed a couple guys for a DBA position the other day and I asked one of my usual questions which is simply to discuss xp_cmdshell and its implications. Without hesitation, I got the same answer twice. Both guys gasped and talked about the evils of xp_cmdshell. So I let them go on and then presented them with a couple scenarios that we discussed. And again, all of this just makes me think about true evil and how xp_cmdshell just doesn’t fit. See, this xp was developed for a reason; It filled in the gap on some missing functionality, and it does it very well. In fact, it does it so well, and the gap is so big, that xp_cmdshell gained in popularity and became an instant success. And in fact, it was used too much and this is where it got its bad reputation. Don’t hold that against xp_cmdshell though. Just because everyone recognizes its usefulness doesn’t mean that it’s bad. The problem started because everyone wanted to use it and the security was opened wide allowing damage to be done.
But it’s not evil; it’s just misused. If you keep it locked down there’s no reason why you can’t have a fairly nice relationship with xp_cmdshell. The same goes for cursors. Cursors have also fallen prey to the cmdshell curse. And again, it’s through misuse. So don’t kick either of these out of your shop because so many other devs are stupid. Use them both wisely and they’ll do good things for you.
People Leave Jobs
One thing I see from time to time is when someone leaves a gig they’ve been at for a long time, their workmates get upset. It’s like they’re personally offended that the guy is choosing to work somewhere else. Look, I know it’s easy to build relationships with people you work with and it’s easy to bond with people you spend so much time with. Hell, you might even say that you’ve been in battle together. What you have to realize though is that people have to do what’s good for them. I can almost promise you that the guy’s not leaving to spite you. He’s probably just tired of one thing or another. Maybe he’s not getting paid what he thinks he should. Maybe the new job is just closer to home. Maybe the new job allows more training or flexibility. Whatever the reason, it’s almost certain it’s not to piss you off.
I know what it’s like because I went through that many years ago. I got a couple guys I worked with that I got along with great and we all worked very well together. Coming to work wasn’t a chore at all. Then the first cool dude left. I was crushed. How could he do that to me? After all we’ve meant to each other!! Then the next one left, and then the next. Finally I was all alone. I want along this way until I went to my next job and found a couple guys I really liked (you know what I’m talking about, huh). Then I left that gig because I got something better and I labored over whether to leave those guys or not. Finally I decided that taking care of my family was more important. Then I got it. Those other guys weren’t leaving ME, they were just moving on to a better gig.
So really guys, if someone you work with leaves for another gig, wish him well. He’s only doing what’s best for him. And if you really are a friend, that’s how you’ll look at it.
SSIS Email Chain
Q:
Hey, would you agree that a monthly load process is better served as an SSIS – even if you have to push/pull from text files for now – than as a series of SPs or DLLs?
A:
if you're staying on the same box for the load then SPs can be an attractive offer because they're very fast and the memory stays in sql and can be managed quite well... if you move that process to ssis, and ssis is on the same box, then you have to allocate memory away from sql to run the pkg and house the data while in the buffer...
if ssis is on another box, but the data is still being moved to different dbs on the same box... so if the data is being moved from server1.db1 to server1.db2 and ssis is on server2, then you don't have to fight sql for memory, but now you incur the network cost of moving the data from the box, and then back to it...
if you're moving between boxes, then y, ssis is a better choice because in SPs you have to manage linked servers or openrowset to make that happen and that's not cricket...
however, what makes ssis attractive in the single box scenario is that it handles errors easier and alerting is much richer and easier to come by... you can also more easily fix problems in the data itself and it's easier to extend... so if your requirements change and you need to switch it to another box, or if you need to send a copy somewhere else, etc then that's much easier in ssis... ssis also gives you parallelism that you cant do in sps... you can load several tables at once in ssis where they have to be serialized in sps...
a good compromise in the single box scenario is to keep things moving like they are if possible, and where not stupid... so if they've already got an sp that inserts data into the 2nd db, then just call that sp from ssis... this way you get the insert and select process in sql where it belongs, and the workflow and error handling of ssis, and everything else that goes with it... if a single sp inserts several tables serially though, i'd create several sps and call them individually in ssis tasks... even if you have to keep them seialized (like for PK/FK issues)... because now you can even add things like checkpoints and individual error flows to your pkg steps and have a richer experience...
these things are meant to allow your process to grow and change much easier than is possible with an sp... so if one of the DBs gets too big and has to move to another box, it's a simple matter in ssis... but in an sp, that means you have to create and manage a linked server, which is just one more thing and they come with their own problems...
as for the DLLs... these processes NEVER belong in a DLL... not only do you have to steal memory from sql, but it's not optimized for data flow tasks... it's just a plain DB connection... you can have parallelism though by calling the windows threading model, but they have to manage those threads manually and mistakes can be made... and that takes extra memory, etc... not only that, but the code isn't available for admins to fix problems, and making changes to the compiled code can be dangerous, right... so no, that's not a good idea...
does this answer... i realize you prob wanted more of a yes, do this, but it's not that simple...
Deleting Production Data
While talking to a group of devs late last week the topic of deleting prod data came up. Since I’m the big MVP of the group they wanted to know what the official word from on-high is. The question is simple, and the answer is even simpler and frankly it’s one of those that was solved so long ago it just doesn’t hold any interest for me anymore. I’ll hash it out here again though because I know there are plenty of you out there who haven’t solved this problem yet.
The question is, what’s the best way to delete gazillions of rows out of a prod table. The issue is with both concurrency and rollback. The problem is that if you do a huge delete in a single transaction you don’t leave any room for anyone else to access the table during that time. So your delete can bring a DB to a complete halt if you don’t do it right. As well, you put your system at risk should something go wrong and the transaction has to rollback. So why would the transaction have to rollback? Well, there are a couple reasons really. The first, and most likely, is that it could fill up the log and with no more log the transaction can’t continue. The other possibility is that the server or the service gets restarted because someone didn’t know you were doing a big operation. And while I’m at it, there is one more logical possibility. Someone could get impatient with the operation and stop it without realizing that it has to rollback. This is actually a scenario that I’ve seen played out many times and the result is always the same. The system has to wait for at least as long as it was going. And what’s even better is when the DB doesn’t come back online right away, that same user will bounce the service again and again.
And of course this counts for updates as well… in SQL2K this was accomplished like this:
SET RowCount 1000
While (1=1)
Begin
Begin Transaction
--Delete stmt here--
if @@RowCount = 0
Begin
Commit Transaction
Break
End
Commit Transaction
End
However, this doesn’t work in SQL2K5 and above where you have to do something more like this:
set nocount on
while 1=1
begin
delete top(1000)
from table1
where conditions…
if @@rowcount = 0
end
So ok, that’s how you batch delete/update in prod. Only under very controlled and specific circumstances should you ever do these types of ops in a single batch.
About Me
- Sean McCown
- I am a Contributing Editor for InfoWorld Magazine, and a frequent contributor to SQLServerCentral.com as well as SSWUG.org. I live with my wife and 3 kids, and have practiced and taught Kenpo for 22yrs now.