大部分的论坛和榜样的网上总是建议同时拥有ALLOW_SNAPSHOT_ISOLATION并READ_COMMITTED_SNAPSHOT设置为ON,每当别人问快照,行版本或类似的问题。
我想这两种设置中的 SNAPSHOT 一词都有些令人困惑。我认为,为了让数据库引擎对 READ_COMMITTED 默认行为使用行版本控制而不是锁定,无论设置如何,数据库READ_COMMITTED_SNAPSHOT都设置为 ON 。ALLOW_SNAPSHOT_ISOLATION
该ALLOW_SNAPSHOT_ISOLATION设定被设定为ON只允许快照隔离启动事务(例如SET TRANSACTION ISOLATION级快照)时无论的READ_COMMITTED_SNAPSHOT设置。
将这两个设置设置为 ON 的唯一原因是它需要具有 READ COMMITTED 行版本控制和 快照隔离。
我的问题是,我的理解在某种程度上是错误的吗?并且这两个设置必须始终一起设置为 ON(特别是对于 READ COMMITTED 行版本控制)?
假设您有以下代码(请忽略它很糟糕):
BEGIN TRAN;
DECLARE @id int
SELECT @id = id + 1 FROM TableA;
UPDATE TableA SET id = @id; --TableA must have only one row, apparently!
COMMIT TRAN;
-- @id is returned to the client or used somewhere else
Run Code Online (Sandbox Code Playgroud)
在我看来,这不是正确管理并发性。仅仅因为您有一个事务并不意味着其他人不会读取您在获取更新语句之前所做的相同值。
现在,让代码保持原样(我意识到这作为单个语句更好地处理,甚至使用自动增量/标识列更好)有哪些确定的方法可以使其正确处理并发并防止允许两个客户端获得相同条件的竞争条件身份证价值?
我很确定将 a 添加WITH (UPDLOCK, HOLDLOCK)到 SELECT 会解决问题。该SERIALIZABLE事务隔离级别(因为它拒绝任何人阅读你做了什么,直到移植是在将似乎工作,以及UPDATE:这是假见马丁的答案)。真的吗?它们会同样有效吗?一个比另一个更受欢迎吗?
想象一下做一些比 ID 更新更合法的事情——一些基于你需要更新的读取的计算。可能涉及许多表,其中一些您会写入,而另一些则不会。这里的最佳做法是什么?
写完这个问题后,我认为锁定提示更好,因为这样你只锁定了你需要的表,但我很感激任何人的意见。
PS 不,我不知道最好的答案,真的很想得到更好的理解!:)
前言
我们的应用程序运行多个DELETE并行执行查询的线程。查询影响孤立的数据,即不应该存在并发DELETE发生在来自不同线程的相同行上的可能性。但是,根据文档,MySQL 对DELETE语句使用所谓的“next-key”锁,它同时锁定匹配的键和一些间隙。这会导致死锁,我们找到的唯一解决方案是使用READ COMMITTED隔离级别。
问题
DELETE使用JOIN大表执行复杂语句时会出现问题。在特定情况下,我们有一个带有警告的表,只有两行,但查询需要从两个单独的INNER JOINed 表中删除属于某些特定实体的所有警告。查询如下:
DELETE pw
FROM proc_warnings pw
INNER JOIN day_position dp
ON dp.transaction_id = pw.transaction_id
INNER JOIN ivehicle_days vd
ON vd.id = dp.ivehicle_day_id
WHERE vd.ivehicle_id=? AND dp.dirty_data=1
Run Code Online (Sandbox Code Playgroud)
当 day_position 表足够大时(在我的测试用例中有 1448 行),那么即使使用READ COMMITTED隔离模式,任何事务也会阻塞整个 proc_warnings表。
该问题始终在此示例数据上重现 - http://yadi.sk/d/QDuwBtpW1BxB9在 MySQL 5.1(在 5.1.59 上检查)和 MySQL 5.5(在 MySQL 5.5.24 上检查)中。
编辑:链接的示例数据还包含查询表的架构和索引,为方便起见,在此处复制:
CREATE TABLE `proc_warnings` (
`id` int(11) NOT NULL AUTO_INCREMENT, …Run Code Online (Sandbox Code Playgroud) 我SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED在大多数一般 SQL 查询中使用,主要是因为这是我最初学习语言时深入了解的。
根据我的理解,这种隔离级别的行为方式与WITH (NO LOCK)我只倾向于使用SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
WITH (NO LOCK)over SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED阻止其他用户被锁定在我正在阅读的表格之外?SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED用于停止锁,而我只是在读取数据,那么使用它有什么意义?是否只有系统密集型查询会生成锁?在运行会在 5-10 秒内返回的查询时是否值得使用它?SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED在读取将用于更新的数据时不要使用 ,大概是为了避免更新脏数据。这会是唯一的原因吗?SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED在我的查询中使用。我知道这可能会导致脏读。除了接收回可能不会提交到数据库的数据(因此将我的结果扔掉)之外,还有哪些其他类型的“脏读”是可能的?对不起,群众问题。
我已经使用 JDBC 技术READ_COMMITTED和READ_UNCOMMITTED在家中进行了一些测试。
我看到READ_UNCOMMITTED实际上可以读取未提交的数据,例如来自某些尚未提交的事务的数据(可以执行更新查询)。
READ_UNCOMMITTED事务可以从另一个事务中读取未提交的数据?READ_COMMITTED事务不可能读取未提交的数据,即执行“脏读”?什么机制强制执行此限制?众所周知,READ UNCOMMITTED 是最低的隔离级别,在该级别中可能会产生脏读和幻读之类的事情。何时是使用此隔离级别的最佳时间,可能出于什么原因使用它?
其实我之前看过答案,但是因为例子不够,所以没能完全理解。
我和我的一位同事讨论了使用可序列化隔离级别的含义。他说它锁定了整个表,但我不同意告诉他它可能可以但它尝试应用范围锁并且它不应用真正的序列化,如此处所述:可序列化隔离级别。
我在文档中找不到“锁定整个表”的任何内容:SET TRANSACTION ISOLATION LEVEL。
该文档说明了一系列关于范围锁的内容,因此理论上您可以通过简单地拥有一个范围锁来锁定整个表,该范围锁可以锁定表中可能值的整个范围,但它不会锁定表。
我在这里完全错了吗?它实际上是否锁定了整个表(或多个表)?
我读到,如果我使用 IsolationLevel.ReadUncommitted,则查询不应发出任何锁。但是,当我对此进行测试时,我看到了以下锁定:
Resource_Type:HOBT
Request_Mode:S(共享)
什么是 HOBT 锁?与 HBT(堆或二叉树锁)相关的东西?
为什么我还会得到 S 锁?
在不打开隔离级别快照选项的情况下进行查询时如何避免共享锁定?
我正在 SQLServer 2008 上对此进行测试,并且快照选项设置为关闭。查询仅执行选择。
我可以看到 Sch-S 是必需的,尽管 SQL Server 似乎没有在我的锁定查询中显示它。为什么它仍然发出共享锁?根据:
在该
READ UNCOMMITTED级别运行的事务不会发出共享锁,以防止其他事务修改当前事务读取的数据。
所以我有点困惑。
我工作的公司目前使用 SQL Server 数据库(通常是最新的企业版)用于我们开发的产品。
我会将它描述为一个 OLTP 数据库,它具有大量时间关键应用程序的读写密集程度。除此之外,根据同一 OLTP 数据库(单独问题)中的信息显示了大量报告和图形数据,这些数据以频繁的速率读取和写入许多相同的表。
我们通常会遇到发生阻塞的问题,并且通常最终会减慢时间关键应用程序的速度,甚至由于这些应用程序中的死锁而导致问题。这个问题的常见解决方案似乎通常是对nolock有问题的查询提出提示。老实说,我讨厌这个解决方案,很长一段时间以来,我一直认为这是尝试解决这个问题的错误方法,从我阅读的所有内容中,我得出了相同的结论。
一段时间以来,我一直试图说服我的团队 RCSI 是我们绝对可以从中受益的东西,特别是考虑到我们的数据库类型。他们似乎认为这是一个很大的风险,并且经常因为风险因素而推迟它,但我们继续遇到性能问题,我们只是nolock在暗示它。
我正在寻找一种向我们的团队展示具体指标的好方法,以最终说服他们我们应该转向这种方法。
在存储过程中,我有以下内容:( sql server 2008 )
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION getStuff
BEGIN TRY
/* some selects, updates, etc, etc. */
....
COMMIT TRANSACTION getStuff
END TRY
BEGIN CATCH
...
END CATCH
Run Code Online (Sandbox Code Playgroud)
由于这是基于事务的,我认为其余的数据库连接不会受到 SERIALIZABLE 的影响。
我是否需要隐式设置隔离级别以在提交后读取已提交?这是否会对我的应用程序服务器和数据库服务器之间的其他连接产生不利影响?
isolation-level ×10
sql-server ×7
locking ×3
concurrency ×2
innodb ×2
mysql ×2
transaction ×2
deadlock ×1
metrics ×1
mysql-5.5 ×1
t-sql ×1