在我的应用程序中,我必须执行分布式锁定模式。因为我们已经有一个 SQL Server 实例可以使用,所以我们决定在我们的 Web 应用程序的 SQL 层实现锁定是最容易的。
可以根据多种条件获得锁,包括:
出于所有意图和目的,将上述两个条件视为int数据类型。
在这种模式中,我们希望将我们所有的锁都视为 FIFO,我相信SERIALIZABLE隔离级别会给我们带来这种好处。
以下是我们建议如何执行“锁定”:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
IF EXISTS (SELECT 1 FROM locks WHERE LockType = @LockType AND ApplicationIdentifier = @ApplicationIdentifier)
BEGIN
-- Awesome, the lock will be acquired
INSERT INTO locks OUTPUT INSERTED.LockId VALUES (2,3)
END
ELSE
BEGIN
-- Someone already has the lock
SELECT -1
END
SET TRANSACTION ISOLATION LEVEL READ COMITTED
Run Code Online (Sandbox Code Playgroud)
和“解锁”:
DELETE FROM locks WHERE LockId = @LockId
Run Code Online (Sandbox Code Playgroud)
所以我的问题有两个方面: …
我想知道是否有人知道为什么 PostgreSQL、SQL Server、Oracle、Vertica、DB2、Informix和SybaseREAD COMMITTED的默认事务隔离级别的历史。
MySQL 使用默认的 REPEATABLE READ,至少对于 InnoDB,SQLite和NuoDB 也是如此(他们称之为“一致读取”)。
同样,我不是在问不同隔离级别之间有什么区别,而是要解释为什么READ COMMITTED在这么多 SQL 数据库中选择默认值。我的猜测是:性能优势小、易于实现、SQL 标准本身的一些建议和/或“它一直都是这样”。这种选择的明显缺点是,READ COMMITTED对于开发人员来说,这往往是非常违反直觉的,并且可能导致细微的错误。
在多个并行批处理中运行处理作业,它基本上读取大块行以更新一些行 - 这里可以使用较低的事务级别,因为我知道在此任务运行时不会更新相关值,因此在调用每个存储之前我运行的过程:
set session transaction isolation level read uncommitted
然后调用存储过程,它获取要处理的 ID 子集。整体操作的SQLFiddle:http ://sqlfiddle.com/#!9/192d62 (有点做作但保持原始查询的结构)
我问的原因是死锁继续发生并查看监视器输出,有一个线程请求共享锁,而另一个线程在同一空间上持有排他锁(反之亦然)-不应设置该事务级别来阻止需要对于共享锁?除了 之外,还有其他理由获得共享锁repeatable-read吗?
使用 InnoDB。
相关锁信息来自show engine innodb status(编辑以匹配来自 SQLFiddle 的表名):
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 481628 page no 24944 n bits 112 index `PRIMARY` of table `events` trx id 27740892 lock mode S locks rec but not gap waiting
Run Code Online (Sandbox Code Playgroud)
和
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 481628 page no …Run Code Online (Sandbox Code Playgroud) 我试图让我的表使用行锁。我已经禁用了锁升级。隔离级别为READ_COMMITTED_SNAPSHOT
alter table <TABLE_NAME> SET (LOCK_ESCALATION=DISABLE)
go
alter index <INDEX_NAME> ON <TABLE_NAME> SET (ALLOW_PAGE_LOCKS=OFF)
go
Run Code Online (Sandbox Code Playgroud)
设置后还是不行。
我是否需要重建我的表以使其不使用页面锁定?
sql-server deadlock sql-server-2008-r2 locking isolation-level
这是一道作业题。
对于以下事务,说明将在不降低数据库完整性的情况下最大化吞吐量的隔离级别。解释答案。
将 coursed_id = 'CPSC1350' 标识的课程从一个部门更改为另一个部门。
Courses 表包含有关课程的信息:课程 ID、名称、提供课程的部门、讲师的 ID 以及可以参加课程的最大学生人数 (max_size)。课程(coursed_id:string,cname:string,dept:string,instructor_id:string,max_size:integer) – 主键:coursed_id – 外键:instructor_id 引用 Instructors
假设使用 PostgreSQL。
我相信可以使用提交的读来完成事务,因为
SELECT陈述 我在正确的轨道上吗?
我开始解决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 …
我想我们的PostgreSQL 9.4的事务级数据库迁移READ COMMITTED要么REPEATABLE READ或SERIALIZABLE。在任何一种情况下,我都会遇到一组新的格式错误:
(for both)
ERROR: could not serialize access due to concurrent update
(just for SERIALIZABLE)
ERROR: could not serialize access due to read/write dependencies among transactions
Run Code Online (Sandbox Code Playgroud)
在阅读了 SSI 上的 wiki 页面和文档后,我彻底了解了可能导致这些错误的错误条件、如何处理它们,甚至是避免它们的最佳实践。
但是,我看不到从 PostgreSQL 可以提供的任何调试输出或任何调试信息中确定导致它们的数据依赖性的方法。有没有办法从数据库中获取这些信息,要么在回滚时执行额外的查询,要么通过某种日志机制?
有了这些信息,我就可以进行应用程序级别的更改(锁定、不同的查询等),从而消除一些数据竞争以避免过多的回滚。
继承的死锁问题需要帮助!
下面给出的代码似乎已经写了一段时间,试图解决围绕在更大/更胖的 [IDs] 父表上分配新 ID 值的争用问题,首先在较小的 [ID_Stub ] 桌子。然而,持续死锁的存在表明这段代码引起的问题似乎比它解决的问题要多。
我们经常在下表中的 INSERT 语句周围遇到死锁(表名和列名已被混淆)。该表没有触发器或外键依赖项,但具有如下聚簇索引和非聚簇索引。
CREATE TABLE dbo.ID_Stub (
ID int IDENTITY(1,1) NOT NULL,
IDReference nchar(25) NULL,
AdditionalID int NULL,
CreatedBy int NOT NULL,
CreatedOn datetime NOT NULL,
CONSTRAINT PK_ID_Stub PRIMARY KEY CLUSTERED (ID) WITH
(
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON,
FILLFACTOR = 90
)
);
GO
CREATE NONCLUSTERED INDEX idx_IDReference ON dbo.ID_Stub (IDReference) WITH
(
PAD_INDEX …Run Code Online (Sandbox Code Playgroud) 我正在研究 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)
老实说,我想不出降低隔离级别有意义的例子,我只能想到一些场景,其中事务的一部分需要可序列化的隔离,而其他部分则不需要。我有一种感觉,将使用快照和行版本控制的隔离级别与其他类型的隔离级别混合使用效果不佳,但我找不到很多信息来支持这一点。
在实践中是否会发生单个事务在其生命周期内在多个隔离级别之间切换的情况?是否有一些注意事项和细节需要了解?
我有两个表 ( SJob& SJobDependent),我需要为存储过程中的某些逻辑加入它们。它们都有一列 ( job)以一对多关系连接它们- 一条SJob记录对应零个或多个SJobDependent记录。
这是我的 SQL 查询:
-- Return any records that are active and have no unsatisfied dependencies.
SELECT * FROM SJob
LEFT JOIN SJobDependent
ON SJob.job = SJobDependent.job
AND SJobDependent.satisfied = 0
WHERE SJobDependent.jobDependentID IS NULL
AND SJob.state = 'active'
Run Code Online (Sandbox Code Playgroud)
这是SQL Server Studio的实际执行计划:
由于代码的编写方式:
-- Return any records that are active and have no unsatisfied dependencies.
SELECT * FROM SJob
LEFT JOIN SJobDependent
ON …Run Code Online (Sandbox Code Playgroud) isolation-level ×10
sql-server ×6
deadlock ×3
locking ×2
postgresql ×2
concurrency ×1
identity ×1
mysql ×1
optimization ×1
parallelism ×1
rdbms ×1
transaction ×1