SQL Server在AlwaysOn中使用內(nèi)存表的“踩坑”記錄
前言
最近因?yàn)榫€上alwayson環(huán)境的一個(gè)數(shù)據(jù)庫(kù)上使用內(nèi)存表。經(jīng)過(guò)大概一個(gè)星期監(jiān)控程序發(fā)現(xiàn)了一個(gè)非常嚴(yán)重問(wèn)題這個(gè)數(shù)據(jù)庫(kù)的日志文件不會(huì)截?cái)?,已用空間一直在增加(存在定時(shí)的每個(gè)小時(shí)的日志備份),同時(shí)內(nèi)存表數(shù)據(jù)庫(kù)文件也無(wú)法刪除,下面就介紹一下后面我的處理過(guò)程,話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
數(shù)據(jù)庫(kù):SQL Server2014 Enterprise Edition (64-bit)
刪除文件
使用一個(gè)單獨(dú)非alwayson環(huán)境的數(shù)據(jù)庫(kù)測(cè)試。
一、創(chuàng)建內(nèi)存表
---創(chuàng)建內(nèi)存表文件組 ALTER DATABASE [test] ADD FILEGROUP [test_ag] CONTAINS MEMORY_OPTIMIZED_DATA GO ----創(chuàng)建內(nèi)存表數(shù)據(jù)庫(kù)文件 ALTER DATABASE [test] ADD FILE ( NAME = 'test_memory', FILENAME ='D:\database\memory' ) TO FILEGROUP [test_ag]; GO
二、刪除內(nèi)存表數(shù)據(jù)庫(kù)文件
USE [test] GO ALTER DATABASE [test] REMOVE FILE [test_memory] GO
備注:此時(shí)還未創(chuàng)建表,創(chuàng)建完后數(shù)據(jù)庫(kù)文件執(zhí)行刪除就無(wú)法刪除,接下來(lái)試試在線文檔的刪除方法方法
三、官方相關(guān)的刪除方法
即使已使用“DBCC SHRINKFILE”操作清空 FILESTREAM 容器,但出于各種系統(tǒng)維護(hù)原因,數(shù)據(jù)庫(kù)可能仍然需要保留對(duì)已刪除文件的引用。 sp_filestream_force_garbage_collection (TRANSACT-SQL)將運(yùn)行 FILESTREAM 垃圾回收器刪除這些文件時(shí),則可以安全進(jìn)行這些操作。 除非 FILESTREAM 垃圾回收器已從 FILESTREAM 容器中刪除所有文件,否則 ALTER DATABASEREMOVE FILE 操作將無(wú)法刪除 FILESTREAM 容器并返回錯(cuò)誤。 建議使用以下過(guò)程刪除 FILESTREAM 容器。
1.運(yùn)行DBCC SHRINKFILE (TRANSACT-SQL)帶有 EMPTYFILE 選項(xiàng)以將此容器的活動(dòng)內(nèi)容移動(dòng)到其他容器
USE test; GO -- Create a data file and assume it contains data. ALTER DATABASE test ADD FILE ( NAME = Test1data, FILENAME = 'D:\database\t1data.ndf', SIZE = 5MB ); GO -- Empty the data file. DBCC SHRINKFILE (test_memory, EMPTYFILE); GO
2.確保已在 FULL 或 BULK_LOGGED 恢復(fù)模型中執(zhí)行日志備份。
3.確保復(fù)制日志讀取器作業(yè)已運(yùn)行(如果相關(guān))。
通過(guò)log_reuse_wait_desc的狀態(tài)可以看到當(dāng)前數(shù)據(jù)庫(kù)已經(jīng)無(wú)需日志備份,當(dāng)然我已經(jīng)執(zhí)行過(guò)日志備份。
4.運(yùn)行sp_filestream_force_garbage_collection (TRANSACT-SQL)強(qiáng)制垃圾回收器刪除不再需要此容器中的任何文件
USE [test] GO EXEC sp_filestream_force_garbage_collection @dbname = N'test' @filename = N' test_memory ';
5.執(zhí)行帶有 REMOVE FILE 選項(xiàng)的 ALTER DATABASE,以刪除此容器。
USE [test] GO ALTER DATABASE [test] REMOVE FILE [test_memory] GO
還是無(wú)法刪除!?。?/p>
四、問(wèn)題分析
一開(kāi)始是在alwayson的環(huán)境中刪除,提示由于副本的原因無(wú)法刪除。后面單獨(dú)在一個(gè)非alwayson的環(huán)境下的數(shù)據(jù)庫(kù)測(cè)試同樣是無(wú)法刪除,起初以為是創(chuàng)建了內(nèi)存表的原因后面測(cè)試僅僅創(chuàng)建文件組和文件然后來(lái)刪除文件同樣是無(wú)法刪除,個(gè)人猜測(cè)有可能是buffer的緣故;在buffer中一直存在內(nèi)存表相關(guān)的文件存在,通過(guò)執(zhí)行DBCC DROPCLEANBUFFERS命令也無(wú)法清空buffer中的內(nèi)存表對(duì)象。使盡渾身解數(shù)還是無(wú)法將它刪除掉,最后只能投降了?。。【€上環(huán)境等不下去;只能使用最不愿使用的生成表結(jié)構(gòu)導(dǎo)出數(shù)據(jù)的辦法來(lái)重建新的數(shù)據(jù)庫(kù)。
生成腳本重建數(shù)據(jù)庫(kù)
創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)同時(shí)保證當(dāng)前數(shù)據(jù)庫(kù)可用(重命名當(dāng)前的數(shù)據(jù)庫(kù),新創(chuàng)建的數(shù)據(jù)庫(kù)使用之前的名稱這樣可以保證應(yīng)用程序那邊不需要改變),這樣如果出現(xiàn)什么問(wèn)題也可以及時(shí)的切換回來(lái)。
步驟如下(在允許停機(jī)維護(hù)的情況下進(jìn)行):
1.禁用所有相關(guān)作業(yè)
2禁用應(yīng)用程序登入用戶
同時(shí)保證相關(guān)進(jìn)程事務(wù)都已完成。
ALTER LOGIN [test] DISABLE GO USE [master] GO ALTER DATABASE [test] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;--將數(shù)據(jù)庫(kù)設(shè)置成單用戶并回滾當(dāng)前連接 USE [test];---保持連接操作,防止其它用戶此時(shí)進(jìn)行連接 GO
3.執(zhí)行checkpoint刷新所有臟頁(yè)
CHECKPOINT ---返回當(dāng)前buffer中每個(gè)數(shù)據(jù)庫(kù)所占的buffer大小和buffer中臟頁(yè)的大小 WITH CTE1 AS ( SELECT COUNT(*) * 8 / 1024 AS dirty_cached_size_MB , COUNT(*) AS dirty_pages, CASE database_id WHEN 32767 THEN 'ResourceDb' ELSE DB_NAME(database_id) END AS database_name FROM sys.dm_os_buffer_descriptors WHERE is_modified = 1 GROUP BY DB_NAME(database_id),database_id ), CET2 AS ( SELECT COUNT(*) * 8 / 1024 AS cached_size_MB , COUNT(*) AS pages, CASE database_id WHEN 32767 THEN 'ResourceDb' ELSE DB_NAME(database_id) END AS database_name FROM sys.dm_os_buffer_descriptors GROUP BY DB_NAME(database_id),database_id ) SELECT CET2.database_name, CET2.cached_size_MB, --CET2.pages, CTE1.dirty_cached_size_MB --CTE1.dirty_pages FROM CTE1 INNER JOIN CET2 ON CTE1.database_name = CET2.database_name ---將數(shù)據(jù)庫(kù)選項(xiàng)改成多用戶訪問(wèn) ALTER DATABASE [test] SET MULTI_USER;
4.生成數(shù)據(jù)庫(kù)腳本
5.重命名舊的數(shù)據(jù)庫(kù)
注意:如果數(shù)據(jù)庫(kù)是在alwayson中,需要先從可用性數(shù)據(jù)庫(kù)中刪除,否則無(wú)法重命名數(shù)據(jù)庫(kù)。
/* 1.斷開(kāi)數(shù)據(jù)庫(kù)所有連接同時(shí)禁止新的連接進(jìn)來(lái) 2.比如禁止登入用戶、將實(shí)例設(shè)為單用戶模式等。 */ ----1.設(shè)置數(shù)據(jù)庫(kù)脫機(jī) USE [master] ALTER DATABASE [test] SET OFFLINE WITH ROLLBACK IMMEDIATE; ----2.手動(dòng)修改數(shù)據(jù)庫(kù)物理文件名,例如將test.mdf改成test_old.mdf ----3.語(yǔ)句修改 USE [master] ALTER DATABASE [test] MODIFY FILE (NAME = test, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\test_old.mdf'); GO ALTER DATABASE [test] MODIFY FILE (NAME = test_log, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\test_old_log.ldf'); GO ---4.設(shè)置數(shù)據(jù)庫(kù)在線 USE [master] ALTER DATABASE [test] SET ONLINE ----5.修改數(shù)據(jù)庫(kù)邏輯文件名 USE [test] GO ALTER DATABASE [test] MODIFY FILE (NAME=N'test', NEWNAME=N'test_old') GO USE [test] GO ALTER DATABASE [test] MODIFY FILE (NAME=N'test_log', NEWNAME=N'test_old_log') GO ----6.重命名數(shù)據(jù)庫(kù) USE [master] EXEC sp_renamedb N'test', N'test_old'; ----7.查詢 SELECT * FROM sys.master_files WHERE database_id = DB_ID('test_old');
6.創(chuàng)建新的數(shù)據(jù)庫(kù)同時(shí)導(dǎo)入腳本到新的數(shù)據(jù)庫(kù)
如果同時(shí)導(dǎo)出表結(jié)構(gòu)和數(shù)據(jù)在ssms工具中執(zhí)行可能會(huì)因?yàn)槟_本過(guò)大無(wú)法執(zhí)行,可以使用sqlcmd工具執(zhí)行腳本導(dǎo)入,具體方法可以百度一下。當(dāng)然還有其他方法就是只導(dǎo)出表結(jié)構(gòu)然后通過(guò)“導(dǎo)出數(shù)據(jù)\導(dǎo)入數(shù)據(jù)”的方法同步數(shù)據(jù)。
注意:如果使用“導(dǎo)出數(shù)據(jù)\導(dǎo)入數(shù)據(jù)”的方法同步數(shù)據(jù),注意勾選“啟用標(biāo)示插入”
7.其它
1.如果存在alwayson記得將新的數(shù)據(jù)庫(kù)加入到可用性數(shù)據(jù)庫(kù)組中。
2.將新的數(shù)據(jù)庫(kù)加入到備份作業(yè)中。
3.對(duì)比新舊兩個(gè)數(shù)據(jù)庫(kù)的表數(shù)量是否相同。
4.配置登入用戶新的數(shù)據(jù)庫(kù)權(quán)限。
總結(jié)
內(nèi)存表是2014新引入的功能所以對(duì)于新功能的第一個(gè)版本使用要比較慎重,特別是在線上環(huán)境。雖然在上線之前做過(guò)測(cè)試,但是顯然備份這塊的測(cè)試往往比較容易被忽略因?yàn)闆](méi)有線上的這種環(huán)境。好在是這次影響的是一個(gè)新上的項(xiàng)目數(shù)據(jù)量和并發(fā)都很小且允許節(jié)假日停機(jī)維護(hù);如果是非常大的系統(tǒng)對(duì)于需要導(dǎo)入導(dǎo)出數(shù)據(jù)肯定是非常頭疼的事情關(guān)鍵還得看允許停機(jī)的時(shí)長(zhǎng)。因?yàn)樽约涸谏a(chǎn)環(huán)境踩了坑,寫(xiě)這篇文章希望后面的人可以避免踩坑。
備注:內(nèi)存表在2014版本的alwayson中無(wú)法同步到輔助副本,這就導(dǎo)致了它的作用大打折扣,2016版本可以同步到輔助副本,建議有條件的直接上2016。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- SQL語(yǔ)句實(shí)現(xiàn)查詢SQL Server內(nèi)存使用狀況
- 優(yōu)化SQL Server的內(nèi)存占用之執(zhí)行緩存
- SQL Server 數(shù)據(jù)頁(yè)緩沖區(qū)的內(nèi)存瓶頸分析
- SqlServer如何通過(guò)SQL語(yǔ)句獲取處理器(CPU)、內(nèi)存(Memory)、磁盤(Disk)以及操作系統(tǒng)相關(guān)信息
- SQL Server 2008 R2占用cpu、內(nèi)存越來(lái)越大的兩種解決方法
- 解決SQL Server虛擬內(nèi)存不足情況
- 揭秘SQL Server 2014有哪些新特性(1)-內(nèi)存數(shù)據(jù)庫(kù)
- 淺談SQL Server 對(duì)于內(nèi)存的管理[圖文]
- SQL Server內(nèi)存遭遇操作系統(tǒng)進(jìn)程壓榨案例分析
- sql server學(xué)習(xí)基礎(chǔ)之內(nèi)存初探
相關(guān)文章
和表值函數(shù)連接引發(fā)的性能問(wèn)題分析
最近調(diào)優(yōu)過(guò)程中遇到一個(gè)問(wèn)題,就是表值函數(shù)作為連接中的一部分時(shí),可能會(huì)引起麻煩,本文會(huì)簡(jiǎn)單闡述表值函數(shù)是什么,以及為什么使用表值函數(shù)進(jìn)行連接時(shí)會(huì)引發(fā)性能問(wèn)題2015-02-02探討Sql Server中的declare基本知識(shí)
這篇文章主要探討Sql Server中的declare基本知識(shí),實(shí)戰(zhàn)探討主要來(lái)源于觸發(fā)器的Demo,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-07-07將一個(gè)表中個(gè)某一列修改為自動(dòng)增長(zhǎng)的方法
如果表中沒(méi)有數(shù)據(jù)可以使用 drop column然后再add column,如果存在一部分?jǐn)?shù)據(jù)可以使用本文提供的第二種解決方法2014-09-09SqlServer2012中LEAD函數(shù)簡(jiǎn)單分析
SQL SERVER 2012 T-SQL新增幾個(gè)聚合函數(shù): FIRST_VALUE LAST_VALUE LEAD LAG,今天我們首先來(lái)簡(jiǎn)單分析下LEAD,希望對(duì)大家有所幫助,能夠盡快熟悉這個(gè)聚合函數(shù)2014-08-08SQL Server誤區(qū)30日談 第2天 DBCC CHECKDB會(huì)導(dǎo)致阻塞
在SQL Server 2000中,這個(gè)命令阻止事務(wù)日志截?cái)鄬?huì)導(dǎo)致日志不正常增長(zhǎng)的相關(guān)問(wèn)題,但對(duì)于SQL Server 2005來(lái)說(shuō),這個(gè)命令就會(huì)導(dǎo)致快照相關(guān)的問(wèn)題(具體請(qǐng)往下看)。2013-01-01SQL Server創(chuàng)建數(shù)據(jù)庫(kù)和數(shù)據(jù)表的相關(guān)約束實(shí)現(xiàn)方法
這篇文章主要介紹了SQL Server創(chuàng)建數(shù)據(jù)庫(kù)和數(shù)據(jù)表的相關(guān)約束實(shí)現(xiàn)方法,以實(shí)例形式較為詳細(xì)的分析講述了數(shù)據(jù)庫(kù)約束的概念、功能、注意事項(xiàng)與實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11如何使用Visual Studio 2010在數(shù)據(jù)庫(kù)中生成隨機(jī)測(cè)試數(shù)據(jù)
本文主要介紹Visual Studio 2010的Data Generation數(shù)據(jù)生成器的使用方法,需要的朋友可以參考下2014-08-08關(guān)于SQL Server中bit類型字段增刪查改的一些事
在 SQL Server中,用來(lái)處理判斷flag的字段,使用bit類型,下面這篇文章主要給大家介紹了關(guān)于SQL Server中bit類型字段增刪查改的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-09-09