O assunto sobre banco de dados é sempre um assunto muito delicado é importante antes de qualquer instrução a ser realizado no banco de dados, por favor, façam backup do banco de dados antes de qualquer instrução ou procure um DBA para realizar os comandos com maior segurança.
Como padrão do Servidor do Banco de Dados ao criar-se um novo banco de dados o padrão do SQL Server é que o Lock em um simples select, enquanto que em outra transação não consegue acessar o dados até a transação que requisição inicial (select) seja liberada pelo servidor/cliente. Nas próximas versões do sistema o banco de dados será criado com o comando (descrito abaixo) e não há a necessidade de execução desse comando.
Para exemplificar os problemas que podem ocorrer com a abordagem podem ser mostrado a seguir:
Imagina uma tabela de nome de Entidade com cinco registros e existem duas transações... Uma está no processo de atualização e inserção de uma nova entidade. Antes de a transação concluir outro usuário acessa a entidade através do Select. Para simular inicie um debug em uma aba do SQL Server Management Studio e pare em Insert.. e depois entre abra uma nova aba e execute o comando da transação 2.
Transação 1
Begin transaction
begin transaction
update Entidade Set NomeFantasia = 'Alterado 123' where ID =1
commit
Insert Into Entidade (Id,NomeFantasia) values (70, 'Test')
update Entidade Set NomeFantasia = 'Outra alteração' where ID = 2
commit
Transação 2
Select * From Entidade -- (Isso deve bloquear (lock) até que a atualização da transação 1 for resolvido )
A segunda transação irá trazer TODOS registros do banco de dados, mas somente quando a primeira transação for finalizada e isso causa lentidão e diversos outros problemas de performance no banco. Alguns para poder resolver isso usando o HINT with(lock) como alguns softwares fazem.
Mas existem uma outra forma usando um comando de configuração do próprio banco, alterando o ISOLATION LEVEL definindo no banco de dados.
Para realização desse commando se faz necessário que somente um usuário esteja conectado, o usuário da transação corrente, para saber se existem mais usuários use a procedure :
exec sp_who
Esse comando retorna todos os usuários conectados no sercidor.
Depois execute o segundo para alterar as configurações :
ALTER DATABASE [NomeDoBancoDeDados] SET READ_COMMITTED_SNAPSHOT ON;
Depois disso realize o mesmo procedimento da executado inicial em Transação 1 e Transação 2 e veja o SqlServer não irá bloquear o resultado do comando Transação 2.
Esse procedimento é aconselhado para TODOS os bancos de dados que existem no servidor, essa configuração ativa o modo ROW VERSION no controle de transações que é comum em outros servidores de banco de dados.
Para saber qual o nível que está configurado e execute o seguinte comando :
SELECT is_read_committed_snapshot_on,* FROM sys.databases WHERE name= 'NomeDoBancoDeados'
O resultado mostra as configurações do banco e uma das linhas mostram o ISOLATION LEVEL do banco de dados:
1 = READ_COMMITTED_SNAPSHOT opção está ATIVA.
0 = READ_COMMITTED_SNAPSHOT a opção está DESATIVADA (default).
Visando aumentar a confiabilidade e a segurança de nossas aplicações, realizamos uma alteração na criação do nosso login padrão (ontime) do usuário de nossos bancos de dados.
O login ontime, obsoleto, era criado com permissões de sysadmin, o que garantia a ele realizar operações especiais dentro do servidor, deixando-o vulnerável a qualquer ação mal-intencionada.
Um novo login será criado, melhorando o aspecto segurança em nosso banco de dados.
Para criação de um novo login:
Um script foi criado contendo as permissões necessárias para que um login tenha acesso básico, para o funcionamento dos add-ons.
Deverá ser criada uma nova função (Role e Server Role) e um novo login, contendo apenas as permissões especificadas.
Após a criação, basta conectar no servidor e alterar a senha do login.
Os comandos a seguir serão utilizados na criação do login:
CREATE LOGIN
Sintaxe:
CREATE LOGIN login_name { WITH <option_list1> | FROM <sources> }
<option_list1> ::=
PASSWORD = { 'password' | hashed_password HASHED } [ MUST_CHANGE ]
[ , <option_list2> [ ,... ] ]
<option_list2> ::=
SID = sid
| DEFAULT_DATABASE = database
| DEFAULT_LANGUAGE = language
| CHECK_EXPIRATION = { ON | OFF}
| CHECK_POLICY = { ON | OFF}
| CREDENTIAL = credential_name <sources> ::=
WINDOWS [ WITH <windows_options> [ ,... ] ]
| CERTIFICATE certname
| ASYMMETRIC KEY asym_key_name<windows_options> ::=
DEFAULT_DATABASE = database
| DEFAULT_LANGUAGE = language
CREATE SERVER ROLE
Sintaxe:
CREATE SERVER ROLE role_name [ AUTHORIZATION server_principal ]
CREATE ROLE
Sintaxe:
CREATE ROLE role_name [AUTHORIZATION owner_name]
GRANT - PERMISSÕES DE OBJETOS
Sintaxe:
GRANT <permission> [ ,...n ] ON
[ OBJECT :: ][ schema_name ]. object_name [ ( column [ ,...n ] ) ]
TO <database_principal> [ ,...n ]
[ WITH GRANT OPTION ]
[ AS <database_principal> ]
<permission> ::=
ALL [ PRIVILEGES ] | permission [ ( column [ ,...n ] ) ]
<database_principal> ::= Database_user
| Database_role
| Application_role
| Database_user_mapped_to_Windows_User
| Database_user_mapped_to_Windows_Group
| Database_user_mapped_to_certificate
| Database_user_mapped_to_asymmetric_key
| Database_user_with_no_login
ALTER AUTHORIZATION
Sintaxe:
ALTER AUTHORIZATION
ON [ <class_type>:: ] entity_name
TO { SCHEMA OWNER | principal_name }
[;]
<class_type> ::=
{
OBJECT | ASSEMBLY | ASYMMETRIC KEY | CERTIFICATE
| CONTRACT | TYPE | DATABASE | ENDPOINT | FULLTEXT CATALOG
| FULLTEXT STOPLIST | MESSAGE TYPE | REMOTE SERVICE BINDING
| ROLE | ROUTE | SCHEMA | SEARCH PROPERTY LIST | SERVER ROLE
| SERVICE | SYMMETRIC KEY | XML SCHEMA COLLECTION
}
Esses são os comandos e sintaxes utilizados para a criação de um login no Sql Server. A versão utilizada do SQL Server para este exemplo é:
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Feb 10 2012 19:39:15 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200:)
Como saber qual a versão do SQL Server?
SELECT @@VERSION
O Script abaixo exemplifica como utilizar os comandos:
CREATE LOGIN ontime
WITH PASSWORD = 'timeon' MUST_CHANGE,
DEFAULT_DATABASE=[master],
DEFAULT_LANGUAGE=[us_english],
CHECK_EXPIRATION=ON,
CHECK_POLICY=ON
GO
CREATE SERVER ROLE [AceesRestrictServerRole]
GO
CREATE ROLE [acessRestrictRole]
GO
GRANT EXECUTE TO [acessRestrictRole]
GRANT CREATE ANY DATABASE TO [AceesRestrictServerRole]
GRANT ALTER ANY DATABASE TO [AceesRestrictServerRole]
GRANT SELECT TO [acessRestrictRole]
GRANT CREATE VIEW TO [acessRestrictRole]
GRANT EXECUTE ON SCHEMA::dbo TO [acessRestrictRole]
GRANT SELECT ON SCHEMA::dbo TO [acessRestrictRole]
GRANT CREATE SEQUENCE ON SCHEMA::dbo TO [acessRestrictRole]
GRANT ALTER ON SCHEMA::dbo to [acessRestrictRole]
ALTER AUTHORIZATION ON DATABASE::[SBO_EMPRESA_MATRIZ] TO [ontime]
ALTER AUTHORIZATION ON DATABASE::[SBO-COMMON] TO [ontime]
ALTER SERVER ROLE [AceesRestrictServerRole] ADD MEMBER [ontime]
Dúvidas no script?
CREATE LOGIN ontime
WITH PASSWORD = 'timeon' MUST_CHANGE,
DEFAULT_DATABASE=[master],
DEFAULT_LANGUAGE=[us_english],
CHECK_EXPIRATION=ON,
CHECK_POLICY=ON
GO
--> Cria um login chamado 'ontime', com senha 'timeon' e base defautl 'master'.
--> linguagem 'us_english' e que checa a expiração e as diretivas.
--> Obs.: Ao conectar com o login criado é necessário alterar a senha.
CREATE SERVER ROLE [AceesRestrictServerRole]
GO
--> Cria uma função do servidor.
CREATE ROLE [acessRestrictRole]
GO
--> Cria uma função de banco, no banco de dados.
GRANT
CREATE ANY DATABASE,
ALTER ANY DATABASE TO [AceesRestrictServerRole]
GO
--> Concede permissão a função [AceesRestrictServerRole] de criar e alterar uma base de dados.
GRANT
SELECT,
CREATE VIEW,
EXECUTE TO [acessRestrictRole]
GO
--> Concede permissão para a função [acessRestrictRole] de executar SELECT, criar VIEW, e executar
--> Storeds Procedures.
GRANT
EXECUTE,
SELECT,
ALTER,
CREATE SEQUENCE ON SCHEMA::dbo TO [acessRestrictRole]
GO
--> Concede permissão para a função [acessRestrictRole] de executar os comandos de EXECUTE, SELECT, ALTER
--> e CREATE SEQUENCE no SCHEMA dbo .
--> O SCHEMA pode ser propriedade de qualquer banco de dados principal, e uma única entidade pode possuir
--> vários SCHEMAS. Você pode aplicar regras de segurança a um SCHEMA, que são herdadas por todos os objetos
--> no SCHEMA. Depois de configurar as permissões de acesso para um SCHEMA, essas permissões são aplicadas
--> automaticamente à medida que novos objetos são adicionados ao SCHEMA, ou seja, ao criar um login baseado
--> nas regras deste documento, e criar uma nova base de dados, ela automaticamente compartilhará de todas as
--> regras já criadas, pois usuários/logins ao SCHEMA dbo, não herdam as permissões de dbo da conta de usuário.
--> Nenhuma permissão é herdada por um SCHEMA de usuário, e sim por objetos de banco de dados contido no SCHEMA.
--> Por isso foram adicionados objetos de segurança ao SCHEMA dbo, para que eles sejam herdados em bases criadas
--> pelo login, e que terão o usuário dbo padrão.
--> Os usuários podem ser atribuídos em um SCHEMA padrão, e vários usuários de banco de dados podem compartilhar
--> o mesmo esquema.
--> Dúvidas consulte https://msdn.microsoft.com/en-us/library/bb669061(v=vs.110).aspx
ALTER AUTHORIZATION ON DATABASE::[SBO_EMPRESA_MATRIZ] TO [ontime]
ALTER AUTHORIZATION ON DATABASE::[SBO-COMMON] TO [ontime]
--> Altera as autorizações nas bases de dados [SBO_EMPRESA_MATRIZ] e [SBO-COMMON], para o login ontime
ALTER SERVER ROLE [AceesRestrictServerRole] ADD MEMBER [ontime]
--> Altera a Função [AceesRestrictServerRole] e adiciona o login 'ontime'
Para alteração de um login existente:
Para um login existente, deve-se primeiro remover as permissões que já estão vinculadas ao Server Role.
Caso não saiba quais são as permissões, o scritp abaixo é uma das alternativas para se descobrir.
SELECT
SRM.role_principal_id,
SP.name AS Role_Name,
SRM.member_principal_id,
SP2.name AS Member_Name
FROM sys.server_role_members AS SRM
JOIN sys.server_principals AS SP
ON SRM.Role_principal_id = SP.principal_id
JOIN sys.server_principals AS SP2
ON SRM.member_principal_id = SP2.principal_id
WHERE sp2.name = 'ontime' -- ->> Coloque aqui o nome do login especifico.
ORDER BY SP.name, SP2.name
O resultado mostrará em qual função (Role) o login está vinculado.
Neste exemplo o usuário ontime está vinculado às funções AceesRestrictServerRole e sysadmin. Para remover o vínculo use a procedure sp_dropsrvrolemember.
Sintaxe:
sp_dropsrvrolemember [@loginame=] 'login',[ @rolename = ] 'role'
Exemplo:
Removendo a função sysadmin
EXEC sp_dropsrvrolemember 'ontime', 'sysadmin';
Ou ainda altere a Server Role:
Sintaxe:
ALTER SERVER ROLE server_role_name
{
[ ADD MEMBER server_principal ]
| [ DROP MEMBER server_principal ]
| [ WITH NAME = new_server_role_name ]
} [ ; ]
Exemplo:
Removendo a regra sysadmin
ALTER SERVER ROLE [sysadmin] DROP MEMBER ontime
Após remover as funções que estão vinculadas, crie uma Server Role, uma Role com as permissões necessárias e adicione o login a elas.
Siga o scritp:
CREATE SERVER ROLE [AceesRestrictServerRole]
GO
CREATE ROLE [acessRestrictRole]
GO
GRANT EXECUTE TO [acessRestrictRole]
GRANT CREATE ANY DATABASE TO [AceesRestrictServerRole]
GRANT ALTER ANY DATABASE TO [AceesRestrictServerRole]
GRANT SELECT TO [acessRestrictRole]
GRANT CREATE VIEW TO [acessRestrictRole]
GRANT EXECUTE ON SCHEMA::dbo TO [acessRestrictRole]
GRANT SELECT ON SCHEMA::dbo TO [acessRestrictRole]
GRANT CREATE SEQUENCE ON SCHEMA::dbo TO [acessRestrictRole]
GRANT ALTER ON SCHEMA::dbo to [acessRestrictRole]
ALTER AUTHORIZATION ON DATABASE::[SBO_EMPRESA_MATRIZ] TO [ontime]
ALTER AUTHORIZATION ON DATABASE::[SBO-COMMON] TO [ontime]
ALTER SERVER ROLE [AceesRestrictServerRole] ADD MEMBER [ontime]
GO
Observe atentamente a alteração das autorizações nas bases de dados usadas como exemplo:
ALTER AUTHORIZATION ON DATABASE::[SBO_EMPRESA_MATRIZ] TO [ontime]
ALTER AUTHORIZATION ON DATABASE::[SBO-COMMON] TO [ontime]
Neste cenário, o login ontime terá acesso apenas a essas duas bases de dados e nas demais que sejam criadas por ele.
Caso já exista alguma base que precise de acesso deste login, use o comando
ALTER AUTHORIZATION ON DATABASE::[<DataBaseName>] TO [ontime]