{"id":770,"date":"2015-11-08T21:39:21","date_gmt":"2015-11-09T00:39:21","guid":{"rendered":"http:\/\/thesqltimes.com\/blog\/?p=770"},"modified":"2015-11-08T21:39:35","modified_gmt":"2015-11-09T00:39:35","slug":"apresentando-custommssql","status":"publish","type":"post","link":"https:\/\/thesqltimes.com\/blog\/2015\/11\/08\/apresentando-custommssql\/","title":{"rendered":"Apresentando CustomMSSQL, Copy-SQLdatabase e SCRIPT STORE: Vers\u00e3o BETA"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"Muito \u00fatil!\" data-post-id=\"770\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Tempo de Leitura:<\/span> <span class=\"rt-time\"> 6<\/span> <span class=\"rt-label rt-postfix\">minutos<\/span><\/span><p>H\u00e1 muito tempo, ingressei no mundo de tecnologia estudando HTML. Desde ent\u00e3o, aprendi muitas coisas na \u00e1rea de TI e n\u00e3o parei por a\u00ed. Bom, o que isso tem a ver com esse post? Simples: A comunidade, n\u00e3o s\u00f3 de SQL, mas de tecnologia em geral, \u00e9 uma das coisas mais importantes de minha carreira.<\/p>\n<p>Pensando em retribuir isso, h\u00e1 algum tempo eu venho mantendo uma s\u00e9rie de scripts feitos em powershell que t\u00eam me ajudado a gerenciar o ambiente SQL. Eu gostei bastante dos resultados que resolvi public\u00e1-los. E tudo isso ser\u00e1 de gra\u00e7a, free, 0800, para sempre! Para tentar entregar algo mais organizado e f\u00e1cil de aprender, eu tamb\u00e9m estou lan\u00e7ando a <a href=\"http:\/\/scriptstore.thesqltimes.com\/\" target=\"_blank\">SCRIPT STORE<\/a>. A script store \u00e9 um reposit\u00f3rio de tudo que \u00e9 tipo de script que eu irei publicar e manter atualizado. Em breve, espero que ela esteja bem, mas bem cheia mesmo.<\/p>\n<p>J\u00e1 existem dois scripts publicados: O m\u00f3dulo <a href=\"http:\/\/scriptstore.thesqltimes.com\/docs\/custommssql\/\" target=\"_blank\">CustomMSSQL<\/a> e a procedure <a href=\"http:\/\/scriptstore.thesqltimes.com\/docs\/whoisauthorized\/\" target=\"_blank\">sp_WhoIsAuthorized<\/a>. Eu j\u00e1 fiz muitos testes com estes dois scripts, tanto que j\u00e1 possui mais de 1 ano de vida. E, eu venho usado em meu dia-a-dia como DBA. Estes scripts s\u00e3o exemplos de coisas que eu sinto falta no SQL Server, e espero que voc\u00ea possa me ajudar, ou melhor, possa ajudar a todos, fazendo destes c\u00f3digos algo est\u00e1vel e \u00fatil para muitos ambientes, e claro, sempre e sempre free!<\/p>\n<p>Hoje eu vou dar destaque para o m\u00f3dulo CustomMSSQL. Este m\u00f3dulo disponibiliza v\u00e1rios cmdlets para lidarmos com o SQL Server. Por exemplo, temos o <strong>Get-SQLAgentOptions<\/strong> que traz as configura\u00e7\u00f5es do SQL Agent que est\u00e3o salvas no registro. H\u00e1 tamb\u00e9m o <strong>Send-SQL2Zabbix<\/strong>, que \u00e9 um cmdlet extremamente poderoso para quem quer integrar o SQL Server com o Zabbix. Este \u00faltimo eu j\u00e1 estou usando em um ambiente que estou trabalhando e tenho tido resultados incr\u00edveis. Em breve posto mais sobre ele.<\/p>\n<p>Eu quero inaugurar este m\u00f3dulo falando, na verdade, de um cmdlet que desenvolvi e t\u00eam sido meu xod\u00f3 e me ajudado bastante: <a href=\"http:\/\/scriptstore.thesqltimes.com\/docs\/custommssql\/custommssql-cmdlets\/copy-sqldatabase\/\" target=\"_blank\">Copy-SQLDatabase<\/a>. Como o nome j\u00e1 diz, este cmdlet serve para copiar bases SQL. Vou pegar o exemplo da <a href=\"http:\/\/scriptstore.thesqltimes.com\/custommssql\/custommssql-cmdlets\/copy-sqldatabase\/copysqldatabase-intro\/\" target=\"_blank\">documenta\u00e7\u00e3o do cmdlet que j\u00e1 est\u00e1 dispon\u00edvel na Script Store:<\/a><\/p>\n<pre class=\"lang:ps decode:true\" title=\"Usando Copy-SQLDatabase\">import-module CustomMSSQL\r\n\r\nCopy-SQLDatabase -SourceServerInstance \"ProdServer\\Inst01\" -SourceDatabase \"MyDb\" -DestinationServerInstance \"DevInst\" -DestinationDatabase \"MyDb\" -BackupFolder \"\\\\SQLBackups\\Temp$\" -RestoreFolder \"MSSQL\\DEFAULT_INST\"\r\n<\/pre>\n<p>Bom, conforme descrito na documenta\u00e7\u00e3o, este exemplo \u00e9 bem simples: ele copia a base MyDB, que est\u00e1 na inst\u00e2ncia &#8220;ProdServer\\Inst01&#8221; para a inst\u00e2ncia &#8220;DevInst&#8221; com o nome, tamb\u00e9m, de &#8220;MyDb&#8221;.<\/p>\n<p>O processo \u00e9 bem simples e se voc\u00ea j\u00e1 administra inst\u00e2ncias SQL h\u00e1 algum tempo, j\u00e1 estar\u00e1 familiarizado: Ele faz um BACKUP da base na inst\u00e2ncia de origem, e um RESTORE na inst\u00e2ncia de destino. Simples. A principal diferen\u00e7a, e minha preferida, \u00e9 que eu n\u00e3o preciso me preocupar mais em determinar em quais discos a base dever\u00e1 ser restaurada. O cmdlet ir\u00e1 fazer isso por conta pr\u00f3pria. Gra\u00e7as \u00e0 flexibilidade do powershell, o script consegue determinar os discos dispon\u00edveis no servidor onde a inst\u00e2ncia de destino est\u00e1. Isso \u00e9 perfeito para a maioria das c\u00f3pias entre produ\u00e7\u00e3o e desenvolvimento.<\/p>\n<figure id=\"attachment_772\" aria-describedby=\"caption-attachment-772\" style=\"width: 1269px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-772\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/01-ScriptStart.png\" alt=\"Log coletado de um caso real\" width=\"1269\" height=\"794\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/01-ScriptStart.png 1269w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/01-ScriptStart-300x188.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/01-ScriptStart-1024x641.png 1024w\" sizes=\"auto, (max-width: 1269px) 100vw, 1269px\" \/><figcaption id=\"caption-attachment-772\" class=\"wp-caption-text\">Exemplo do in\u00edcio do log de Copy-SQLDatabase. Este log foi de um uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.<\/figcaption><\/figure>\n<p>Quando a base n\u00e3o existe, o algoritmo que ele usa tem uma l\u00f3gica bem simples: Maiores primeiros. Isto significa que, partindo do maior do arquivo, o cmdlet tenta eleger em qual volume ele ir\u00e1 alocar o mesmo. Ap\u00f3s escolher, ele subtrair a quantidade de espa\u00e7o do volume, e checa o pr\u00f3ximo maior arquivo. Ele vai fazendo at\u00e9 que todos os arquivos tenham sido mapeados para um volume. Se algum arquivo n\u00e3o pode ser mapeado, por n\u00e3o haver um volume com espa\u00e7o suficiente, por exemplo, ent\u00e3o ele encerra a execu\u00e7\u00e3o e exibe o erro.<\/p>\n<p>Se a base de destino j\u00e1 existe, por padr\u00e3o, o script vai tomar um caminho diferente. Ao inv\u00e9s de realocar os arquivos em volumes novos, ele usa os diret\u00f3rios em que os arquivos da base existente est\u00e3o. Ele associa os arquivos pelo nome l\u00f3gico. Se o arquivo n\u00e3o existir \u00a0na base de destino (caso tenha sido adicionado desde que a base foi copiada, por exemplo) ele escolhe um dos diret\u00f3rios aleatoriamente. O cmdlet tem esse comportamento pois ele assume que a base de destino j\u00e1 est\u00e1 alocada no melhor lugar poss\u00edvel. Voc\u00ea controlar esse comportamento atrav\u00e9s de par\u00e2metros do cmdlet. No caso da base existir tamb\u00e9m, antes de substitui-la, usu\u00e1rios, permiss\u00f5es e roles s\u00e3o &#8220;backupeados&#8221; para depois serem restaurados.<\/p>\n<figure id=\"attachment_773\" aria-describedby=\"caption-attachment-773\" style=\"width: 1294px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-773\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/02-ScriptDeterminandoSource.png\" alt=\"Exemplo do log de Copy-SQLDatabase, quando vai fazer o backup na origem e determinar os arquivos dispon\u00edveis. Este log foi de uma uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.\" width=\"1294\" height=\"462\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/02-ScriptDeterminandoSource.png 1294w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/02-ScriptDeterminandoSource-300x107.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/02-ScriptDeterminandoSource-1024x366.png 1024w\" sizes=\"auto, (max-width: 1294px) 100vw, 1294px\" \/><figcaption id=\"caption-attachment-773\" class=\"wp-caption-text\">Exemplo do log de Copy-SQLDatabase, quando vai fazer o backup na origem e determinar os arquivos dispon\u00edveis. Este log foi de um uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.<\/figcaption><\/figure>\n<p>Bom, \u00a0h\u00e1 muita, mas muita coisa que este cmdlet \u00e9 capaz de fazer, e em futuros posts irei dar mais dicas e mostrar mais funcionalidades. Por hora, destaco alguns par\u00e2metros que potencializam Copy-SQLDatabase:<\/p>\n<ul>\n<li>UseRecent, RecentFileMask e RecentBase<br \/>\nEstes par\u00e2metros permitem que voc\u00ea especifique um arquivo existente como fonte do RESTORE, ao inv\u00e9s do cmdlet executar um BACKUP novo. Voc\u00ea pode controlar qu\u00e3o recente o arquivo deve ser e o filtro para listar os arquivos. O cmdlet ir\u00e1 procurar o arquivo no diret\u00f3rio especificado por &#8220;BackupFolder&#8221;.<\/li>\n<li>DestinationDatabaseBackup<br \/>\nFaz o backup da base de destino antes de substitui-la. Voc\u00ea deve informar o caminho do backup. Isso \u00e9 \u00fatil em situa\u00e7\u00f5es que necessitem guardar uma base que ser\u00e1 sobrescrita.<\/li>\n<li>ForceSimple, Replace, NoRecovery<br \/>\nColoca a base em SIMPLE ap\u00f3s restaur\u00e1-la, usa a op\u00e7\u00e3o REPLACE e usa a op\u00e7\u00e3o NORECOVERY, respectivamente.<\/li>\n<li>AllowedVolumes,VolumesForData, VolumesForLog<br \/>\nPermite especificar quais volumes ser\u00e3o usados. AllowedVolumes restringe os volumes que ser\u00e3o considerados. Voc\u00ea pode usar caracteres coringa como &#8220;*&#8221;. VolumesForData e VolumesForLog permite que voc\u00ea especifique em quais volumes o cmdlet deve mapear arquivos de dados e arquivos de log, respectivamente. Isso \u00e9 bem \u00fatil quando voc\u00ea que restaurar bases na produ\u00e7\u00e3o. Estes par\u00e2metros n\u00e3o t\u00eam efeito quando a base j\u00e1 existe e o diret\u00f3rio dos arquivos existentes ser\u00e3o usados.<\/li>\n<li>PostScripts, UseLimitedUser<br \/>\nEste e um dos meus favoritos. Muitas solicita\u00e7\u00f5es de c\u00f3pias de produ\u00e7\u00e3o para desenvolvimento incluem a execu\u00e7\u00e3o de scripts, como por exemplo, um UPDATE para trocar as senhas para &#8220;123456&#8221;. Pensando na diversidade destas solicita\u00e7\u00f5es, voc\u00ea pode especificar um array de c\u00f3digo T-SQL para ser executado na base ap\u00f3s o restore. Voc\u00ea pode especificar diret\u00f3rios, comandos T-SQL ou nome de arquivos. O\u00a0par\u00e2metro UseLimitedUser faz com que os scripts sejam executados com um usu\u00e1rio que s\u00f3 ir\u00e1 ter acesso a base restaurada. Isso pode evitar que scripts maliciosos afetem a inst\u00e2ncia inteira. Por exemplo, se o usu\u00e1rio colocar um SHUTDOWN no script, ele n\u00e3o ir\u00e1 funcionar. \u00a0O script apenas cria um login\/usu\u00e1rio \u00fanico na inst\u00e2ncia\/base, concede permiss\u00f5es de db_owner na base de destino somente, e ao final deleta ele.<\/li>\n<li>LogTo e LogLevel<br \/>\nCom estes par\u00e2metros voc\u00ea pode controlar \u00a0quantidade de Log que \u00e9 gerado pelo script. O padr\u00e3o \u00e9 o modo &#8220;DETAILED&#8221; onde ele mostra uma s\u00e9rie de informa\u00e7\u00f5es a respeito do progresso do script. Pode ser \u00fatil para entender erros que podem acontecer, \u00a0ou mesmo ver para onde os arquivos ser\u00e3o mapeados. Com \u00a0LogTo, voc\u00ea controla para onde o log ser\u00e1 feito. Voc\u00ea pode especificar um array de arquivos. O padr\u00e3o \u00e9 &#8220;#&#8221; que significa que o script ir\u00e1 usar &#8220;write-host&#8221; para logar as mensagens.<\/li>\n<\/ul>\n<p>Apesar de estar na vers\u00e3o beta, eu j\u00e1 tenho usado este script para copiar diversas bases, todos os dias, de produ\u00e7\u00e3o para homologa\u00e7\u00e3o, e usando, al\u00e9m dos par\u00e2metros acima, muitos outros disponibilizados. Recentemente eu usei o script para migrar cerca de 20 bases distribu\u00eddas em 100GB de uma inst\u00e2ncia standalone para uma inst\u00e2ncia em cluster, em produ\u00e7\u00e3o. Apesar de ser pouco, eu poupei bastante trabalho e precisei apenas observar.<\/p>\n<figure id=\"attachment_774\" aria-describedby=\"caption-attachment-774\" style=\"width: 1184px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-774\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/03-DeterminandoVolumes.png\" alt=\"Exemplo log de Copy-SQLDatabase, quando vai determinar os volumes. Este log foi de uma uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.\" width=\"1184\" height=\"551\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/03-DeterminandoVolumes.png 1184w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/03-DeterminandoVolumes-300x140.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/03-DeterminandoVolumes-1024x477.png 1024w\" sizes=\"auto, (max-width: 1184px) 100vw, 1184px\" \/><figcaption id=\"caption-attachment-774\" class=\"wp-caption-text\">Exemplo log de Copy-SQLDatabase, quando vai determinar os volumes. Este log foi de uma uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.<\/figcaption><\/figure>\n<p>&nbsp;<\/p>\n<figure id=\"attachment_775\" aria-describedby=\"caption-attachment-775\" style=\"width: 1170px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-775\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/Log_ForthPart.png\" alt=\"Exemplo do log de Copy-SQLDatabase, quando, vai determinar em quais volumes ele ir\u00e1 alocar o arquivo. Este log foi de uma uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.\" width=\"1170\" height=\"772\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/Log_ForthPart.png 1170w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/Log_ForthPart-300x198.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/11\/Log_ForthPart-1024x676.png 1024w\" sizes=\"auto, (max-width: 1170px) 100vw, 1170px\" \/><figcaption id=\"caption-attachment-775\" class=\"wp-caption-text\">Exemplo do log de Copy-SQLDatabase, quando, vai determinar em quais volumes ele ir\u00e1 alocar o arquivo. Este log foi de uma uso em real, para copiar a base de uma inst\u00e2ncia de produ\u00e7\u00e3o para outra, em cluster.<\/figcaption><\/figure>\n<p>Bom, espero que o script seja \u00fatil e qualquer d\u00favida, sugest\u00e3o e problema basta enviar um email para &#8220;rodrigo@thesqltimes.com&#8221; ou &#8220;rodrigorigomes@gmail.com&#8221; ou enviar em um coment\u00e1rio deste post.<\/p>\n<p>Baixe\u00a0o m\u00f3dulo CustomMSSQL Beta em: <a href=\"http:\/\/scriptstore.thesqltimes.com\/custommssql\/sobre-custommssql\/custommssql\/\" target=\"_blank\">http:\/\/scriptstore.thesqltimes.com\/custommssql\/sobre-custommssql\/custommssql\/\u00a0<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>H\u00e1 muito tempo, ingressei no mundo de tecnologia estudando HTML. Desde ent\u00e3o, aprendi muitas coisas na \u00e1rea de TI e n\u00e3o parei por a\u00ed. Bom, o que isso tem a ver com esse post? Simples: A comunidade, n\u00e3o s\u00f3 de SQL, mas de tecnologia em geral, \u00e9 uma das coisas mais importantes de minha carreira.&hellip;&nbsp;<a href=\"https:\/\/thesqltimes.com\/blog\/2015\/11\/08\/apresentando-custommssql\/\" rel=\"bookmark\"><span class=\"screen-reader-text\">Apresentando CustomMSSQL, Copy-SQLdatabase e SCRIPT STORE: Vers\u00e3o BETA<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":772,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[8,3,11,94,7],"tags":[174,171,172,96,175,177,173,176,133,73],"series":[],"class_list":["post-770","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administracao","category-banco-de-dados-2","category-desenvolvimento","category-powershell","category-sql-server","tag-backup","tag-copy-sqldatabase","tag-custommssql","tag-powershell","tag-restore","tag-scripts","tag-scriptstore","tag-send-sql2zabbix","tag-who-is-authorized","tag-sql-server"],"_links":{"self":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/770","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/comments?post=770"}],"version-history":[{"count":3,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/770\/revisions"}],"predecessor-version":[{"id":777,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/770\/revisions\/777"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media\/772"}],"wp:attachment":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media?parent=770"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/categories?post=770"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/tags?post=770"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/series?post=770"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}