2014-04-10
Trzeba przenieść bazę danych na inny dysk w clustrze. Dyski już gotowe, widać je w clustrze pora na zabawę z SQL. Niestety po poleceniu
ALTER DATABASE xxx MODIFY FILE
dostałem błąd:
Cannot use file 'I:\Default\xxxx.mdf’ for clustered server. Only formatted files on which the cluster resource of the server has a dependency can be used. Either the disk resource containing the file is not present in the cluster group or the cluster resource of the Sql Server does not have a dependency on it.
O co chodzi!? Chodzi o definicję zależności usług SQL od dysków. Skoro SQL ma korzystać z dysku I to musi w definicji clustra zależność pokazana niżej:

2014-04-10
Może być tak, że pracujesz z pewną ilością danych. Za każym razem może to byc inna liczba danych umieszczonych w tabeli ze zmienną ilością kolumn.
Jeśli trzeba by policzyć sumę dla każej kolumny w tej tabeli mogłyby się przydać zmienne sum1, sum2, sum3 ….
Oczywiście warto byłoby skorzystać z tablicy, ale jeśli preferujesz zmienne, to skrypt powershell może dynamicznie generować zmienne:
for ($i=1; $i -le 10; $i++)
{
New-Variable -Name "sum$i" -Value $i
Get-Variable -Name "sum$i" -ValueOnly
}
Pierwsza linijka stworzy zmienną o nazwie sum1, sum2, sum3… Jest to alternatywny sposób na tworzenie nazwy zmiennej. Zazwyczaj z niej nie korzystasz, wolisz napisać po prostu $sum1 i zmienna jest zadeklarowana i $sum1=100 i zmienna ma swoją wartość. Ale w takich „dziwnych” przypadkach możesz deklarować zmienną przez New-Variable, zmieniać jej wartość przez Set-Variable oraz odczytać wartość przez Get-Variable.
I pomyśleć że na pierwszy rzut oka wydawało się że te komendy stworzył chory z przepracowania programista…
2014-04-09
Załóżmy, że chcesz w Powershell wykonać zapytanie do serwera SQL i coś zrobić z wynikiem. Oto moja propozycja:
function RunQuery ([string]$computer,[string]$instance,[string]$database,[string]$query)
{
try
{
#determine the name of instance (for default instance – simply the server name and for named instance servername\instancename
if($instance -eq „MSSQLSERVER”)
{
$SQLServer = $computer
}
else
{
$SQLServer = „$computer\$instance”
}
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = „Server = $SQLServer; Database = $database; Integrated Security = True”
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $query
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet) | Out-Null
$SqlConnection.Close()
#return value
$DataSet.Tables[0]
}
catch {}
return false
}
Teraz korzystanie z tej funkcji poniżej. do zmiennej $table zostanie wpisany wynik polecenia wykonanego w instancji domyślnej na serwerze serverName. Jeśli chodzi o nazwaną instancję, to podaj jej nazwę zamisat MSSQLSERVER.
$table = RunQuery 'serverName’ 'MSSQLSERVER’ „master” 'select name, user_access_desc from sys.databases’
A teraz iteracja po wierszach zwróconej tabeli:
foreach ($record in $table)
{
$col1 = $record.Item(0)
$col2 = $record.Item(1)
echo „$col1 $col2”
}
2014-04-09
Powershell Web Access pozwala na połączenie do serwera Windows Server 2012 za pomocą przeglądarki, do dedykowanej aplikacji webowej, która z kolei potrafi utworzyć sesję powershell do dowolnego innego komputera w sieci. Bardzo sprytne, zakładając że przeglądarkę można uruchomić obecnie na komputerze, tablecie, telefonie… pralce (może z czasem…).
Oczywiście usługa musi być wcześniej skonfigurowana.
Próbowałem zainstalować PSWA zdalnie:
Enter-PSSession myServer
#check if it is already installed
Get-WindowsFeature *powershell*
#install windows powershell web access
install-windowsFeature WindowsPowershellWebAccess
#check available cmdlets (found 6)
get-help *pswa*
#configure, create web application, select certificate to use
#(Test Certificate = Self Signed Certificate - do not use in production!)
Install-PswaWebApplication -UseTestCertificate
I tutaj pojawił się problem:
WARNING: The 'Microsoft.PowerShell.Security’ module was not imported because the 'Microsoft.PowerShell.Security’ snap-in was already imported.
The 'Install-PswaWebApplication’ command was found in the module 'PowerShellWebAccess’, but the module could not be loaded. For more information, run 'Import
-Module PowerShellWebAccess’.
+ CategoryInfo : ObjectNotFound: (Install-PswaWebApplication:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CouldNotAutoloadMatchingModule
Co pomogło? Zalogowałem się na docelowej maszynie poprzez RDP i tam wykonałem ostatnie komendy
Czytaj dalej »
2014-04-07
Chciałem usunąć joby powiązane z maintnance planem. Zacząłem od usunięcia maintnance planu, co udało się znakomicie! Maintanace planów już nie było, joby pozostały. Próbuję więc usunąć joba, a tu:

The DELETE statement conflicted with the REFERENCE constraint „FK_subplan_job_id”. The conflict occurred in database „msdb”, table „dbo.sysmaintplan_subplans”, column 'job_id’.
The statement has been terminated. (Microsoft SQL Server, Error: 547) Czytaj dalej »
2014-04-06
Kiedy shrinkujesz bazę, mimo tego, że dobrze wiadomo, że shrinkowanie nie jest dobre, no ale czasem trzeba, a obawiasz się o zablokowanie bazy na długi długi czas, możesz wykonywać pomiejszanie pliku etapami. Np zamiast pomniejszyć ją o 50 GB na raz, zmniejsz ją po 5 GB w 10 krokach.
Zawsze to masz jakąś kontrolę nad procesem shrink. Jeśli już jednak zapuściłeś dużego shrinka, a wykonanie trwa i trwa, to pewnie chciałbyś wiedzieć kiedy się skończy.
Poniższe zapytanie spróbuje mniej więcej wyznaczyć czas zakończenia polecenia:
SELECT command, percent_complete, start_time,
CAST(((DATEDIFF(s,start_time,GetDate()))/3600) as varchar) + ’ hour(s), ’
+ CAST((DATEDIFF(s,start_time,GetDate())%3600)/60 as varchar) + 'min, ’
+ CAST((DATEDIFF(s,start_time,GetDate())%60) as varchar) + ’ sec’ as running_time,
CAST((estimated_completion_time/3600000) as varchar) + ’ hour(s), ’
+ CAST((estimated_completion_time %3600000)/60000 as varchar) + 'min, ’
+ CAST((estimated_completion_time %60000)/1000 as varchar) + ’ sec’ as est_time_to_go,
dateadd(second,estimated_completion_time/1000, getdate()) as est_completion_time,
s.text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) s
where command=’dbccFilesCompact’
Skomplikowane obliczenia CAST… mają na celu przedstawienie czasu zakończenia polecenia w czytelnej dla człowieka formie.
2014-04-06
Może są otwarte jakieś transkacje? Kandydat na zasobożercę:
DBCC OPENTRAN
Jeśli znajdziesz tutaj numer sesji, to może warto zobaczyć co ta sesja robi?
select t.text,* from sys.dm_exec_connections c
cross apply sys.dm_exec_sql_text(c.most_recent_sql_handle) t
where c.session_id=55
A może ta lub jakaś inna sesja zablokowała inną sesję. Odpowiedź da (kolumna BlkBy):
EXEC sp_who2
Może powstały jakieś olbrzymie tabele w tempdb? Poniższe zapytanie wyświetli tabele i ich rozmiary:
use tempdb;
SELECT TBL.name AS ObjName
,STAT.row_count AS StatRowCount
,STAT.used_page_count * 8 AS UsedSizeKB
,STAT.reserved_page_count * 8 AS RevervedSizeKB
FROM tempdb.sys.partitions AS PART
INNER JOIN tempdb.sys.dm_db_partition_stats AS STAT
ON PART.partition_id = STAT.partition_id
AND PART.partition_number = STAT.partition_number
INNER JOIN tempdb.sys.tables AS TBL
ON STAT.object_id = TBL.object_id
ORDER BY TBL.name;
To może popatrzmy, która sesja otrzymywała najwięcej przestrzeniw w tempdb? Będzie to kandydat na zasobożercę:
SELECT
sys.dm_exec_sessions.session_id AS [SESSION ID],
DB_NAME(database_id) AS [DATABASE Name],
HOST_NAME AS [System Name],
program_name AS [Program Name],
login_name AS [USER Name],
status,
cpu_time AS [CPU TIME (in milisec)],
total_scheduled_time AS [Total Scheduled TIME (in milisec)],
total_elapsed_time AS [Elapsed TIME (in milisec)],
(memory_usage * 8) AS [Memory USAGE (in KB)],
(user_objects_alloc_page_count * 8) AS [SPACE Allocated FOR USER Objects (in KB)],
(user_objects_dealloc_page_count * 8) AS [SPACE Deallocated FOR USER Objects (in KB)],
(internal_objects_alloc_page_count * 8) AS [SPACE Allocated FOR Internal Objects (in KB)],
(internal_objects_dealloc_page_count * 8) AS [SPACE Deallocated FOR Internal Objects (in KB)],
CASE is_user_process
WHEN 1 THEN 'user session’
WHEN 0 THEN 'system session’
END AS [SESSION Type], row_count AS [ROW COUNT]
FROM sys.dm_db_session_space_usage
INNER join sys.dm_exec_sessions
ON sys.dm_db_session_space_usage.session_id = sys.dm_exec_sessions.session_id
i znowu sprawdzenie co ta sesja robi, jak wyżej