“谁把我的表给删拉”,”谁删了整个表阿”…碰到这种棘手的情况,你如果没有预先做好准备,真的是头都要急炸了。那怎么能抓出这个”凶手”呢?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语句,这里有个简单的例子:

  1. 通过 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相关推荐

  1. 从sqlserver中数据写入mysql_[SQL Server]SQL Server数据库中如何返回INSERT INTO语句插入/写入数据后的记录值(比如ID等)?...

    问题描述 SQL Server数据库中,有时候当我们使用INSERT INTO语句写入数据后,需要返回写入数据对应的自增ID或者GUID,以便根据此记录进行后续的操作.那么SQL语句如何实现返回记录值 ...

  2. 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() 函数 请看下面 ...

  3. SQL Server SQL高级查询语句小结(转)

    --select select * from student; --all 查询所有 select all sex from student; --distinct 过滤重复 select disti ...

  4. SQL Server - SQL Server 2016新特性之 --- Query Store

    前言 SQL Server 2016引入新的查询语句性能监控.调试和优化工具/功能 -- Query Store.以前我们发现一条查询语句性能突然下降,我们要去找出问题的所在往往需要通过调用一些DMV ...

  5. oracle sequence sql server,SQL Server 实现oracle的sequence方法示例

    这篇文章主要为大家详细介绍了SQL Server 实现oracle的sequence方法示例,具有一定的参考价值,可以用来参考一下. 感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! 当然 ...

  6. SQL Server - sql 空间数据

    以geometry为例,geography类似 目录 基础功能 创建空间表 录入数据 计算面积 转WKB 转WKT 转地理标记语言 (GML) 创建geometry实例 获得集合中的实例 STPoin ...

  7. .NET编程和SQL Server ——Sql Server 与CLR集成

    一.SQL Server 为什么要与CLR集成 1. SQL Server 提供的存储过程.函数等十分有限,经常需要外部的代码来执行一些繁重的移植: 2.与CLR集成可将原本需要独立的程序来实现的功能 ...

  8. Sql Server sql语句中发送电子邮件

    SQL Server 并没有内置邮件服务器(Mail Server),它跟我们发送邮件一样,需要用户名和密码通过 SMTP(Simple Message Transfer Protocol)去连接邮件 ...

  9. 【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 ...

  10. SQL Server 2012学习笔记 (三) ----- SQL Server SQL语句

      在很多情况下,可以用CREATE TABLE语句创建数据表.使用ALTER TABLE语句修改表结构.使用DROP TABLE语句删除表:   可以使用CREATE DATABASE创建数据库.A ...

最新文章

  1. windows 64位 dll文件 位置及python包rtree shapely安装
  2. hicharts Linux服务器导出,中文字体问题
  3. Grpc C# 入门
  4. 部委调研互联网金融企业 内部风控指引或出台
  5. mongodb 3.4 安装_Python数据分析及可视化实例之CentOS7.2+MongoDB V3.4 安装
  6. 关于编译器的一个疑问
  7. Opencv 图片 读取,显示,保存基本操作
  8. winxp制作服务器,你要知道的WinXP服务器操作系统安装的方法
  9. select count(1)什么意思_Python VS MySQL,我发现了select和print之间的“相通点”!
  10. php 修改服务器ip,php 修改服务器ip
  11. Matlab图形窗口大小的控制 ,plot窗口大小,figure大小,axis设置
  12. 计算机桌面小工具软件,win10桌面小工具(Desktop Gadgets Installer)
  13. 腕能助手android9,腕间应用助手(com.gmf.watchapkassistant) - 1.7 - 应用 - 酷安
  14. 2022-2028全球与中国真空探针台市场现状及未来发展趋势
  15. Java类加载机制--类加载过程(解析)
  16. 网络营销实战密码——策略、技巧、案例(修订版)
  17. 使用IntelliJ IDEA自动生成serialVersionUID
  18. jquery选择器可以利用后代和直系后代选择器连续选择元素
  19. Magic Leap 价值 20 多亿美元的 AR 幻梦,现在醒了
  20. 你上面写的代码用什么编程软件?

热门文章

  1. TscanCode代码扫描工具
  2. 洗内衣、白鞋、羊毛衫……需要专用清洁剂吗
  3. id在python中是什么意思_Python中的id函数是什么意思
  4. matlab怎么计算行列式,MATLAB计算行列式
  5. Android 9.0 USER_ROTATION重启后恢复默认值
  6. Error connecting to database: Access denied for user ‘zabbix‘@‘locahost‘
  7. 读周爱民《javascript语言精髓与编程实践》有感
  8. 机器学习笔记之R语言基础5(T,F检验)
  9. “Defaulting to user installation because normal site-packages is not writeable“
  10. HDLCPPP原理与配置