Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Размеры дисков сервера  [new]
AndrF
Member

Откуда:
Сообщений: 2194
xp_fixeddrives не возвращает размеры дисков сервера, а иногда их все же требуется знать, причем включать поддержку скриптов/clr нельзя.

В итоге сегодня набросал процедуру приведенную ниже. Она вернет размеры всех дисков, на которых есть базы данных. Если на диске нет баз, но есть папка DATA или LOGS, то процедура создаст в них пустую базу данных, чтобы место все же определялось...

В общем, желающие могут пробовать.

CREATE PROCEDURE GetDisks(@Drv char(1) = NULL)
AS
BEGIN
	SET NOCOUNT ON

	DECLARE @f tinyint = 0, @db sysname, @DefaultLogFolder sysname
	DECLARE @Sql nvarchar(MAX)
	
	DECLARE @Disks TABLE (Drv char(1), Total_MB int, Free_MB int, [Data] bit DEFAULT 0, Logs bit DEFAULT 0)
	DECLARE @Folders TABLE (Folder sysname)

	EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultLog', @DefaultLogFolder OUTPUT
	INSERT INTO @Disks (Drv, Free_MB) EXEC master..xp_fixeddrives
	IF NOT @Drv IS NULL
		DELETE FROM @Disks WHERE Drv <> @Drv

	UPDATE @Disks
		SET Total_MB = t.total_bytes / 1048576
		FROM @Disks d
			INNER JOIN(SELECT DISTINCT UPPER(LEFT(volume_mount_point,1)) AS Drv, total_bytes
						FROM sys.master_files f
							CROSS APPLY sys.dm_os_volume_stats(f.database_id, f.file_id)) t ON d.Drv = t.Drv

	DECLARE cur CURSOR FOR SELECT Drv FROM @Disks
	OPEN cur
	FETCH NEXT FROM cur INTO @Drv
	WHILE @@FETCH_STATUS = 0
	BEGIN
		SET @f = 0
		DELETE FROM @Folders

		INSERT INTO @Folders EXEC('EXEC master..xp_subdirs ''' + @Drv + ':\''')

		IF EXISTS(SELECT * FROM @Folders WHERE Folder='DATA')
			BEGIN
				SET @f = 1
				UPDATE @Disks SET [Data] = 1 WHERE Drv = @Drv
			END

		IF EXISTS(SELECT * FROM @Folders WHERE Folder='LOGS')
			BEGIN
				IF @f = 0 SET @f = 2
				UPDATE @Disks SET [Logs] = 1 WHERE Drv = @Drv
			END
		
		IF @f > 0 AND EXISTS(SELECT * FROM @Disks WHERE Drv = @Drv AND Total_MB IS NULL)
			BEGIN
				SET @db = 'z_disk_' + @Drv
				EXEC ('DROP DATABASE IF EXISTS ' + @db)

				SET @Sql ='
CREATE DATABASE ' + @db + '
	ON ( NAME = ' + @db + '_dat, FILENAME = ''' + @Drv + ':\' + CASE WHEN @f = 1 THEN 'DATA' ELSE 'LOGS' END + '\' + @db + '_dat.mdf'' )
	LOG ON ( NAME = ' + @db + '_log, FILENAME = ''' + @DefaultLogFolder + '\' + @db + '_log.ldf'' )'
				EXEC ( @Sql)

				UPDATE @Disks
					SET Total_MB = total_bytes / 1048576
					FROM @Disks d
						INNER JOIN  (SELECT UPPER(LEFT(volume_mount_point,1)) AS Drv, total_bytes
										FROM sys.database_files f
										CROSS APPLY sys.dm_os_volume_stats(DB_ID( @db ), f.file_id)) t ON d.Drv=t.Drv 
			END
		FETCH NEXT FROM cur INTO @Drv
	END
	CLOSE cur
	DEALLOCATE cur
	DELETE FROM @Disks WHERE [Data]=0 AND Logs=0 AND Drv <> 'C'
	SET NOCOUNT OFF

	SELECT * FROM @Disks
END
6 июн 19, 15:09    [21903623]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
komrad
Member

Откуда:
Сообщений: 5245
AndrF,

как обрабатывается случай отсутствия у учетки прав на диск, на котором создается временная бд?
6 июн 19, 15:17    [21903636]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
Критик
Member

Откуда: Москва / Калуга
Сообщений: 33700
Блог
AndrF,

зачем?
администратор же есть, у которого имеются права,
и диски - это его проблема
6 июн 19, 15:26    [21903657]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
AndrF
Member

Откуда:
Сообщений: 2194
komrad
как обрабатывается случай отсутствия у учетки прав на диск, на котором создается временная бд?


Пока - никак.
6 июн 19, 15:34    [21903667]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
L_argo
Member

Откуда:
Сообщений: 1217
Какая минимальная версия сервера должна быть ?
6 июн 19, 15:43    [21903678]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
komrad
Member

Откуда:
Сообщений: 5245
AndrF
komrad
как обрабатывается случай отсутствия у учетки прав на диск, на котором создается временная бд?


Пока - никак.

похоже что последняя временная база и не удаляется, так?
6 июн 19, 15:52    [21903689]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
AndrF
Member

Откуда:
Сообщений: 2194
komrad
AndrF
пропущено...
Пока - никак.

похоже что последняя временная база и не удаляется, так?


Собственно это не совсем временная. Для того чтобы dm_os_volume_stats возвращала данные о диске необходимо чтобы на нем была какая-то база или ее лог. Так что пустую базку можно оставить постоянно - ее нет смысла удалять, тогда в следующий раз и создавать не придется. А лучше дописать удаление в случае если на этом диске появились другие базы...

На счет прав - еще буду думать - надо чтобы все работало для группы не имеющей прав sysadmin-a. В общем, пока все в процессе - для того и кинул сюда чтобы не упустить чего - добрые люди подскажут. Догонят и еще раз подскажут... ;)
6 июн 19, 16:07    [21903706]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
столько ещё вариантов заставить что-то делать неестественное sql серевер...
6 июн 19, 16:13    [21903716]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
komrad
Member

