如果您将隔离级别读取为“已提交”,它将仅返回事务日志已“提交”的结果。因此,如果您在该时间点启动处于“已提交”隔离级别的查询,则 sql 事务日志只会为您提供已发布到其日志的已提交事务。如果在选择过程中有人发布记录,他们将在那个时间点被视为“未提交”,直到他们结束操作并被“提交”。但是,即使您将级别更改为“未提交”,您也不应该获得处于中间流中的数据,您应该根据事务日志在开始操作时获得引擎可用的内容。
已提交与未提交将在选择时根据您的选择在系统中获取记录。因此,如果我说 3,000,000 条记录和 200,000 条记录插入,但他们一次提交一个,只有 100,000 条已提交,100,000 条知道日志中的操作但尚未提交。
已提交将给我 3,100,000,而未提交将给我 3,200,000。但是有一些思想流派,我昨天刚刚与某人讨论过这个......未提交会给您未提交的结果,并且被称为“脏读”,因为您正在阅读尚未设置的日志(您反叛)。您是在说“嘿,数据库,我不在乎您收到的已最终确定的内容,我现在就想要。” 当您说已提交时,您是在说:“数据库我只想要合格的数据,如果某些事情没有最终确定,我不想要它。”
各有优势:
未提交的你不会锁定任何东西。你基本上是在对系统说:“不要锁定任何东西,让我通过系统自由地获取那里的东西,我不在乎你是否改变了一些东西。我想要它在操作的那一刻。” 如果在您执行此操作时尝试插入或更新某些内容,它将不会锁定它。
已提交不会锁定任何内容,除非您的操作完成之前正在提交的内容。您可以安全地知道返回的数据已完成,但您会冒着阻止尝试插入或发布事务的风险。您实际上是在告诉数据库:“等待我完成,然后再继续对我正在访问的表进行提交。我需要准确的数据,所以在我完成之前放手”。这可能会在对您从中收集的表执行读取时锁定数据。这并不常见,因为大多数选择几乎是即时的,但在基于每秒发布数千条记录的事务性大型系统上,这是一个大问题。
老实说,在我的讨论中,我赞成不承诺,而另一个人赞成承诺。我认为获取脏数据比停止生产插入更容易接受。他们认为幻读和其他情况更糟。这是一种观点,SQL 系统是围绕插入和选择设计的,但很少有你能在不影响另一个的情况下非常快地完成这两个操作。如果您想要准确的报告,我的回答是进行夜间备份、SSIS 包、二进制集合或类似隔离级别的东西,例如快照或提交,并将该数据放在某处。让该数据以我们知道它已完成并已锁定的方式设置,因此以后可能不会更改并报告它。不要报告生产数据的热点,并强调告诉每个人都这样做。
如果您是一家只有 5 或 10 人使用数据库的小型夫妻店,会不会很痛苦,可能不会。如果您稍微大一点并且有 50 个人访问同一个数据库,但它是大约 100 个演出和半事务性的,因为您在白天会获得涓涓细流的数据,这会不会很痛苦。仍然可能没有。如果你有 200 个人、多个服务器和数据库以及一个存储所有数据组合的主要事务数据库大脑,会不会很痛苦。绝对,如果主要目的是获取要存储的数据,请不要从操作密集的主生产数据库中读取。
编辑从现实世界的例子进一步指出:
这就是为什么通常在我不使用表变量的大多数操作的顶部(声明@Table table)我设置这个:“设置事务隔离级别读取未提交”。每次查询时我都会强烈使用它吗?大声笑,我希望不会。事实上,从这一点开始,完全披露它可能永远不会帮助我,因为我使用临时表将我的数据隔离了很多,以进行大量事务报告。但是我不会被其他人大喊大叫,因为我有一个长期运行的事务阻止他们的插入。您还会看到很多人这样做:“select * from table (nolock)” 我通常将这样的代码提供给较小的查询设计人员,因为它在查询中嵌入了 nolock 提示。如果我告诉每个人都这样做,他们就会制定政策。
您不必这样做,事实上有些人可能会关注我并声称这是错误的并发布他们的立场。我这样做主要是为了生产保护,如果有人告诉我这是错误的,我想听听他们为什么喜欢在生产中锁定表并报告它们,而不是首先实时获取或更新他们的数据。我很难去找经理说:“你知道那个巨大的帐户,你正在等待发布 200 万条记录,并且知道它完成的实例。嗯,大厅里的约翰真的很想运行这个需要运行一个小时,因为它的设计草率。他选择使用已提交,并且正在访问一些执行插入操作的表,因此我们偶尔会遇到锁定问题。嗯,我认为他得到他的报告比我们得到业务更重要。