SQL Server中避免觸發(fā)鏡像SUSPEND的N種方法
背景:
我們在使用數(shù)據(jù)庫的過程中,很多時(shí)候要追求性能,特別在處理大批量數(shù)據(jù)的時(shí)候更希望快速處理。那么對SQL SERVER而言,數(shù)據(jù)庫實(shí)現(xiàn)大批量插入的優(yōu)化方案,這里特別介紹通過大容量插入的一種方式。
基本原理:
簡單恢復(fù)模式按最小方式記錄大多數(shù)大容量操作,對于完整恢復(fù)模式下的數(shù)據(jù)庫,大容量導(dǎo)入期間執(zhí)行的所有行插入操作被完整地記錄到事務(wù)日志中。如果數(shù)據(jù)導(dǎo)入量較大,會(huì)導(dǎo)致迅速填滿事務(wù)日志。對于大容量導(dǎo)入操作,按最小方式記錄比完整記錄更有效,并減少了大容量導(dǎo)入操作填滿日志空間的可能性,所以性能會(huì)得到極大的提升。
但是,大容量導(dǎo)入中按最小方式記錄日志的前提條件需要滿足:
1. 當(dāng)前沒有復(fù)制表
2. 指定了表鎖定:
注意:鎖定是 SQL Server 數(shù)據(jù)庫引擎用來對多個(gè)用戶同時(shí)訪問同一數(shù)據(jù)塊的操作進(jìn)行同步。當(dāng)事務(wù)修改某個(gè)數(shù)據(jù)塊時(shí),它將持有保護(hù)所做修改的鎖,直到事務(wù)結(jié)束。指定大容量導(dǎo)入操作的表鎖定后,該表將在大容量導(dǎo)入操作期間采取大容量更新 (BU) 鎖定。大容量更新 (BU) 鎖允許多個(gè)線程將數(shù)據(jù)并發(fā)地大容量導(dǎo)入到同一表中,同時(shí)阻止其他不進(jìn)行大容量導(dǎo)入數(shù)據(jù)的進(jìn)程訪問該表。表鎖定可以通過減少表的鎖爭用來提高大容量導(dǎo)入操作的性能。
基本的理論信息還很多,這里不再累述。
在阿里云SQL SERVER的主備架構(gòu)中,使用大容量插入時(shí),使用時(shí)需要特別留意一個(gè)特性需要明確指定,如果不指定,會(huì)觸發(fā)微軟尚未在SQL Server 2008 R2中未修復(fù)的BUG,會(huì)導(dǎo)致鏡像SUSPEND,那么如何來避免各種情況呢? 下面列舉了一些常見的場景:
1、通過ado.net sqlbulkcopy 方式:
只需要將SqlBulkCopy 指定SqlBulkCopyOptions.CheckConstraints就好,數(shù)據(jù)庫指定AdventureWorks2008R2的Person表。舉個(gè)例子:
static void Main() { string srcConnString = "Data Source=(local);Integrated Security=true;Initial Catalog=testdb"; string desConnString = "Data Source=****.sqlserver.rds.aliyuncs.com,3433;User ID=**;Password=**;Initial Catalog=testdb"; SqlConnection srcConnection = new SqlConnection(); SqlConnection desConnection = new SqlConnection(); SqlCommand sqlcmd = new SqlCommand(); SqlDataAdapter da = new SqlDataAdapter(); DataTable dt = new DataTable(); srcConnection.ConnectionString = srcConnString; desConnection.ConnectionString = desConnString; sqlcmd.Connection = srcConnection; sqlcmd.CommandText = @"SELECT top 1000000 [PersonType],[NameStyle],[Title],[FirstName],[MiddleName],[LastName],[Suffix],[EmailPromotion] ,[AdditionalContactInfo],[Demographics],NULL as rowguid,[ModifiedDate] FROM [testdb].[dbo].[Person]"; sqlcmd.CommandType = CommandType.Text; sqlcmd.Connection.Open(); da.SelectCommand = sqlcmd; da.Fill(dt); using (SqlBulkCopy blkcpy = new SqlBulkCopy(desConnString, SqlBulkCopyOptions.CheckConstraints)) //using (SqlBulkCopy blkcpy = new SqlBulkCopy(desConnString, SqlBulkCopyOptions.Default)) { blkcpy.BatchSize = 2000; blkcpy.BulkCopyTimeout = 5000; blkcpy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied); blkcpy.NotifyAfter = 2000; foreach (DataColumn dc in dt.Columns) { blkcpy.ColumnMappings.Add(dc.ColumnName, dc.ColumnName); } try { blkcpy.DestinationTableName = "Person"; blkcpy.WriteToServer(dt); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { sqlcmd.Clone(); srcConnection.Close(); desConnection.Close(); } } } private static void OnSqlRowsCopied( object sender, SqlRowsCopiedEventArgs e) { Console.WriteLine("Copied {0} so far...", e.RowsCopied); }
2、通過jdbc sqlbulkcopy 方式:
只需要在初始化對象時(shí)指定setCheckConstraints屬性為TRUE,例如:
QLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions();
copyOptions.setCheckConstraints(true);
3、通過DTS/SSIS方式:
1. import/export data方式需要先保存SSIS包,然后修改Connection Manager的屬性
2. 直接使用SQL Server Business Intelligence Development Stuidio新建 SSIS包
3、通過BCP方式
1. 先將數(shù)據(jù)BCP出來 BCP ...OUT
BCP testdb.dbo.person Out "bcp_data" /t /N /U **** /P *** /S "****.sqlserver.rds.aliyuncs.com,3433"
2. 然后將數(shù)據(jù)BCP進(jìn)去 BCP...IN ,但需要指定提示:/h "CHECK_CONSTRAINTS"
BCP testdb.dbo.person In "bcp_data" /C /N /q /k /h "CHECK_CONSTRAINTS" /U *** /P *** /b 500 /S "***.sqlserver.rds.aliyuncs.com,3433"
4、通過bulk insert方式(在RDS不可是實(shí)現(xiàn),因?yàn)椴辉试S上傳文件)
BULK INSERT testdb.dbo.person_in FROM N'D:\trace\bcp.txt' WITH ( CHECK_CONSTRAINTS );
四種方式教你在SQL Server中避免觸發(fā)鏡像SUSPEND,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
數(shù)據(jù)庫表的查詢操作實(shí)踐演練(實(shí)驗(yàn)三)
這篇文章主要對數(shù)據(jù)庫表的查詢操作進(jìn)行實(shí)踐演練,針對實(shí)驗(yàn)一和實(shí)驗(yàn)二涉及到的內(nèi)容進(jìn)一步深入學(xué)習(xí),進(jìn)一步理解關(guān)系運(yùn)算,鞏固數(shù)據(jù)庫的基礎(chǔ)知識(shí),感興趣的小伙伴可以參考一下2015-08-08SQLServer"通過端口1433連接到主機(jī)localhost的TCP/IP連接失敗"常見問題的解
今天碰到一個(gè)問題,查了很久,這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Java通過JDBC連接SQLServer?2012出現(xiàn)"通過端口1433連接到主機(jī)localhost的TCP/IP連接失敗"常見問題的解決方案,需要的朋友可以參考下2023-05-05MS SQL Server游標(biāo)(CURSOR)的學(xué)習(xí)使用
使用MS SQL Server這樣久,游標(biāo)一直沒有使用過。以前都是使用WHILE循環(huán)加臨時(shí)表來實(shí)現(xiàn)。剛剛聯(lián)系個(gè)示例了解到游標(biāo)概念與語法2014-06-06遠(yuǎn)程連接阿里云SqlServer 2012 數(shù)據(jù)庫服務(wù)器的圖文教程
在使用 阿里云 上的一些產(chǎn)品時(shí),遇到不少坑,安裝IIS 時(shí),遇到因買的配置過低,虛擬內(nèi)存不足,而導(dǎo)致 IIS 總是安裝失敗,下面小編給大家分享遠(yuǎn)程連接阿里云SqlServer 2012 數(shù)據(jù)庫服務(wù)器的圖文教程,一起看看吧2017-09-0910種Java開發(fā)者編寫SQL語句時(shí)常見錯(cuò)誤
這篇文章主要介紹了10種Java開發(fā)者編寫SQL語句時(shí)常見錯(cuò)誤,當(dāng)Java開發(fā)人員編寫SQL語句時(shí),一切都變得不同了。SQL是一種說明式語言,與面向?qū)ο笏枷牒兔钍剿枷霟o關(guān),需要的朋友可以參考下2015-08-08在SQL Server中遷移數(shù)據(jù)的幾種方法
這篇文章主要介紹了在SQL Server中遷移數(shù)據(jù)的幾種方法,本文給出了6種方法來移動(dòng)、遷移SQL Server中的數(shù)據(jù),需要的朋友可以參考下2014-08-08