Shrink the Unshrinkable SQL Transaction Log

Various reasons may cause SQL Server to get in a rut and not empty the transaction log of a database. In my case, our database backups were failing without our knowledge for several weeks, so the backups were never successful, and the transaction logs of a few databases grew so large that the backup process would still not clear out the transaction log. In one case, we had a 187MB database with a 37GB transaction log!

The insanity had to stop! A handful of databases like this would put us over the top on that particular server's hard drive storage.

The SQL Server GUI for shrinking the database rendered no effect, and even using the DBCC SHRINKFILE command was not working.

The key, as explained by Pinal Dave, is to run the SHRINKFILE command twice, with an explicit backup log truncation in between both runs. This code here will get you up and running:

DBCC SHRINKFILE("MyDatabase_Log", 1)
BACKUP LOG MyDatabase WITH TRUNCATE_ONLY
DBCC SHRINKFILE("MyDatabase_Log", 1)

This freed up dozens of gigabytes on our server.

Combining Repositories Into One Large Repository

I keep all my projects in separate Subversion repositories. I did this because it feels a lot cleaner this way, there is less risk in the event of repository corruption, and I use corresponding Trac projects that I also wanted to keep separate from one project to the next.

That said, there are advantages to having one single repository. No big deal, that can be done after the fact with code.

Here is some Windows code to combine all the repositories in a directory into a single big repository:

set svndir=c:\Test\svn
set bigrepo=c:\Test\BigRepo
set bigrepoUNC=file:///c:/Test/BigRepo
set rev=0:HEAD

echo Setting up the big repository.
rmdir /S /Q %bigrepo%
mkdir %bigrepo%
svnadmin create %bigrepo%

cd %svndir%
dir /A:D /B> dirs.tmp
for /F %%i in (dirs.tmp) do (
echo Adding %svnDir%\%%i to the big repository:
svnadmin dump -r %rev% %%i >  %%i.dmp
svn mkdir -m "Making project directory %%i." --non-interactive %bigrepoUNC%/%%i
svnadmin load %bigrepo% --parent-dir %%i  < %%i.dmp
del /F /Q %%i.dmp
)
del dirs.tmp

There's really not much happening here; the process is simple. First, we create the new "big" repository with the svnadmin create statement. Second, we loop through the directory, processing each Subversion repository in the directory with a three-step process: (a) Dump the repository with the svnadmin dump statement into a temporary *.dmp file. (b) Explicitly add a new directory in the "big" repository for the current repository we're processing, with the svn mkdir statement. (c) Import the dump into the "big" repository with the svnadmin load statement. Really, the rest of the code is just looping, commenting, or cleanup code.

What have we produced? As you might expect, we now have one big repository that has all of the files and commits that were in all of the smaller repositories. The big repository will maintain its own revision numbering, so the revision numbers in your smaller repositories will not match the big repository's revision numbering, although the original commit dates will be preserved. This can be really handy for searching or similar actions that you might do from a more global perspective.

However, this approach is not without its caveats. During the import process, one entire repository is imported at a time. All of a particular repository's revisions will be "grouped" together in the big repository. As a result, revision numbers in the big repository will change every time you recreate it, if there was any new activity in the repositories it contains. For instance, revision #1050 in the big repository may parallel revision #500 in Repository X, but if a commit was added to a repository that is imported before it and the big repository is recreated, that revision would now be #1051. Additionally, although all history and dates are preserved in the revisions, the big repository has commits that are not in chronological order since the import was processed by repository. This inconsistent date/commit ordering can be confusing to some repository reporting tools and may actually render those tools useless to you when they are reporting by date.

Filtering by revision. Note that my svnadmin dump statement includes the -r argument, which specifies the beginning and ending revisions to dump. By default, I'm using "0:HEAD", which basically means "dump every revision", or "dump from the first revision to the HEAD, or latest, revision". Changing the beginning and ending revisions can be useful, especially when used with dates instead of actual revision numbers. For instance, you could change the value to {2007-01-01}:{2007-12-31} to only dump revisions that were committed in 2007.

Combining all of your smaller repositories into one big repository after the fact isn't a perfect solution, but it can be handy, and it's really easy to do when you have a script like this ready to run.

Trimming a String in JavaScript

This is a nice clean way to implement string trimming for the String object in JavaScript:

String.prototype.trim = function()
{
   return this.replace(/^\s+|\s+$/g,"");
}

With that implemented, you can then trim a string in the object-oriented way you would prefer and love:

var myStr="This is a test!   ";
alert(myStr.trim());

This is handy for client-side clean-up of form information, although bear in mind that depending on client-side code for data entry clean-up isn't necessarily wise unless you have some server-side code also checking the data.

How to Fix 301 Error for Subversion Checkouts

My Linux box was hosting Subversion with no problem. I added a new repository to the several that were already present, and when I checked it out, it said, "301 Moved Permanently". Excuse me?

As it turns out, there is a 301 error section in the Subversion FAQs. It says that this typically means your Apache configuration is invalid (nope, the rest of my repositories worked just fine) or your repository has the same path as a literal directory on your web root. Ahhh!

Sure enough, my subversion path was http://myserver.com/xyz/, and I had a literal directory named "xyz" in the web root. I changed that directory name, and Subversion would then allow me to checkout the repository with no problem.

  Theme Brought to you by Directory Journal and Elegant Directory.