我有一个关于事务日志(我们简称为 LDF)内容的问题。我假设一个具有完整恢复模型的数据库。
我已经读过 LDF 文件包含(记录)对数据库的每个操作(即处于完全恢复模式)。它与记录期间有什么不同BEGIN TRAN; COMMAND(s); COMMIT
?我问是因为显然您可以回滚事务,但不能回滚标准命令(在完全恢复模式下)。
我猜在事务期间记录到 LDF 文件中的内容与常规完整恢复日志记录中的内容不同。那正确吗?有什么不同?是否只包含每个动作的“撤消”操作?
在相关说明中,我听说有一些商业工具可以使用完整的恢复 LDF 文件“回滚/撤消”标准查询。他们是怎么做到的呢?他们是否分析 LDF 内容并尝试提出逆/撤消操作?
我找不到创建时命令必须是查询批处理中的第一条语句的对象类型列表。到目前为止,我发现 function/stored_procedure/view 必须是第一个。
有谁知道为什么需要这样做?我确定有一个很好的理由,但它逃脱了我。想到存储过程的唯一原因是过程结束后对代码的奇怪解释。当 SP 被调用时,SQL 服务器仍然执行代码,如果有更多的 CREATE STATEMENTS 结果会一团糟。
背景:我正在尝试创建创建/删除/禁用/启用等脚本,并且需要知道在执行之前将什么放入动态 exec() 中。是的,我可能会将所有语句都包装在 exec() 中,但是我不会学到任何东西。
我有一个关于如何在运行查询的 SQL Server 2008 R2(标准版)中调试非常奇怪的行为(嵌套查询卡住)的问题。
有时(不幸的是并非总是如此)当我运行一个复杂的过程来执行一些数据转换时,涉及:
-- Update of statistics.
EXEC sp_updatestats;
-- Run of another procedure with single complex query
-- procedure declared with recompile.
EXEC usp_query_procedure;
Run Code Online (Sandbox Code Playgroud)
我遇到了这个过程没有完成的问题(典型的时间 < 1 秒,当卡住时,运行时间可能是几天,还没有完成)。
如果我取出查询文本并单独运行它,它会在一秒钟内完成,但如果我在程序中运行它,它就会卡住。
当这些症状开始我没有任何WITH RECOMPILE
或sp_updatestats
。我搜索了一下,发现可能会使用缓存的错误执行计划(对于某些输入参数),并且重新编译会有所帮助(前提是统计信息已更新)。虽然这两个选项似乎减轻了这个问题(它发生的频率较低),但它确实没有完全消失。为什么它在所有情况下都没有帮助?还有什么可能导致这个问题?
当该过程“卡住”并且我附加了一个 SQL Profiler 时,我可以看到每个刷新滴答声的数千个锁定 acuqires/释放。当查询正常运行时,只有一小部分已使用的锁,但这可能很明显。
同样非常奇怪的是,这种情况只发生在运行相同应用程序(标准版/企业版混合版)的四台服务器中的一台(标准版)上。
我该如何进一步调试?我应该登录探查器的哪些事件才能查看导致问题的原因?这里的其他人有没有发生过类似的事情?
请甚至暗示谷歌什么,寻找什么,追踪什么可以导致解决方案。如果我设法解决了这个问题,我一定会在这里发布我的发现以供后代使用。
我有一个关于交易如何运作的理论,但如果可能的话,我希望有人可以验证它或纠正一些观点。假设我们有一个具有完整恢复模型的数据库。
现在,发生在数据库上的所有事情都首先记录到事务日志中,在到达检查点后写入磁盘。
如果我在一个显式事务中,对数据库的所有更改都会首先写入日志,但在检查点期间未提交的事务不会传播到磁盘。
如果我决定回滚事务,只需删除所有事务日志条目即可完成回滚。
如果我提交,则在下一个检查点更改后写入磁盘。
事务日志包含有关如何重做操作的说明,而不是如何撤消操作的说明,这就是为什么只能从基线备份向前恢复到时间点,而不能向后恢复的原因。
它可以从一些操作及其关于如何撤消它的重做指令中推导出来(但不是全部)。这就是商用工具如何使用事务日志恢复完整恢复模型数据库中的数据。
我的所有观点至少在某种程度上有效吗?有人可以发表评论吗?这是我关于探索事务和事务日志如何在 SQL Server 中工作的第三个也是最后一个问题。谢谢。
编辑:
简单的测试似乎反驳了我的理论,因为即使在插入 1000000 行的事务中(数据库没有其他任何内容),SQL Server 似乎也会写入主数据文件。我感到困惑和悲伤:)
正如标题中所述,我想知道为什么以下代码段会记录失败并显示重复键错误。作为以下测试的结果,很明显,更新不会在每一行之后检查重复性。里面会发生什么?这只是 SQL Server 特定行为的标准的一部分吗?谢谢!
DECLARE @T TABLE(
x INT PRIMARY KEY
);
INSERT INTO @T VALUES (1)
INSERT INTO @T VALUES (2)
UPDATE @T SET x = x + 1;
-- DUPLICATE KEY ERROR EXPECTED.
SELECT * FROM @T;
--- VALUES HAVE BEEN INCREMENTED. NO ERROR THROWN.
Run Code Online (Sandbox Code Playgroud) 假设我有一个 Web 应用程序,它允许用户输入 SQL 查询(SQL Server 2008+)。我希望用户能够运行任何 SELECT 查询并读取数据库中的任何内容,但我不希望他们能够插入/更新/删除/截断/执行等(简而言之:仅选择)。请注意,整个数据库中没有数据甚至数据库元数据被视为机密。
目前的规则:
这够了吗?除了选择之外,还有什么办法可以做吗?
编辑:谢谢 Thomas Stringer 关于 SELECT ... INSERT 的说明。这正是我所追求的信息。我将从查询字符串中删除所有换行符,这应该有助于解决这个问题。有没有其他方法可以解决这个问题并能够修改数据?
注意:CTE 与这种情况无关。让我们假设查询必须以 SELECT 开头。
我有两个问题。我有一个处于完全恢复模式的数据库。让我们将事务日志简称为 LDF 文件。
SQL Server 允许我在从数据库恢复到自身时恢复到过去的时间点。这甚至有意义吗?当我尝试它没有产生预期的结果。如果它不起作用,为什么甚至允许这样做?它有什么实际用途吗?
在玩 LDF 文件时,我发现了一个好奇心:考虑在简单模式下使用数据库。然后我将其切换到完全恢复模式。然后我在数据库中插入了一些 10000 行,检查 LDF 并发现 LDF 文件大小没有增加。当我进行完整备份然后再次将 10000 行插入数据库时,LDF 文件才会增加。这是某种优化吗?注意:我在两次操作之前都缩小了 LDF 文件。
感谢所有的解释。