经过一些调整和优化, 4.3 已经运行在生产环境, 对于不久将会遇到的查询性能, 读写分离需求列上日程
对于一个数据库作了主从发布 / 订阅, 主库为 DB1, 从库为 DB2
所有写入通过 DB1, 所有查询通过 DB2, 当然也可以通过 DB1
在 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;
更改数据
- varitem = Code.ProductDataManage.Instance.QueryItem(2);
- item.ProductName ="更改主库数据为"+ DateTime.Now.Second;
- Code.ProductDataManage.Instance.Update(item);
DB1 数据被更改
查询数据
- varitem = Code.ProductDataManage.Instance.QueryItem(2);
- Response.Write("从库数据2为"+ item.ProductName);
查询出 DB2 的数据
由于主从复制可能存在延迟, 在事务中可不想查到脏数据, 或者数据在事务中被更改
因此, 在事务内需要由主库查询
在 CRL 事务范围内的查询, 都默认为主库
此功能测试代码见文档 / Page/ReadSeparation.aspx
最新源码见文章底部签名
来源: http://www.cnblogs.com/hubro/p/6971327.html