Откуда:
Сообщений: 5245
AndrF
На счет прав - еще буду думать - надо чтобы все работало для группы не имеющей прав sysadmin-a.

try catch ?

AndrF
В общем, пока все в процессе - для того и кинул сюда чтобы не упустить чего - добрые люди подскажут. Догонят и еще раз подскажут... ;)

по-товарищески, поскольку не всё равно
было бы всё равно - никто бы и не взлянул ;)
6 июн 19, 16:46    [21903745]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
komrad
Member

Откуда:
Сообщений: 5245
AndrF
все работало для группы не имеющей прав sysadmin-a.

http://www.sommarskog.se/grantperm.html часть 5
6 июн 19, 17:04    [21903770]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7780
Узнать, сколько осталось места:

exec xp_cmdshell 'dir c:\'


А другое DBA и не требуется.
6 июн 19, 17:08    [21903779]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31371
AndrF
Она вернет размеры всех дисков, на которых есть базы данных. Если на диске нет баз, но есть папка DATA или LOGS, то процедура создаст в них пустую базу данных, чтобы место все же определялось...
Идея мониторить параметры дисков, на которых расположены базы, понятна, собственно, для этого МС сделал sys.dm_os_volume_stats.
Для дополнительного контроля DBA того, что в принципе должно контролироваться железными админами - но двойной контроль критических параметров полезен.

Но зачем создавать временные базы и мониторить диски, на которых баз не было?

Соглашусь с предыдущими ораторами, ненужный функционал для DBA.
6 июн 19, 17:38    [21903837]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
AndrF,

Ну то есть mount points вы не используете? Оно вам ерунду выдаст да еще и не по всем дискам.
Wmi/PowerShell надо использовать для такого если очень хочется. А идея с созданием пустых баз конечно забавная.
7 июн 19, 02:46    [21904135]     Ответить | Цитировать Сообщить модератору
 Re: Размеры дисков сервера  [new]
AndrF
Member

Откуда:
Сообщений: 2194
alexeyvg
Но зачем создавать временные базы и мониторить диски, на которых баз не было?


Потому что они там могут быть созданы. А для этого нужно знать сколько там места, ну и сколько останется после... В том числе и в %.

alexeyvg
Соглашусь с предыдущими ораторами, ненужный функционал для DBA.


Тут все же каждый решает сам, со своей колокольни. По мне - так очень удобно. Кроме того - вам же неизвестна конкретная задача, для которой оно требуется...

В, общем, все же пришел к тому чем вначале не хотел заниматься, а именно к CLR - на нем все оказалось до смешного просто:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void GetDataDisks(bool bAllDisks = true)
    {
        DriveInfo[] allDrives = System.IO.DriveInfo.GetDrives();

        SqlDataRecord record = new SqlDataRecord(
            new SqlMetaData("Drive", SqlDbType.NVarChar, 25),
            new SqlMetaData("VolumeLabel", SqlDbType.NVarChar, 50),
            new SqlMetaData("Size (MB)", SqlDbType.Float),
            new SqlMetaData("FreeSpace (MB)", SqlDbType.Float),
            new SqlMetaData("Percent Free Space", SqlDbType.Float),
            new SqlMetaData("Data", SqlDbType.Bit),
            new SqlMetaData("Logs", SqlDbType.Bit));

        SqlContext.Pipe.SendResultsStart(record);

        foreach (DriveInfo d in allDrives)
        {
            if (d.DriveType == DriveType.Fixed && d.IsReady == true)
            {
                bool bDataDisk = Directory.Exists(d.Name + "Data");
                bool bLogsDisk = Directory.Exists(d.Name + "Logs");

                if (bAllDisks == true || bDataDisk == true || bLogsDisk == true)
                {
                    record.SetValue(0, d.Name);
                    record.SetValue(1, d.VolumeLabel);
                    record.SetValue(2, (double)d.TotalSize / 1048576);
                    record.SetValue(3, (double)d.TotalFreeSpace / 1048576);
                    record.SetValue(4, (double)(d.TotalFreeSpace * 100) / d.TotalSize);
                    record.SetValue(5, bDataDisk);
                    record.SetValue(6, bLogsDisk);

                    SqlContext.Pipe.SendResultsRow(record);
                }
            }
        }

        SqlContext.Pipe.SendResultsEnd();
    }
}
8 июн 19, 17:29    [21905192]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить