Is it possible to put a ceiling on the amount of CPU a certain database or preferably a certain user, or group of users can use?
I have one app on a server that is maxing out the CPU due to complex queries that are being created at runtime. Until the specific module in that application is redeveloped (which could take months) i need to find a way to stop that specific application from choking SQL Server and reducing availability for other apps on the same server.
Do you look at Resource Governor? It makes possible to devde the resources between the group of users.
This is only example and for full information you need to look at documentation:
Create the pools:
create resource pool Pool1
with (
min_cpu_percent = 30
, max_cpu_percent = 100
)
create resource pool Pool2
with (
min_cpu_percent = 50
, max_cpu_percent = 70
)
create resource pool Pool3
with (
min_cpu_percent = 5
, max_cpu_percent = 100
)
Create the workload groups and link them to pools:
create workload group Group1
using Pool1
create workload group Group2
using Pool2
create workload group Group3
using Pool3
Create the function which will be make decision which workload group will be used for current session:
create function dbo.rg_class_simple() returns sysname
with schemabinding
as begin
declare
#grp_name as sysname
if (suser_name() = 'user1')
set #grp_name = 'Group1'
else if (suser_name() = 'user2')
set #grp_name = 'Group2'
else if (suser_name() = 'user3')
set #grp_name = 'Group3'
return #grp_name
end
Related
I have datasets that are pulling from multiple Amazon RDS servers in multiple accounts, and I'd really like to be able to have the SQL Server instance tell me which account owns it and which region it lives in.
For example, this would be ideal when constructing ARNs on the fly:
SELECT id, 'arn:aws:quicksight:' + rdsadmin.dbo.get_region() +
':' + rdsadmin.dbo.get_account_id() + ':group/default/admin' AS groupArn
FROM my_rules_table
I've looked all over and I don't see a way to infer this information. I could create unique versions of those UDFs on every server with static values, but I'd really rather fetch the actual values dynamically.
EDIT:
Another way to think about my request is that I want to do in Amazon RDS what I can do in all my other EC2 instances:
read -r account_id region <<< $(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r '. | "\(.accountId) \(.region)"')
echo "arn:aws:quicksight:$region:$account_id:group/default/admin"
This is just a workaround because Amazon QuickSight has certain requirements on the supported SQL features used to fetch data.
I was unable to find the information exposed from Amazon RDS for Microsoft® SQL Server®, so I created a table to hold this information in each RDS instance:
CREATE TABLE rds_instance (
id UNIQUEIDENTIFIER NOT NULL DEFAULT(NEWID()),
account_id VARCHAR(20) NOT NULL,
environment VARCHAR(20) NOT NULL,
region VARCHAR(20) NOT NULL,
active BIT NOT NULL DEFAULT(0),
PRIMARY KEY (id)
);
The values for account_id, environment, and region can be plugged in and used where needed. A copied database can be programmatically modified for its new placement:
UPDATE rds_instance SET active = 0;
INSERT INTO rds_instance (account_id, environment, region, active)
VALUES ('12341234123', 'stage', 'us-southwest-7', 1);
The instance information can be used to produce ARNs in a query like so:
SELECT u.fkid, 'arn:aws:quicksight:' + ri.region + ':' + ri.account_id +
':user/' + ri.environment + '_ns/' + u.username AS userArn
FROM users AS u
JOIN rds_instance AS ri ON (ri.active = 1)
I am accessing the other database using elastic queries. The data source was created like this:
CREATE EXTERNAL DATA SOURCE TheCompanyQueryDataSrc WITH (
TYPE = RDBMS,
--CONNECTION_OPTIONS = 'ApplicationIntent=ReadOnly',
CREDENTIAL = ElasticDBQueryCred,
LOCATION = 'thecompanysql.database.windows.net',
DATABASE_NAME = 'TheCompanyProd'
);
To reduce the database load, the read-only replica was created and should be used. As far as I understand it, I should add the CONNECTION_OPTIONS = 'ApplicationIntent=ReadOnly' (commented out in the above code). However, I get only the Incorrect syntax near 'CONNECTION_OPTIONS'
Both databases (the one that sets the connection + external tables, and the other to-be-read-only are at the same server (thecompanysql.database.windows.net). Both are set the compatibility lever SQL Server 2019 (150).
What else should I set to make it work?
The CREATE EXTERNAL DATA SOURCE Syntax doesn't support the option CONNECTION_OPTIONS = 'ApplicationIntent=ReadOnly'. We can't use that in the statements.
If you want achieve that readonly request, the way is that please use the user account which only has the readonly(db_reader) permission to login the external database.
For example:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<password>' ;
CREATE DATABASE SCOPED CREDENTIAL SQL_Credential
WITH
IDENTITY = '<username>' -- readonly user account,
SECRET = '<password>' ;
CREATE EXTERNAL DATA SOURCE MyElasticDBQueryDataSrc
WITH
( TYPE = RDBMS ,
LOCATION = '<server_name>.database.windows.net' ,
DATABASE_NAME = 'Customers' ,
CREDENTIAL = SQL_Credential
) ;
Since the option is not supported, then we can't use it with elastic query. The only way to connect to the Azure SQL data with SSMS is like this:
HTH.
I have a C# app that is multi-threaded. The application's purpose is to find an available proxy server stored in a SQL server table to connect to.
The table contains 200 proxies. The maximum concurrent proxy connections allowed is 5.
The table has the following columns:
(ProxyId int, IpAddress varchar, IsSocks bit, ConnectStatus tinyint, LastConnected datetime)
ProxyId is a identity column, ConnectStatus has 3 values
0: available (updated by C# app)
1: being connected to (updated inside the sp below)
2: connected (updated by C# app)
I have the following stored procedure defined which will be called from the C# app:
Create Proc GetNextAvailableProxy
AS
Declare #proxyId int, #ipAddress varchar(20), #isSocks bit
if (Select Count(*) From Proxies Where ConnectStatus > 0) < 5 Begin
Select Top 1 #proxyId = Id, #ipAddress= IpAddress, #isSocks = IsSocks
From Proxies with (updlock, readpast)
Where ConnectStatus = 0
Order By IsNull(LastConnected, '1970-01-01')
Update Proxies Set ConnectStatus = 1
Where Id = #proxyId
Select #proxyId ProxyId, #ipAddress IpAddress, #isSocks IsSocks;
return;
End
Select Null ProxyId, Null IpAddress, Null IsSocks
GO
The above sp gets the next available proxy, and if there are 5 proxies being connected to or connected, the C# app receives Null for proxyId and wait for 2 seconds before attempting again.
The C# app will set the ConnectStatus = 2 when the proxy connection is established successfully, and ConnectStatus = 0 once the work is done.
My question: is my sp written correctly with the right choice of table hint? I don't know what table hint I should place on the Select Count(*) statement.
I have Oracle 10g database. I want to mask my record of tables. It doesn't really need to make sense, it doesn't need to be readable. Just needs to be masked. For example:
select *
from customer;
LAST_NAME FIRST_NAME ADDRESS
-------------- -------------- --------------------
Doe John 10 someroad st
i convert to this :
LAST_NAME FIRST_NAME ADDRESS
-------------- -------------- --------------------
Ahd Uiea 55 xxxx ue
I need open source software that can do this work. What should i use?
You can use ORA_HASH or DBMS_CRYPTO package to full fill your requirements. Giving solution using DBMS_CRYPTO:
--Source data:
create table customer(last_name varchar2(50),first_name varchar2(50), address varchar2(200));
--Encrypt Function(Script Source):
CREATE OR REPLACE FUNCTION encrypt_value (p_in IN varchar2, p_key IN raw) RETURN raw IS l_enc_val raw (2000);
l_mod number := dbms_crypto.ENCRYPT_AES128 + dbms_crypto.CHAIN_CBC + dbms_crypto.PAD_PKCS5;
BEGIN l_enc_val := dbms_crypto.encrypt ( UTL_I18N.STRING_TO_RAW (p_in, 'AL32UTF8'), l_mod, p_key );
RETURN l_enc_val;
END;
--Function Implementation:
select encrypt_value(last_name,'AABBCC'),encrypt_value(first_name,'AABBCC'), encrypt_value(address,'AABBCC') from customer;
If you're using the Enterprise version of Oracle, you can use a Virtual Private Database (VPD) for this.
A VPD allows you to fine-grained access control (based on the account used to connect to the database). It can:
return only a subset of rows
use column masking to display sensitive columns as NULL values
It achieves this by appending a custom WHERE clause to every query run against the table. There's no way to circumvent it, and no need to adapt existing applications (for using a custom-built view etc.)
To create a VPD for your customer table, you need to:
create a function for generating the WHERE clause
create a policy for your database table
enable the policy
Function
CREATE OR REPLACE FUNCTION hide_address (
v_schema IN VARCHAR2,
v_objname IN VARCHAR2)
RETURN VARCHAR2 AS
result VARCHAR2 (200);
BEGIN
result := '1=0'; -- evaluates to FALSE for every account
RETURN (result);
END hide_address;
Creating a policy
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'scott',
object_name => 'customer',
policy_name => 'hide_address_policy',
policy_function => 'hide_address',
sec_relevant_cols =>' address',
sec_relevant_cols_opt => dbms_rls.ALL_ROWS);
END;
After enabling the policy, every query trying to access CUSTOMER.ADDRESS will return NULL. Depending on your requirements, you might want to add a view to access the table that returns a random address instead of NULL:
select name,
(case when address is NULL
then dbms_random.string('', 15)
else address end) as address
from
customer
I'm trying to build an XE in order to find out which of our internal apps (that don't have app names and thus show up as .Net SQLClient Data Provider) are hitting particular servers. Ideally, I'd like to get the name of the Client and Database , but not sure if I can do that in one XE.
I figured for ease of use, I'd use a histogram/asynchronous_bucketizer, and save counts of what's trying to hit and how often. However, I can't seem to get it work on 2012, much less 2008. If I use sqlserver.existing_connection it works, but only gives me the count when it connects. I want to get counts during the day and see how often it occurs from each server, so I tried preconnect_completed. Is this the right event?
Also, and part of the reason I'm using XE, is that those servers can get thousands of calls a minute.
Here's what I've come up with thus far, which works but only gives me current SSMS connections that match - obviously, I'll change that to the .Net SQLClient Data Provider.
CREATE EVENT SESSION UnknownAppHosts
ON SERVER
ADD EVENT sqlserver.existing_connection(
ACTION(sqlserver.client_hostname)
WHERE ([sqlserver].[client_app_name] LIKE 'Microsoft SQL Server Management%')
)
ADD TARGET package0.histogram
( SET slots = 50,
filtering_event_name='sqlserver.existing_connection',
source_type=1,
source='sqlserver.client_hostname'
)
WITH(MAX_DISPATCH_LATENCY =1SECONDS);
GO
Aha! It's login, not preconnect_starting or preconnect_completed.
CREATE EVENT SESSION UnknownAppHosts
ON SERVER
ADD EVENT sqlserver.login(
ACTION(sqlserver.client_hostname)
WHERE ([sqlserver].[client_app_name] LIKE 'Microsoft SQL Server Management%')
)
ADD TARGET package0.histogram
( SET slots = 50,
filtering_event_name='sqlserver.login',
source_type=1,
source='sqlserver.client_hostname'
)
WITH(MAX_DISPATCH_LATENCY =1SECONDS);
GO
Then to query it, some awesome code I made horrid:
-- Parse the session data to determine the databases being used.
SELECT slot.value('./#count', 'int') AS [Count] ,
slot.query('./value').value('.', 'varchar(20)')
FROM
(
SELECT CAST(target_data AS XML) AS target_data
FROM sys.dm_xe_session_targets AS t
INNER JOIN sys.dm_xe_sessions AS s
ON t.event_session_address = s.address
WHERE s.name = 'UnknownAppHosts'
AND t.target_name = 'Histogram') AS tgt(target_data)
CROSS APPLY target_data.nodes('/HistogramTarget/Slot') AS bucket(slot)
ORDER BY slot.value('./#count', 'int') DESC