Auditing SQL Server SQL Statements
“谁把我的表给删拉”,”谁删了整个表阿”…碰到这种棘手的情况,你如果没有预先做好准备,真的是头都要急炸了。那怎么能抓出这个”凶手”呢?SQL Trace, SQL Profile,SQL Trigger,Extended Events等着伺候你呢,更别说CLR,Service Broker等重量级武器了,别急!
工具虽好,但是也得用得贴合场景才能发挥作用,要不然跟你的SQL Server抢IO,那就得不偿失了。比如高频的OLTP场合,你还用TRIGGER把大量的DML语句都写到当前数据库去,那不是给数据库增加一倍工作量么。当然控制好权限,做好测试也能保证你的数据安全。这不妨碍我们讨论auditing SQL。
SQL Profiler是基于SQL Trace的,而SQL Trace是会被更高版本的SQL Server给逐渐摒弃的,所以我们就只讨论一个就可以了。一开始我知道 SQL Profiler是可以可视化监控即时的SQL Server活动的,但是缺点是不能保存或者自动执行,需要人工干预。经过研究,它是可以自动保存截取结果的。
让我们认识下“源”:想要抓“破坏分子”,首先要知道“破环分子”的标示有哪些,漏抓,错抓,都是失手的表现。访问SQL SERVER的方式有很多种,有ADO.NET, JDBC, SQL SERVER Management Studio, ODBC等各种方法,也有 Ad-hoc SQL, Stored Procedure等表现形式,是否每一种的方式都有各自不同的格式呢?最好的方法就是针对每种方式都来做个例子验证下。
首先最简单的SSMS方式,我们将SQL Profiler限制到某一个数据库,lenistest4。 在SSMS里面输入:
use lenistest4go
SQL Profiler显示的是SQL:BatchCompleted。
这里与有没有go无关。当你选中一块SQL区域并执行,其中如果有go那就有关系了,比如:
select top 10 * from sys.tablesgoselect top 10 * from dbo.regiongo
这里一个go分割了一个batch。最后一个go没有意义,我们提交了一段代码,这段代码相当于是一个大batch,如果中间有go,那这个go 就代表了一个子batch。
那么用动态语句,会有什么Trace格式呢:
declare @sqlstatement nvarchar(max) = N'select top 10 * from dbo.region' ;exec sp_executesql @sqlstatement
这里有SQL:Batch*, SQL:Stmt*,SP:Stmt, SQL:Stmt*代表的是一系列的SQL命令,比如declare, set等;SP:Stmt*代表了stored procedure的范围内语句。
declare @sqlstatement nvarchar(max) = N'declare @regionName varchar(20) = ''China''select top 10 * from dbo.regionwhere regionName = @regionName' ;exec sp_executesql @sqlstatement
上面这段SQL,验证了SQL命令select和declare是不是都被看作是SP:Stmt* ? 其实在一个batch里面,SQL命令里面DML语句也是被当作Statement来处理的。
如果在动态SQL里面有go是不是也会有SP:Batch*? 我们接着往下看:
declare @sqlstatement nvarchar(max) = N'declare @regionName varchar(20) = ''China''select top 10 * from dbo.regionwhere regionName = @regionName;godeclare @regionName2 varchar(20) = ''England''select top 10 * from dbo.regionwhere regionName = @regionName2' ;exec sp_executesql @sqlstatement
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ‘go’.
可以看到go是不能用在动态语句里面的。
为了验证SP:Stmt*是不是指的是存储过程里面的语句,我们先创建一个stored procedure,然后再执行它:
create procedure dbo.getRegionNameasbegindeclare @regionName varchar(20) = 'China'select top 10 * from dbo.regionwhere regionName = @regionNamedeclare @regionNamex varchar(20) = 'England'select top 10 * from dbo.regionwhere regionName = @regionNamexendexec dbo.getRegionName
正是如此 !综上所述, SQL:Batch* , 这里的batch相当于是个scope,一个大的执行空间,里面的所有 SQL 语句都是statement,包括DML,DDL等一系列 T-SQL语句 ;而SP:Stmt*又是存储过程的执行空间,里面所有的 T-SQL语句都是statement。
下面看段c#调用这个stored procedure,看看trace是如何识别的:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Data.SqlClient;using System.Data.SqlTypes;using System.Data;namespace AccessLenistest4DB{class Program{static void Main(string[] args){SqlConnection ICONN = new SqlConnection(@"data source = (localhost);initial catalog = lenistest4 ;user id = sa; password = sas;");SqlCommand icmd = new SqlCommand();icmd.Connection = ICONN;icmd.CommandType = System.Data.CommandType.StoredProcedure;icmd.CommandText = "dbo.getRegionName";SqlDataAdapter ida = new SqlDataAdapter(icmd);DataSet localds = new DataSet();try{ICONN.Open();ida.Fill(localds);}catch(SqlException se){Console.Write(se.ToString());}}}}
这儿多了个RPC, remote procedure call。其他都一样,所以RPC可以看作是一种命名空间,用阿里区别访问协议。这里要区别的是我们调用的是stored procedure,所以会RPC。所以如果我们是用纯SQL来访问数据库,那会不会有 RPC标示呢:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Data.SqlClient;using System.Data.SqlTypes;using System.Data;namespace AccessLenistest4DB{class Program{static void Main(string[] args){SqlConnection ICONN = new SqlConnection(@"data source = (localhost);initial catalog = lenistest4 ;user id = sa; password = sas;");SqlCommand icmd = new SqlCommand();icmd.Connection = ICONN;icmd.CommandType = System.Data.CommandType.Text;icmd.CommandText = "select * from dbo.region";SqlDataAdapter ida = new SqlDataAdapter(icmd);DataSet localds = new DataSet();try{ICONN.Open();ida.Fill(localds);}catch(SqlException se){Console.Write(se.ToString());}}}}
并没有RPC。 事实证明 RPC只出现在客户端语言调用存储过程的例子。
Trace的手段 :“破坏分子”的特征被识别了,接下来就是怎么去抓捕的手段问题了。可以有即时的GUI工具,比如SQL Profiler,Extended Event(SSMS自带),也可以用脚本去抓,并放在特定存储里面供稍后分析使用。
SQL Profiler 是即时的GUI工具很好用,可以保存结果,也可以自定义模板,缺点在于你必须开一个额外的窗口去跟踪,有时候数据量太大,还会影响传输,对多太SQL Server做监控就不怎么容易了,一个一个手工去开窗口,是不是很麻烦 ?
这里有Extended Events可以帮我们用脚本的形式去捕捉这些T-SQL语句,这里有个简单的例子:
- 通过 Extended Events ,我们可以监控一段时间内的的 SQL Completed 情况,简要介绍下:
1.1 Extended Events 概念:由一系列自动触发的 event 产生性能数据,经过 event engine 的收集,存放到指定的输出文件,以供后续的分析。
1.2 XE 涉及到的动态管理试图 : sys.dm_xe_packages; sys.dm_xe_objects;sys.dm_xe_sessions
1.3 基本用法:
2.3.1 创建一个 Event Session
create event session capture_sql_eventson serveradd event sqlserver.sql_statement_completed(action(sqlserver.sql_text))add target package0.event_file(set filename = 'E:\data_bu\capture_sql_events.xel', metadatafile = 'E:\data_bu\capture_sql_event.xem')go
2.3.2 启用这个 Event session 来收集数据
alter event session capture_sql_eventson serverSTATE = startgo
2.3.3 停用这个 Event session
alter event session capture_sql_eventson serverstate = stopgo
2.3.4 修改一个 session 来增加或者删除对 Event 的监控
alter event session capture_sql_events on serveradd event sqlserver.sql_batch_completed (action(sqlserver.sql_text))go
2.3.5 查看正在运行的 Event Session
select * from sys.dm_xe_sessionsselect * from sys.dm_xe_session_events
2.3.6 查看收集到的统计数据
select top 10 * from dbo.regiongoselect * , cast(event_data as xml) as event_data_xmlfrom sys.fn_xe_file_target_read_file('E:\data_bu\capture_sql_events*.xel',null,null,null)where event_data like N'%region%'
从结果集我们可以看到,sql_statement_completed这个Event抓到的结果中,包含了Action中我们指定的内容,还包含了其他的一些统计信息:
<event name="sql_statement_completed" package="sqlserver" timestamp="2016-05-06T03:29:48.868Z"><data name="duration"><value>0</value></data><data name="cpu_time"><value>0</value></data><data name="physical_reads"><value>0</value></data><data name="logical_reads"><value>2</value></data><data name="writes"><value>0</value></data><data name="row_count"><value>6</value></data><data name="last_row_count"><value>6</value></data><data name="line_number"><value>1</value></data><data name="offset"><value>0</value></data><data name="offset_end"><value>62</value></data><data name="statement"><value>select top 10 * from dbo.region</value></data><data name="parameterized_plan_handle"><value /></data><action name="sql_text" package="sqlserver"><value>select top 10 * from dbo.region</value></action></event>
我们在Action里面加入对database_name,和plan_handle的捕捉,可以从结果看到又多出来两个元素:
create event session capture_sql_eventson serveradd event sqlserver.sql_statement_completed(action(sqlserver.sql_text,sqlserver.database_name,sqlserver.plan_handle))add target package0.event_file(set filename = 'E:\data_bu\capture_sql_events.xel', metadatafile = 'E:\data_bu\capture_sql_event.xem')
<event name="sql_statement_completed" package="sqlserver" timestamp="2016-05-06T03:52:02.524Z"><data name="duration"><value>0</value></data><data name="cpu_time"><value>0</value></data><data name="physical_reads"><value>0</value></data><data name="logical_reads"><value>2</value></data><data name="writes"><value>0</value></data><data name="row_count"><value>6</value></data><data name="last_row_count"><value>6</value></data><data name="line_number"><value>1</value></data><data name="offset"><value>0</value></data><data name="offset_end"><value>62</value></data><data name="statement"><value>select top 10 * from dbo.region</value></data><data name="parameterized_plan_handle"><value /></data><action name="plan_handle" package="sqlserver"><value>06002000448a700f00d62b7a0300000001000000000000000000000000000000000000000000000000000000</value></action><action name="database_name" package="sqlserver"><value>lenistest4</value></action><action name="sql_text" package="sqlserver"><value>select top 10 * from dbo.region</value></action></event>
欢迎关注个人微信公众号
Auditing SQL Server SQL Statements相关推荐
- 从sqlserver中数据写入mysql_[SQL Server]SQL Server数据库中如何返回INSERT INTO语句插入/写入数据后的记录值(比如ID等)?...
问题描述 SQL Server数据库中,有时候当我们使用INSERT INTO语句写入数据后,需要返回写入数据对应的自增ID或者GUID,以便根据此记录进行后续的操作.那么SQL语句如何实现返回记录值 ...
- SQL Server -- SQL NULL值,ISNull(),Oracal NVL(),MYSQL IFNULL(),COALESCE()
From: http://www.w3school.com.cn/sql/sql_isnull.asp SQL ISNULL().NVL().IFNULL() 和 COALESCE() 函数 请看下面 ...
- SQL Server SQL高级查询语句小结(转)
--select select * from student; --all 查询所有 select all sex from student; --distinct 过滤重复 select disti ...
- SQL Server - SQL Server 2016新特性之 --- Query Store
前言 SQL Server 2016引入新的查询语句性能监控.调试和优化工具/功能 -- Query Store.以前我们发现一条查询语句性能突然下降,我们要去找出问题的所在往往需要通过调用一些DMV ...
- oracle sequence sql server,SQL Server 实现oracle的sequence方法示例
这篇文章主要为大家详细介绍了SQL Server 实现oracle的sequence方法示例,具有一定的参考价值,可以用来参考一下. 感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! 当然 ...
- SQL Server - sql 空间数据
以geometry为例,geography类似 目录 基础功能 创建空间表 录入数据 计算面积 转WKB 转WKT 转地理标记语言 (GML) 创建geometry实例 获得集合中的实例 STPoin ...
- .NET编程和SQL Server ——Sql Server 与CLR集成
一.SQL Server 为什么要与CLR集成 1. SQL Server 提供的存储过程.函数等十分有限,经常需要外部的代码来执行一些繁重的移植: 2.与CLR集成可将原本需要独立的程序来实现的功能 ...
- Sql Server sql语句中发送电子邮件
SQL Server 并没有内置邮件服务器(Mail Server),它跟我们发送邮件一样,需要用户名和密码通过 SMTP(Simple Message Transfer Protocol)去连接邮件 ...
- 【SQL】Sql Server SQL语句学习
文章目录 1. 什么是SQL 2. 关系模型 2.1 主键 2.2 外键 2.3 索引 3. DDL操作 3.1 对库操作 3.2 对表操作 3.2.1 创建和删除表 3.2.2 添加约束 3.2.3 ...
- SQL Server 2012学习笔记 (三) ----- SQL Server SQL语句
在很多情况下,可以用CREATE TABLE语句创建数据表.使用ALTER TABLE语句修改表结构.使用DROP TABLE语句删除表: 可以使用CREATE DATABASE创建数据库.A ...
最新文章
- windows 64位 dll文件 位置及python包rtree shapely安装
- hicharts Linux服务器导出,中文字体问题
- Grpc C# 入门
- 部委调研互联网金融企业 内部风控指引或出台
- mongodb 3.4 安装_Python数据分析及可视化实例之CentOS7.2+MongoDB V3.4 安装
- 关于编译器的一个疑问
- Opencv 图片 读取,显示,保存基本操作
- winxp制作服务器,你要知道的WinXP服务器操作系统安装的方法
- select count(1)什么意思_Python VS MySQL,我发现了select和print之间的“相通点”!
- php 修改服务器ip,php 修改服务器ip
- Matlab图形窗口大小的控制 ,plot窗口大小,figure大小,axis设置
- 计算机桌面小工具软件,win10桌面小工具(Desktop Gadgets Installer)
- 腕能助手android9,腕间应用助手(com.gmf.watchapkassistant) - 1.7 - 应用 - 酷安
- 2022-2028全球与中国真空探针台市场现状及未来发展趋势
- Java类加载机制--类加载过程(解析)
- 网络营销实战密码——策略、技巧、案例(修订版)
- 使用IntelliJ IDEA自动生成serialVersionUID
- jquery选择器可以利用后代和直系后代选择器连续选择元素
- Magic Leap 价值 20 多亿美元的 AR 幻梦,现在醒了
- 你上面写的代码用什么编程软件?
热门文章
- TscanCode代码扫描工具
- 洗内衣、白鞋、羊毛衫……需要专用清洁剂吗
- id在python中是什么意思_Python中的id函数是什么意思
- matlab怎么计算行列式,MATLAB计算行列式
- Android 9.0 USER_ROTATION重启后恢复默认值
- Error connecting to database: Access denied for user ‘zabbix‘@‘locahost‘
- 读周爱民《javascript语言精髓与编程实践》有感
- 机器学习笔记之R语言基础5(T,F检验)
- “Defaulting to user installation because normal site-packages is not writeable“
- HDLCPPP原理与配置