我开始解决tempdb我们在 SQL Server 2005 企业版上遇到的问题。开发人员收到tempdb空间不足的错误。从技术上讲,错误是:
访问数据库 'dbname' 中的表 'dbo.inserted' 中的版本化行时,事务中止。未找到请求的版本化行。您的 tempdb 可能空间不足。请参考 BOL 如何配置 tempdb 进行版本控制
我查看了数据库配置sys.databases,发现了以下设置:
snapshot_isolation_state: 0
snapshot_isolation_state_desc: OFF
is_read_committed_snapshot_on: 1
Run Code Online (Sandbox Code Playgroud)
我在BOL 中查找了这意味着什么,主要信息如下:
snapshot_isolation_state允许快照隔离事务的状态,由 ALLOW_SNAPSHOT_ISOLATION 选项设置:
0 = 快照隔离状态为关闭(默认)。不允许快照隔离。
1 = 快照隔离状态开启。允许快照隔离。
2 = 快照隔离状态正在转换为关闭状态。所有事务都有其修改版本。无法使用快照隔离启动新事务。数据库保持转换为 OFF 状态,直到运行 ALTER DATABASE 时处于活动状态的所有事务都可以完成。
3 = 快照隔离状态正在转换为 ON 状态。新的交易有他们的修改版本。在快照隔离状态变为 1 (ON) 之前,事务无法使用快照隔离。数据库将保持转换到 ON 状态,直到可以完成运行 ALTER DATABASE 时处于活动状态的所有更新事务。
snapshot_isolation_state_desc允许快照隔离事务的状态描述,由 ALLOW_SNAPSHOT_ISOLATION 选项设置:
- 离开
- 在
- IN_TRANSITION_TO_ON
- IN_TRANSITION_TO_OFF
is_read_committed_snapshot_on1 = READ_COMMITTED_SNAPSHOT 选项为 ON。read-committed 隔离级别下的读操作基于快照扫描,不获取锁。
0 …
我正在研究 SQL Server 中的事务隔离级别,并试图弄清楚在事务的生命周期中隔离级别发生变化时 SQL Server 的行为。
在 SQL Server 中似乎有这样的事情是可能的:
BEGIN TRANSACTION;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
/* (some selects/inserts/updates/deletes) */
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
/* (some selects/inserts/updates/deletes) */
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
老实说,我想不出降低隔离级别有意义的例子,我只能想到一些场景,其中事务的一部分需要可序列化的隔离,而其他部分则不需要。我有一种感觉,将使用快照和行版本控制的隔离级别与其他类型的隔离级别混合使用效果不佳,但我找不到很多信息来支持这一点。
在实践中是否会发生单个事务在其生命周期内在多个隔离级别之间切换的情况?是否有一些注意事项和细节需要了解?
我们正在我们的组织中建立一个数据仓库(以及一些数据集市)。我的 DBA 技能主要用于 OLTP 类型的应用程序,但我正在为我们的组织支持 OLAP。
我们最近遇到了一个问题,我们的一个 ETL 程序(在本例中恰好是一个用 Java 编写的消息驱动 Bean)正在使用可重复读取 (RR) 隔离级别。因此,他们遇到了锁。我显然质疑为什么使用 RR。(编辑:我原本以为是DB2端的RR,后来了解到这是JDBC端的RR,映射到DB2端的RS。此后我们也尝试了JDBC端的RC,也就是DB2端的CS 。这似乎解决了一些锁定问题。)
所以我开始从提要/源端和检索端研究数据仓库的建议隔离级别应该是什么。
我真的找不到太多。我发现有几篇文章提到未提交的读取 (UR) 对查询/检索方面有好处,但没有提到馈送方面。我在想应该使用光标稳定性 (CS) 或最高读取稳定性 (RS)。我会站在 CS 一边,但也许这受到了 OLTP 思维的影响?
在我们的例子中,我们仓库的主要提要现在使用 Java 消息队列“实时”完成。从仓库中检索将使用 ETL 工具(在我们的案例中为 DataStage)完成,可能作为夜间作业开始(一些用于每日报告,其他用于月度或季度报告)。这些报告将基于我们的市场。因此,虽然仓库可能会被“实时”提供,但不会被读取或主动查询(至少现在不是)。
诚然,我们使用 DB2 9.7 FP 4(我们希望在明年某个时候迁移到 10.1),并且每个供应商的某些细节可能不同,但是您对 DBA 推荐的提要和读取的隔离级别是什么?为什么?
此外,任何有关 marts 隔离级别的输入都将不胜感激。
编辑:这样就更容易与其他供应商进行比较。这是映射到 JDBC 隔离级别的 DB2 隔离级别名称表。(这是根据《理解 DB2:通过示例直观地学习》一书,因此版权 IBM。)
Run Code Online (Sandbox Code Playgroud)+------------------------------+-----------------------+ | JDBC | DB2 | +------------------------------+-----------------------+ | TRANSACTION_READ_UNCOMMITTED | Uncommitted Read (UR) | +------------------------------+-----------------------+ | TRANSACTION_READ_COMMITTED | Cursor Stability (CS) | +------------------------------+-----------------------+ | …
我认为自己是 Sql Server 锁定的初学者。
我的理解是,在使用 RCSI 时,Sql Server 不需要发出 S 锁,因为它使用行版本控制(在大多数情况下)。从http://technet.microsoft.com/en-us/library/jj856598(v=sql.110).aspx我们可以阅读以下关于 U 锁的信息:
用于可以更新的资源。防止在多个会话读取、锁定和稍后可能更新资源时发生的常见死锁形式。
知道了这一点,为什么Sql Server 需要发出U 锁(使用RCSI 时)?在我看来,Sql Server 可以简单地读取行,并在必须执行更新时直接请求 X 锁。
我一直在考虑这个的原因是因为我在更新同一个表的 2 个会话中遇到了死锁。像这样(为了清楚起见而简化):
第 1 节:
BEGIN TRAN
UPDATE t1 SET col1 = col1 + 100 WHERE col2 = value1
UPDATE t1 SET col1 = col1 + 100 WHERE col2 = value2
UPDATE t1 SET col1 = col1 + 100 WHERE col2 = value3
Run Code Online (Sandbox Code Playgroud)
第 2 节:
BEGIN TRAN
UPDATE t1 SET col1 = col1 …Run Code Online (Sandbox Code Playgroud) sql-server deadlock locking isolation-level snapshot-isolation
我已经阅读了许多关于 NOLOCK 或读取未提交的隔离级别在采用的锁/闩锁方面如何运作的不同看法。
当使用带有 NOLOCK 的 SELECT 或在 Read Uncommitted Isolation 级别时,是唯一取出模式稳定性锁的锁,还是在查询通过行时滚动获取共享锁?(显然这些锁需要立即放下)
闩锁呢?当我假设不允许引用正在修改的内存对象时,如何处理内存中的页面?
可序列化隔离模式可用于避免更新插入相等 id 时的竞争条件。因此,create table u(uid int primary key, name text);如果我们运行两个相似的事务 T1 和 T2:
begin isolation level serializable;
select * from u where uid = 1;
Run Code Online (Sandbox Code Playgroud)
然后继续 T1 和 T2:
insert into u (uid, name) values (1, 'A');
Run Code Online (Sandbox Code Playgroud)
commit;只有第一个成功,而另一个抛出序列化失败之后。
这是该模式的一个非常巧妙的功能,可以处理复杂交易中的独特密钥违规,而不是诉诸特定的“黑客” insert ... on conflict。然而,即使 uid 不同,例如uid = 2和uid = 3,事务 T1 和 T2仍然无法提交。
怎么可能?据说他们创建了不同的谓词 SIReadlocks 并select使用索引扫描。窍门在哪里?
如果我有一个用户表:
id | name | age
1 | Mateus | 27
Run Code Online (Sandbox Code Playgroud)
第一个事务执行更新,并使事务保持打开状态,不提交或回滚:
update User set name = 'John' where id = 1;
同时,第二个事务执行一个选择:
select * from User where id = 1;
该命令将等待第一个事务通过提交或回滚释放锁,除非第二个事务使用表提示with(nolock),如下所示:
select * from User with(nolock) where id = 1;
这将返回记录而不锁定事务,但是它将返回未提交的值John而不是原始值Mateus。
据我所知,只有两种方法可以在不锁定当前事务的情况下返回锁定的记录,一种可以使用with(nolock)将返回记录但带有未提交值的方法,并且with(readpast)不会返回记录。
有没有办法可以在不锁定表的情况下返回记录并返回其“旧”值?
到目前为止,我读过的所有谈论事务的书籍都展示了涉及多个 SQL 语句的场景。
但是单个语句又如何呢?他们的隔离程度如何?标准中是否有指定?或者它取决于 RDBMS 和隔离级别?
让我举几个例子。
UPDATE table SET value = value + 1 WHERE id = 1;
这是一个复合read-update-write操作。read并行事务可以改变和write操作之间的值吗?有些书指出,在大多数RDBMS中,此操作是原子的(在多线程编程意义上) 。
SELECT * FROM table t1 JOIN table t2 USING (id);
如果表很大(或者查询会有一些复杂的过滤子句),在某些隔离级别上,列t1.*和t2.*列是否可能因并行更新而有所不同?
SELECT * FROM table1 WHERE id IN (SELECT t_id FROM table2);
table1执行子选择后是否有可能删除一些记录?(这里我假设table2.t_id引用table1.id具有级联删除功能。)
热膨胀系数...
还可以提供有用手册的链接,这些手册充分解释了交易的所有细节。
我读过《深入了解 MySQL 和 PostgreSQL 中的隔离级别》和《读取现象》,尤其是“Postgres 中的序列化异常”部分。我想我已经理解了那里描述的问题,但是我很难判断它何时会在我的应用程序中发生。
是否只有使用 SUM/COUNT 这样的聚合函数才能在 Postgres 中获得序列化异常?如果不是,我还需要注意什么?
我试图了解 SQL Server 版本存储和相关的隔离级别。据我了解,当数据库启用读取已提交快照选项时,可能会发生这种情况:
update products set price = price * 1.5。由于这涉及表的所有行,因此需要很长时间。update语句仍在进行时,会话 2 启动一个查询:select * from products where id = 1。由于数据库处于读已提交快照模式,因此写入者不会阻止读取者。因此,会话 1 从版本存储中读取该行的旧版本,并认为该产品的价格为 1000 美元。update语句执行完毕,产品(id = 1)的新价格为 1500 美元。如果用户知道产品的新价格,他就不会购买。在这种情况下,会发生什么呢?这种情况实际上可能吗?如果是这样,防止这种情况的规范是什么?
sql-server isolation-level tempdb-version-store snapshot-isolation
isolation-level ×10
sql-server ×6
concurrency ×2
locking ×2
postgresql ×2
transaction ×2
consistency ×1
db2 ×1
deadlock ×1
latch ×1
upsert ×1