解释一下SQLSERVER事务日志记录
解释一下SQLSERVER事务日志记录
大家知道在完整恢复模式下,SQLSERVER会记录每个事务所做的操作,这些记录会存储在事务日志里,有些软件会利用事务日志来读取
操作记录恢复数据,例如:log explorer
那么事务日志记录怎麽查看,里面都记录了些什么?
打开可以利用下面SQL语句来查看所在数据库的事务日志记录
USE [GPOSDB] --要查看事务日志记录的数据库
GO
SELECT * FROM [sys].[fn_dblog](NULL,NULL)
事务日志记录里很多东西可以看的,里面记录了非常详细的数据库活动信息
我这里只介绍一些重要的需要知道的字段,其他字段由于本人能力有限而且觉得其他字段不是很重要就不介绍了
CurrentLSN:当前LSN号,事务日志中的每个记录都由一个唯一的日志序列号 (LSN) 标识。LSN 是这样排序的:如果 LSN2 大于 LSN1,
则 LSN2 所标识的日志记录描述的更改发生在日志记录 LSN1 描述的更改之后
MSDN解释:http://msdn.microsoft.com/zh-cn/library/ms190411(v=SQL.90).aspx
Operation:当前LSN所做的操作
Context:操作的上下文
TransactoinID:事务ID号
Log Record Fixed Length:LSN记录的所占虚拟日志文件的固定长度
Previous LSN:前一个LSN号
--------------------------------------------------------------------------------------------------------------
AllocUnitID:修改的那条数据所属分配单元ID
AllocUnitName:修改了数据的表名
Page ID:0001:00000121 转换成十进制:289 所以查看pageid为289页 DBCC PAGE([pratice],1,289,3)
Slot ID:数据所在数据页面的第几条记录
PartitionID:数据所在数据页面的所在分区ID
如上图,修改数据的表名是Insert_Test,Page ID是0001:00000121 转换为十进制为289 Slot ID是6(即数据页的第6条记录)
通过下面SQL语句就可以查看页面所在数据
USE [pratice]
GO
DBCC TRACEON(3604,-1)
GO DBCC PAGE([pratice],1,289,3)
GO
Slot 6 Offset 0x552 Length 211 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
Memory Dump @0x0A2AC552 00000000: 1000d000 3f080000 61616120 20202020 †....?...aaa
00000010: 20202020 20202020 20202020 20202020 †
00000020: 20202020 20202020 20202020 20202020 †
00000030: 20202020 20202020 20202020 20202020 †
00000040: 20202020 20202020 20202020 20202020 †
00000050: 20202020 20202020 20202020 20202020 †
00000060: 20202020 20202020 20202020 20202020 †
00000070: 20202020 20202020 20202020 20202020 †
00000080: 20202020 20202020 20202020 20202020 †
00000090: 20202020 20202020 20202020 20202020 †
000000A0: 20202020 20202020 20202020 20202020 †
000000B0: 20202020 20202020 20202020 20202020 †
000000C0: 20202020 20202020 20202020 20202020 †
000000D0: 0200fc†††††††††††††††††††††††††††††††... Slot 6 Column 0 Offset 0x4 Length 4 id = 2111 Slot 6 Column 1 Offset 0x8 Length 200 name = aaa
这个表只有两个字段,我们看一下表数据
--------------------------------------------------------------------------------------------------------
Checkpoint Begin:Checkpoint开始时间
Checkpoint Begin DB Version:当前数据库版本 SQL2005是611 SQL2012是706
Checkpoint End:checkpoint的结束时间,这个时间肯定在Checkpoint Begin的下一条事务日志记录的位置
Minimum LSN: 这个第一个日志记录的日志序列号 (LSN),称为最小恢复 LSN (MinLSN)
Dirty Pages:脏的数据页
Oldest Replicated Begin LSN:如果数据库配置复制的话,那么最老的复制起始LSN
Next Replicated End LSN:下一个复制结尾LSN
Last Distributed End LSN:最新的分发结尾LSN
SPID:执行当前操作的进程ID
Beginlog Status:开始记录事务日志的状态,这个状态表示现时能够正常记录事务日志
Begin Time:事务开始时间
Transaction Name:事务名称
End Time:事务结束时间
Transaction Begin:记录这个事务的begin transaction的时候的cureent LSN
Master DBID:显示当前master数据库的DBID
Preplog Begin LSN:启动数据库前的前一个事务日志LSN
Prepare Time:准备启动数据库的时间
New Split Page:哪个数据页产生了页拆分
Rows Deleted:数据页有多少行被删除了
Description:描述这个事务是干什么的,有时候事务名称不一定就是他所做的操作名称,
比如这里碰巧事务名和描述都是CREATE TABLE 如果你为这个事务命名的话,那么只能看Description列看这个事务是做什么的
-------------------------------------------------华丽的分割线-------------------------------------------------------------------
现在解释一下 一些常见operation和context,一些不常见的我也不知道 ,呵呵o(∩_∩)o
Operation:当前LSN所做的操作
Context:操作的上下文
DCM页的资料:http://www.cnblogs.com/lyhabc/archive/2013/01/21/2870392.html
Operation |
Context |
解释 |
LOP_SET_BITS |
LCX_DIFF_MAP |
设置位图,资料: 差异(Differential)备份:只备份上次完整备份后,做修改的部分。备份单位是区(Extent)。意味着某个区内即使只有一页做了变动,则在差异备份里会被体现.差异备份依靠一个BitMap进行维护,一个Bit对应一个区,自上次完整备份后,被修改的区会被置为1,而BitMap中被置为1对应的区会被差异备份所备份。而到下一次完整备份后,BitMap中所有的Bit都会被重置为0 而这个BitMap在数据库第7页: DCM页 差异变更(Differential Changed Map,DCM)页面他跟踪一个文件中的哪一个区在最新一次完整数据库备份之后被修改过。SQLSERVER用在增量备份时只对已发生数据变更的分区进行增量备份即可 |
LOP_BEGIN_XACT |
事务开始 |
|
LOP_MODIFY_ROW |
LCX_HEAP |
修改堆表中的某一行记录 |
LOP_PREP_XACT |
准备启动数据库 |
|
LOP_COMMIT_XACT |
提交事务 |
|
LOP_MODIFY_ROW |
LCX_BOOT_PAGE |
修改数据库启动页 |
LOP_MODIFY_HEADER |
LCX_PFS |
修改PFS页的页头部信息 |
LOP_INSERT_ROWS |
LCX_CLUSTERED |
插入数据到聚集索引的索引页 |
LOP_INSERT_ROWS |
LCX_INDEX_LEAF |
插入数据到索引的叶子节点即数据页 |
LOP_FORMAT_PAGE |
LCX_CLUSTERED |
重新组织聚集索引 |
LOP_DELETE_SPLIT |
LCX_CLUSTERED |
删除聚集索引表的一行记录引起页拆分 |
LOP_MODIFY_HEADER |
LCX_HEAP |
修改堆表的某页的页头信息 |
LOP_BEGIN_CKPT |
LCX_NULL |
检查点开始 |
LOP_END_CKPT |
LCX_NULL |
检查点结束 |
LOP_SET_FREE_SPACE |
LCX_PFS |
修改PFS页设置那个数据页是空闲的 |
LOP_ROOT_CHANGE |
LCX_CLUSTERED |
聚集索引的根节点改变 |
LOP_INSERT_ROWS |
LCX_HEAP |
插入数据到堆表 |
LOP_FORMAT_PAGE |
LCX_HEAP |
格式化堆里的数据页 |
Operation |
Lock Information |
解释 |
LOP_LOCK_XACT |
HoBt 0:ACQUIRE_LOCK_SCH_M METADATA: database_id = 14 STATS(object_id = 7, stats_id = 11) |
在事务里获取锁 |
-------------------------------------------------------华丽的分割线---------------------------------------------------
在大容量日志恢复模式下,在事务日志记录里你会看不到对数据页的操作,当你使用bcp ,bulk inert, select into大容量操作语句的时候
像下图的那样修改数据和插入数据的记录你在事务日志记录里找不到的
所以大容量日志恢复模式时,ldf文件才这麽小,插入速度才这麽快
下面引用MSDN:
http://msdn.microsoft.com/zh-cn/library/ms190925.aspx
可以尽量减少日志量的操作
“最小日志记录”是指只记录在不支持时间点恢复的情况下恢复事务所需的信息。 本主题介绍在大容量日志恢复模式下(以及简单恢复模式下)按最小方式记录、但在运行备份时例外的操作。
注意
在完整恢复模式下,所有大容量操作都将被完整地记录下来。 但是,可以通过将数据库暂时切换到用于大容量操作的大容量日志恢复模式,最小化一组大容量操作的日志记录。 最小日志记录比完整日志记录更为有效,并在大容量事务期间,降低了大规模大容量操作填满可用的事务日志空间的可能性。 不过,如果在最小日志记录生效时数据库损坏或丢失,则无法将数据库恢复到故障点。
下列操作在完整恢复模式下执行完整日志记录,而在简单和大容量日志恢复模式下按最小方式记录:
大容量导入操作(bcp、BULK INSERT 和 INSERT...SELECT)。 有关在何时对大容量导入表按最小方式进行记录的详细信息,请参阅在大容量导入中按最小方式记录日志的前提条件。
注意
启用事务复制时,将完全记录 BULK INSERT 操作,即使处于大容量日志恢复模式下。
SELECT INTO 操作。
注意
启用事务复制时,将完全记录 SELECT INTO 操作,即使处于大容量日志恢复模式下。
插入或追加新数据时,使用 UPDATE 语句中的 .WRITE 子句部分更新到大型值数据类型。 注意,在更新现有值时没有使用最小日志记录。 有关大型值数据类型的详细信息,请参阅数据类型 (Transact-SQL)。
在 text、ntext 和 image 数据类型列中插入或追加新数据时的 WRITETEXT 和 UPDATETEXT 语句。 注意,在更新现有值时没有使用最小日志记录。
注意
不推荐使用 WRITETEXT 语句和 UPDATETEXT 语句,因此应该避免在新的应用程序中使用这些语句。
如果数据库设置为简单或大容量日志恢复模式,则无论是脱机还是联机执行操作,都会按最小方式记录一些索引 DDL 操作。 按最小方式记录的索引操作如下:
CREATE INDEX 操作(包括索引视图)。
ALTER INDEX REBUILD 或 DBCC DBREINDEX 操作。
注意
不推荐使用 DBCC DBREINDEX 语句,因此应该避免在新的应用程序中使用该语句。
DROP INDEX 新堆重新生成(如果适用)。
注意
DROP INDEX 操作期间将始终完整记录索引页的释放操作。
还可以看一下这篇帖子,关于大容量日志恢复模式
http://social.msdn.microsoft.com/Forums/zh-CN/958febc2-5eaf-46e4-b658-4bea087c0b0f
0
投票
另外,做了下测试。 在Bulk logged模式下,日志中仅记录对Page(比如IAM,PFS和GAM)的操作,没有记录数据。。 Operation Context AllocUnitName
LOP_MODIFY_ROW LCX_PFS dbo.SomeTable
LOP_SET_BITS LCX_IAM dbo.SomeTable
LOP_SET_BITS LCX_GAM dbo.SomeTable
LOP_MODIFY_ROW LCX_PFS dbo.SomeTable
LOP_SET_BITS LCX_IAM dbo.SomeTable
LOP_SET_BITS LCX_GAM dbo.SomeTable
LOP_MODIFY_ROW LCX_PFS dbo.SomeTable
LOP_SET_BITS LCX_IAM dbo.SomeTable
但是对于处于Full模式下的DB,除了包含这部分数据,还有记录Data的部分。 那处于Bulk Logged模式下,所做的事务日志备份,是怎么抓取到数据变化的呢? 我做了实验,处于Bulk logged模式下,执行了事务备份,之后还是可以通过该备份文件来恢复到select * into 操作之后。 select * into ../....from ......这个应该是可以最小化日志的操作吧。
帖子里面说到,不记录事务日志,那么怎麽进行数据库还原呢?实际上通过数据库的系统页BCM页来记录数据页的变更的
参考资料:SQL Server 2008 存储结构之DCM、BCM
BCM页面结构
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 PAGE: (1:7) BUFFER: BUF @0x03EDB9F4 bpage = 0x170E4000 bhash = 0x00000000 bpageno = (1:7)
bdbid = 5 breferences = 1 bUse1 = 14098
bstat = 0xc00009 blog = 0x32159 bnext = 0x00000000 PAGE HEADER: Page @0x170E4000 m_pageId = (1:7) m_headerVersion = 1 m_type = 17
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x0
m_objId (AllocUnitId.idObj) = 99 m_indexId (AllocUnitId.idInd) = 0 Metadata: AllocUnitId = 6488064
Metadata: PartitionId = 0 Metadata: IndexId = 0 Metadata: ObjectId = 99
m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 90
m_slotCnt = 2 m_freeCnt = 6 m_freeData = 8182
m_reservedCnt = 0 m_lsn = (0:0:1) m_xactReserved = 0
m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 0 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = NOT ALLOCATED PFS (1:1) = 0x44 ALLOCATED 100_PCT_FULL
DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED ML_MAP: Header @0x09C2C064 Slot 0, Offset 96 status = 0x0 ML_MAP: Extent Alloc Status @0x09C2C0C2 (1:0) - (1:43256) = NOT MIN_LOGGED DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
----------------------------------------------------华丽的分割线-------------------------------------------------
大家有兴趣可以看一下我写的这篇文章,更加了解事务日志
对SQLSERVER数据库事务日志的疑问
http://www.cnblogs.com/lyhabc/archive/2013/06/10/3130856.html
根据上面事务日志中的这几个字段,LOG EXPLORER软件为什麽能恢复数据生成insert脚本,估计是读取事务日志中删除了数据的数据页id
然后到数据页里先保存下数据,但是如果使用大容量日志恢复模式或者使用truncate table语句估计LOG EXPLORER软件也救不了你
因为delete语句无论是where 删除某条记录还是全表delete应该都会每条记录生成一个事务日志记录,即生成一个LSN
但是大容量日志恢复模式或者使用truncate table语句是不记录每行数据的LSN的,可能只记录删除动作
AllocUnitID:修改的那条数据所属分配单元ID
AllocUnitName:修改了数据的表名
Page ID:数据页ID
Slot ID:数据所在数据页面的第几条记录
PartitionID:数据所在数据页面的所在分区ID
--------------------------------------------------华丽的分割线-------------------------------------------------------
当你备份事务日志并截断日志之后,然后你没有对数据库做任何操作,但是依然会看到有事务日记记录生成
至于原因,由于篇幅关系,大家可以到我的另一篇博文的最下面那个问题,里面有答案
为什麽完整备份之后日志记录会增加,有时候备份完之后会增加,有时候备份完之后会减少???
因为数据库启动的时候一定修改一些系统数据库页所以肯定会有一些事务日志记录生成
文章地址:对SQLSERVER数据库事务日志的疑问
------------------------------------------------------------------------------------------------------
文章有什么不对的地方,大家一定要拍砖哦o(∩_∩)o
解释一下SQLSERVER事务日志记录的更多相关文章
- (转)解释一下SQLSERVER事务日志记录
本文转载自桦仔的博客http://www.cnblogs.com/lyhabc/archive/2013/07/16/3194220.html 解释一下SQLSERVER事务日志记录 大家知道在完整恢 ...
- sqlserver 事务日志过大 收缩方法解决方案
sqlserver 事务日志过大,可能会导致备份失败或者数据库出现异常,所以要定期清除sqlserver 事务日志 建议:为了防止日志文件无限扩大,可以对日志文件作一些限制. 清除sqlserver事 ...
- 内存中OLTP(Hekaton)里的事务日志记录
在今天的文章里,我想详细讨论下内存中OLTP里的事务日志如何写入事务日志.我们都知道,对于你的内存优化表(Memory Optimized Tables),内存中OLTP提供你2个持久性(durabi ...
- sqlserver 事务日志已满解决方案
sqlserver 事务日志已满解决方案 可参考这篇博客: https://www.cnblogs.com/strayromeo/p/6961758.html 一.删除日志文件:(不建议) 二.手动收 ...
- SqlServer 事务日志传输
基本概念 可以使用日志传送将事务日志不间断地从一个数据库(主数据库)发送到另一个数据库(辅助数据库).不间断地备份主数据库中的事务日志,然后将它们复制并还原到辅助数据库,这将使辅助数据库与主数据库基本 ...
- Linux定时器工具-crontab 各參数具体解释及怎样查看日志记录
要使用crontab定时器工具,必需要启动cron服务: service cron start crontab的语法,以备日后救急.先上张超给力的图: crontab各參数说明: -e : 运行文字编 ...
- 收缩sqlserver事务日志
若要允许 DBCC SHRINKFILE 命令收缩文件,首先需要通过将数据库恢复模式设置为 SIMPLE 来截断该文件. 示例,收缩数据库abce的事务日志 USE abce; GO -- Trunc ...
- sqlserver 事务日志
预写式日志(Write-Ahead Logging (WAL)) --在数据写入到数据库之前,先写入到日志. 1.”Begin Tran”记录 -> 缓冲区 2. 日志 ...
- SQLSERVER事务日志已满 the transaction log for database 'xx' is full
解决办法:清除日志 USE [master] GO ALTER DATABASE DNName SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE D ...
随机推荐
- C语言也能干大事1
今天看了个视频,叫C语言也能干大事,写了第一个WIN项目的代码,感觉特别好,就像以前刚刚学会写C语言一样, 然后就恶搞出一个东西,最后的结果就是这个东西退出不了了
- Linux下编译安装python3
Linux下默认系统自带python2.6的版本,这个版本被系统很多程序所依赖,所以不建议删除,如果使用最新的Python3那么我们知道编译安装源码包和系统默认包之间是没有任何影响的,所以可以安装py ...
- hibernate xx(tableName) is not mapped
数据库中表名是:book,数据库表名不区分大小写的 之后我在hibernate 使用book, String sql="from book"; Query query=sessio ...
- TS初探
简介 TypeScript具有类型系统,且是JavaScript的超集.它可以编译成普通的JavaScript代码. TypeScript支持任意浏览器,任意环境,任意系统并且是开源的.Ts主要用于解 ...
- 13. javacript高级程序设计-事件
1. 事件 1.1 事件流 事件流描述的是从页面中接受事件的顺序,IE的事件是冒泡流,而Netscape Communicator的事件流是事件捕捉流. 1.1.1 事件冒泡 <!DOCTYPE ...
- zmqsend for FFmpeg
编译 FFmpeg 时,配置中添加 --enable-libzmq 就可以通过 tcp 通讯给 FFmpeg 发送命令 Usage: zmqsend [-h ip:port] TARGET COMMA ...
- Django~automated tests
def xx(): 冒号下一行要缩进 ATD http://blog.csdn.net/doupei2006/article/details/7657547 http://www.jb51.net/a ...
- [转] Android Volley完全解析(一),初识Volley的基本用法
版权声明:本文出自郭霖的博客,转载必须注明出处. 目录(?)[-] Volley简介 下载Volley StringRequest的用法 JsonRequest的用法 转载请注明出处:http ...
- Effective C++ -----条款38:通过复合塑模出has-a或“根据某物实现出”
复合(composition)的意义和public继承完全不同. 在应用域(application domain),复合意味has-a(有一个).在实现域(implementation domain) ...
- nyoj20_吝啬的国度_DFS
吝啬的国度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市, ...