經過一些調整和優化,4.3已經運行在生產環境,對於不久將會遇到的查詢性能,讀寫分離需求列上日程
讀寫分離需求
對於一個數據庫作了主從發布/訂閱,主庫為DB1,從庫為DB2
所有寫入通過DB1,所有查詢通過DB2,當然也可以通過DB1
CRL內部實現
在CRL內部調用,請求讀和請求寫的方法會標記為Read或Write,然后再通過標記實現不同的數據庫連接訪問對象
如以下代碼
1 /// <summary> 2 /// 返回動態對象的查詢 3 /// </summary> 4 /// <param name="query"></param> 5 /// <returns></returns> 6 internal CallBackDataReader GetQueryDynamicReader(LambdaQueryBase query) 7 { 8 CheckTableCreated(query.__MainType); 9 var sql = ""; 10 query.FillParames(this); 11 sql = query.GetQuery(); 12 sql = _DBAdapter.SqlFormat(sql); 13 System.Data.Common.DbDataReader reader; 14 var compileSp = query.__CompileSp; 15 var db = GetDBHelper(AccessType.Read); 16 if (!compileSp) 17 { 18 if (query.TakeNum > 0) 19 { 20 db.AutoFormatWithNolock = false; 21 } 22 reader = db.ExecDataReader(sql); 23 } 24 else//生成儲過程 25 { 26 string sp = CompileSqlToSp(_DBAdapter.TemplateSp, sql); 27 reader = db.RunDataReader(sp); 28 } 29 query.ExecuteTime = db.ExecuteTime; 30 ClearParame(); 31 return new CallBackDataReader(reader, null, sql); 32 }
GetDBHelper方法將此標記傳到數據訪問對象創建層
在程序啟動處,以Global為例
1 protected void Application_Start(object sender, EventArgs e) 2 { 3 CRL.SettingConfig.UseReadSeparation = true;//啟用主從讀寫分離 4 //配置數據連接 5 CRL.SettingConfig.GetDbAccess = (dbLocation) => 6 { 7 var obj = dbLocation.TagData; 8 if (dbLocation.ShardingDataBase != null)//按分庫判斷 9 { 10 if (dbLocation.ShardingDataBase.Name == "db1") 11 { 12 return WebTest.Code.LocalSqlHelper.TestConnection; 13 } 14 else 15 { 16 return WebTest.Code.LocalSqlHelper.TestConnection2; 17 } 18 } 19 else 20 { 21 //可按type區分數據庫 22 var type2 = dbLocation.ManageType; 23 if (type2 == typeof(Code.MongoDBTestManage)) 24 { 25 return Code.LocalSqlHelper.MongoDB; 26 } 27 if(dbLocation.AccessType== CRL.AccessType.Read)//區分讀寫 28 { 29 return Code.LocalSqlHelper.TestConnection2; 30 } 31 return WebTest.Code.LocalSqlHelper.TestConnection; 32 } 33 }; 34 35 }
這樣就實現了在邏輯調用上實現了讀寫分離
實際調用
啟用主從讀寫分離
CRL.SettingConfig.UseReadSeparation = true;
更改數據
var item = Code.ProductDataManage.Instance.QueryItem(2); item.ProductName = "更改主庫數據為" + DateTime.Now.Second; Code.ProductDataManage.Instance.Update(item);
DB1數據被更改
查詢數據
var item = Code.ProductDataManage.Instance.QueryItem(2); Response.Write("從庫數據2為" + item.ProductName);
查詢出DB2的數據
事務問題
由於主從復制可能存在延遲,在事務中可不想查到臟數據,或者數據在事務中被更改
因此,在事務內需要由主庫查詢
在CRL事務范圍內的查詢,都默認為主庫
此功能測試代碼見文檔/Page/ReadSeparation.aspx
最新源碼見文章底部簽名