Как найти каталог данных для экземпляра SQL Server?
-
19-09-2019 - |
Вопрос
У нас есть несколько огромный базы данных (20 ГБ+), которые в основном содержат статические данные поиска.Поскольку наше приложение выполняет соединения с таблицами в этих базах данных, они должны быть частью локального SQL-сервера каждого разработчика (т.они не могут размещаться на центральном общем сервере базы данных).
Мы планируем скопировать канонический набор реальных файлов базы данных SQL Server (*.mdf и *.ldf) и прикрепить их к локальной базе данных каждого разработчика.
Как лучше всего узнать каталог данных локального экземпляра SQL Server, чтобы мы могли скопировать файлы в нужное место?Это будет сделано посредством автоматизированного процесса, поэтому я должен иметь возможность найти и использовать его из сценария сборки.
Решение
Это зависит от того, установлен ли путь по умолчанию для файлов данных и журналов или нет.
Если путь указан явно в Properties
=> Database Settings
=> Database default locations
затем SQL-сервер сохраняет его по адресу Software\Microsoft\MSSQLServer\MSSQLServer
в DefaultData
и DefaultLog
ценности.
Однако, если эти параметры не заданы явно, SQL-сервер использует пути к данным и журналам главной базы данных.
Ниже приведен сценарий, охватывающий оба случая.Это упрощенная версия запроса, выполняемого SQL Management Studio.
Также обратите внимание, что я использую xp_instance_regread
вместо xp_regread
, поэтому этот скрипт будет работать для любого экземпляра, по умолчанию или с именем.
declare @DefaultData nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultData', @DefaultData output
declare @DefaultLog nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultLog', @DefaultLog output
declare @DefaultBackup nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @DefaultBackup output
declare @MasterData nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SqlArg0', @MasterData output
select @MasterData=substring(@MasterData, 3, 255)
select @MasterData=substring(@MasterData, 1, len(@MasterData) - charindex('\', reverse(@MasterData)))
declare @MasterLog nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SqlArg2', @MasterLog output
select @MasterLog=substring(@MasterLog, 3, 255)
select @MasterLog=substring(@MasterLog, 1, len(@MasterLog) - charindex('\', reverse(@MasterLog)))
select
isnull(@DefaultData, @MasterData) DefaultData,
isnull(@DefaultLog, @MasterLog) DefaultLog,
isnull(@DefaultBackup, @MasterLog) DefaultBackup
Вы можете добиться того же результата, используя SMO.Ниже приведен пример C#, но вы можете использовать любой другой язык .NET или PowerShell.
using (var connection = new SqlConnection("Data Source=.;Integrated Security=SSPI"))
{
var serverConnection = new ServerConnection(connection);
var server = new Server(serverConnection);
var defaultDataPath = string.IsNullOrEmpty(server.Settings.DefaultFile) ? server.MasterDBPath : server.Settings.DefaultFile;
var defaultLogPath = string.IsNullOrEmpty(server.Settings.DefaultLog) ? server.MasterDBLogPath : server.Settings.DefaultLog;
}
В SQL Server 2012 и более поздних версиях это намного проще, если предположить, что у вас установлены пути по умолчанию (что, вероятно, всегда правильно):
select
InstanceDefaultDataPath = serverproperty('InstanceDefaultDataPath'),
InstanceDefaultLogPath = serverproperty('InstanceDefaultLogPath')
Другие советы
Несмотря на то, что это очень старая тема, я чувствую, что мне нужно предложить простое решение.Каждый раз, когда вы знаете, где в Management Studio находится параметр, к которому вы хотите получить доступ для любого типа автоматизированного сценария, самый простой способ — запустить быструю трассировку профилировщика в автономной тестовой системе и отследить, что Management Studio делает на серверной части. .
В этом случае, если вы заинтересованы в поиске местоположений данных и журналов по умолчанию, вы можете сделать следующее:
ВЫБИРАТЬ
SERVERPROPERTY('instancedefaultdatapath') AS [DefaultFile],
SERVERPROPERTY('instancedefaultlogpath') AS [DefaultLog]
Я наткнулся на это решение в документации по оператору Create Database в справке по SQL Server:
SELECT SUBSTRING(physical_name, 1, CHARINDEX(N'master.mdf', LOWER(physical_name)) - 1)
FROM master.sys.master_files
WHERE database_id = 1 AND file_id = 1
Для текущей базы данных вы можете просто использовать:
select physical_name from
sys.database_files;
чтобы указать другую базу данных, например.«Модель», используйте sys.master_files
select physical_name from sys.master_files where database_id = DB_ID(N'Model');
Начиная с Sql Server 2012, вы можете использовать следующий запрос:
SELECT SERVERPROPERTY('INSTANCEDEFAULTDATAPATH') as [Default_data_path], SERVERPROPERTY('INSTANCEDEFAULTLOGPATH') as [Default_log_path];
(Это было взято из комментария на http://technet.microsoft.com/en-us/library/ms174396.aspx, и протестировано.)
Различные компоненты SQL Server (данные, журналы, SSAS, SSIS и т. д.) имеют каталог по умолчанию.Эту настройку можно найти в реестре.Подробнее читайте здесь:
http://technet.microsoft.com/en-us/library/ms143547%28SQL.90%29.aspx
Итак, если вы создали базу данных, используя только CREATE DATABASE MyDatabaseName
он будет создан по пути, указанному в одной из настроек выше.
Теперь, если администратор/установщик изменил путь по умолчанию, путь по умолчанию для экземпляра сохраняется в реестре по адресу
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\[INSTANCENAME]\Setup
Если вы знаете имя экземпляра, вы можете запросить реестр.Этот пример относится только к SQL 2008 — дайте мне знать, если вам также нужен путь SQL2005.
DECLARE @regvalue varchar(100)
EXEC master.dbo.xp_regread @rootkey='HKEY_LOCAL_MACHINE',
@key='SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLServer\Setup',
@value_name='SQLDataRoot',
@value=@regvalue OUTPUT,
@output = 'no_output'
SELECT @regvalue as DataAndLogFilePath
Каждая база данных может быть создана с переопределением настроек сервера в своем собственном месте при запуске CREATE DATABASE DBName
оператор с соответствующими параметрами.Вы можете узнать это, выполнив sp_helpdb
exec sp_helpdb 'DBName'
Если говорить просто:
use master
select DB.name, F.physical_name from sys.databases DB join sys.master_files F on DB.database_id=F.database_id
это вернет все базы данных со связанными файлами
Из графического интерфейса:откройте свойства сервера, перейдите в Настройки базы данных, и посмотреть Расположение базы данных по умолчанию.
Обратите внимание, что вы можете переместить файлы базы данных куда угодно, хотя кажется удобнее хранить их в каталоге по умолчанию.
Вы можете найти расположение данных и журналов по умолчанию для текущего экземпляра SQL Server, используя следующий T-SQL:
DECLARE @defaultDataLocation nvarchar(4000)
DECLARE @defaultLogLocation nvarchar(4000)
EXEC master.dbo.xp_instance_regread
N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'DefaultData',
@defaultDataLocation OUTPUT
EXEC master.dbo.xp_instance_regread
N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'DefaultLog',
@defaultLogLocation OUTPUT
SELECT @defaultDataLocation AS 'Default Data Location',
@defaultLogLocation AS 'Default Log Location'
Маленькая придирка:папки с данными нет, есть только по умолчанию папка данных.
В любом случае, чтобы найти его, предполагая, что вы хотите установить первый экземпляр по умолчанию:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.1\Setup\SQLDataRoot
Если есть именованный экземпляр, MSSQL.1 становится чем-то вроде MSSQL10.INSTANCENAME.
Расширяя ответ «разбрызганные биты», вот полный скрипт, который это делает:
@ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION
SET _baseDirQuery=SELECT SUBSTRING(physical_name, 1, CHARINDEX(N'master.mdf', LOWER(physical_name)) - 1) ^
FROM master.sys.master_files WHERE database_id = 1 AND file_id = 1;
ECHO.
SQLCMD.EXE -b -E -S localhost -d master -Q "%_baseDirQuery%" -W >data_dir.tmp
IF ERRORLEVEL 1 ECHO Error with automatically determining SQL data directory by querying your server&ECHO using Windows authentication.
CALL :getBaseDir data_dir.tmp _baseDir
IF "%_baseDir:~-1%"=="\" SET "_baseDir=%_baseDir:~0,-1%"
DEL /Q data_dir.tmp
echo DataDir: %_baseDir%
GOTO :END
::---------------------------------------------
:: Functions
::---------------------------------------------
:simplePrompt 1-question 2-Return-var 3-default-Val
SET input=%~3
IF "%~3" NEQ "" (
:askAgain
SET /p "input=%~1 [%~3]:"
IF "!input!" EQU "" (
GOTO :askAgain
)
) else (
SET /p "input=%~1 [null]: "
)
SET "%~2=%input%"
EXIT /B 0
:getBaseDir fileName var
FOR /F "tokens=*" %%i IN (%~1) DO (
SET "_line=%%i"
IF "!_line:~0,2!" == "c:" (
SET "_baseDir=!_line!"
EXIT /B 0
)
)
EXIT /B 1
:END
PAUSE
я бы сделал восстановление из резервной копии просто потому, что это проще и поддерживает управление версиями.Справочные данные особенно нуждаются в версионировании, чтобы знать, когда они начали действовать.Отсоединение не даст вам такой возможности.Кроме того, с помощью резервных копий вы можете продолжать предоставлять обновленные копии без необходимости выключать базу данных.
Ответ Алекса правильный вариант, но для потомков есть еще один вариант:создайте новую пустую базу данных.Если вы используете CREATE DATABASE без указания целевого каталога, вы получите...каталоги данных/журналов по умолчанию.Легкий.
Однако лично я бы, вероятно, либо:
- ВОССТАНОВИТЕ базу данных на ПК разработчика, а не копируйте/прикрепляйте ее (резервные копии можно сжимать и размещать в формате UNC) или
- Используйте связанный сервер, чтобы вообще этого не делать (зависит от того, какой объем данных передается через соединение).
пс:20 ГБ — это не так уж и много даже в 2015 году.Но это все относительно.
SELECT DISTINCT dbo.GetDirectoryPath(filename) AS InstanceDataPaths
FROM sys.sysaltfiles WHERE filename like '%.mdf' and filename not like '%\MSSQL\Binn\%'
SELECT DISTINCT dbo.GetDirectoryPath(filename) AS InstanceLogPaths
FROM sys.sysaltfiles WHERE filename like '%.ldf' and filename not like '%\MSSQL\Binn\%'
Подробный сценарий SQL можно загрузить с сайта как найти каталог данных для экземпляра SQL Server
Вы получите местоположение по умолчанию, если пользовательская база данных по этому запросу:
declare @DataFileName nVarchar(500)
declare @LogFileName nVarchar(500)
set @DataFileName = (select top 1 RTRIM(LTRIM(name)) FROM master.sys.master_files where database_id >4 AND file_id = 1)+'.mdf'
set @LogFileName = (select top 1 RTRIM(LTRIM(name)) FROM master.sys.master_files where database_id >4 AND file_id = 2)+'.ldf'
select
( SELECT top 1 SUBSTRING(physical_name, 1, CHARINDEX(@DataFileName, LOWER(physical_name)) - 1)
FROM master.sys.master_files
WHERE database_id >4 AND file_id = 1) as 'Data File'
,
(SELECT top 1 SUBSTRING(physical_name, 1, CHARINDEX(@LogFileName, LOWER(physical_name)) - 1)
FROM master.sys.master_files
WHERE database_id >4 AND file_id = 2) as 'Log File'