[MSSQL] SQL Server 的一些眉眉角角

同步发表至部落格:[MSSQL] SQL Server 的一些眉眉角角 (2018/11/01)

目前工作 Database 方面主要都在使用 SQL Server,写了近两年的 Stored Procedure 也遇到了许多的问题,在这里简单笔记一下。

暂存资料表小知识

### 建立的暂存资料表,可从 tempdb.暂存资料表 找到。# 建立的暂存资料表只有该连线可以取用;## 则是全部连线均可使用。连线结束时皆会自动删除,若程式中有 Connection Pool 来管理连线则不会立刻删除。父层 Stored Procedure 建立的暂存资料表子层也可以使用;子层 Stored Procedure 建立的暂存资料表父层也可以使用

若开启交易 (Transaction) 但无提交异动 (Commit) 会发生资料表锁死 (Table Lock) 的问题,切记要提交异动 (Commit)。

使用主键来 UPDATE 为资料锁 (Row Lock),若使用其他条件则有可能会升级成资料页锁(Page Lock) 或资料表锁 (Table Lock)。

交易 (Transaction) 具有复原机制 (RollBack),但实际上资料表中的资料已经被异动且锁定的关係所以无法取得,可利用 WITH(NOLOCK) 来取得被锁定的髒资料。

未开启交易时使用 CURSORUPDATE FROM 若超过五千笔时可能会造成锁定与死结,可使用 ROW_NUMBER() 排序资料塞入暂存资料表并使用 WHILE 来一笔一笔更新资料避开锁定,速度虽慢但能减少锁死。

SET NOCOUNT ONDECLARE@RowNumINT,@RowCountINT,@Temp_IdINTSELECTROW_NUMBER() OVER(ORDER BY [Id]) AS RowNum,[Id],[Name]INTO#TempFROM[exfast].[dbo].[TableA] WITH(NOLOCK)SELECT@RowNum = 1,@RowCount = (SELECT SUM(1) FROM #Temp)WHILE(@RowNum <= @RowCount)BEGINSELECT@Temp_Id = [Id]FROM#TempWHERERowNum = @RowNumUPDATE[exfast].[dbo].[TableA]SET[Name] = 'dddd'WHERE[Id] = @Temp_IdSET @RowNum = @RowNum + 1ENDDROP TABLE #Temp
高负载情况下使用 UPDATE OUTPUT 的方法来取得资料更新前后的状态,可减少 SELECT 次数提高效率。
DECLARE@TempATABLE([INSERTED_Id]INT,[INSERTED_Name]NVARCHAR(32),[DELETED_Id]INT,[DELETED_Name]NVARCHAR(32))UPDATE[exfast.Helper].[dbo].[TableA]SET[Name] = 'qqqq'OUTPUTINSERTED.[Id],INSERTED.[Name],DELETED.[Id],DELETED.[Name]INTO@TempASELECT * FROM @TempA
高负载情况下可能会将隔离层级拉高到 Serializable,这时使用交易会发生相同资料表 SELECT UPDATE 中的 Shared Lock 与 Exclusive Lock 撞车造成 DeadLock,可在 SELECT 加上 WITH(UPDLOCK) 来减少此问题。
-- 故意指定隔离层级模拟撞车的情况SET TRANSACTION ISOLATION LEVEL SERIALIZABLEBEGIN TRANSELECT * FROM [exfast.Helper].[dbo].[TableA]WAITFOR DELAY '00:00:10'UPDATE[exfast.Helper].[dbo].[TableA]SET[Name] = 'cccc'WHERE[Id] = 2ROLLBACK

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章