在项目中,往往涉及到数据库的版本升级,通常会有两种升级方式,一种是纯代码实现,一种是脚本实现,这里使用脚本升级,这样的升级方式更便于维护

思路

全版本升级,重点在于数据的迁移,这里使用备份原数据库,新建数据库,增删字段,复制数据库的升级思路,其版本控制在脚本中声明,代码在写好之后基本是不会变动的,更利于维护

SQLite修改表语句

  • 创建表 CREATE TABLE 表名 (列名 数据类型 限定符...)
CREATE TABLE Table (ID INTEGER,NAME TEXT);
  • 修改表 ALTER TABLE ...
    命令允许用户重命名或添加新的字段在已有表中,不能从表中删除字段。并且只能在表的末尾添加字段
ALTER TABLE tTable RENAME TO MyTable;
  • 添加一列 ALTER TABLE 表名 ADD COLUMN 列名 数据类型 限定符
ALTER TABLE MyTable ADD COLUMN AGE INTEGER;
  • 删除表 DROP TABLE 表名
DROP TABLE MyTable;

更改表结构的方法:

  1. 当表中没有任何数据时
    删除表
DROP TABLE MyTable;

创建表

CREATE TABLE MyTable ...
  1. 当表中有数据时
    将表名改为临时表
ALTER TABLE MyTable RENAME TO _temp_MyTable;

创建新表

CREATE TABLE MyTable (....);

导入数据

INSERT INTO MyTable SELECT .., .. ,"用空来补充原来不存在的数据" FROM _temp_MyTable;

删除临时表

DROP TABLE _temp_MyTable;

实现

这里沿用设计的数据库,数据库分库已经在项目中包含了
修改BaseDaoFactory,使其支持数据库分库

public class BaseDaoFactory {private static final String TAG = "BaseDaoFactory";private String sqliteDatabasePath;private SQLiteDatabase sqLiteDatabase;private SQLiteDatabase userDatabase;private Map<String, BaseDao> map = Collections.synchronizedMap(new HashMap<String, BaseDao>());private static BaseDaoFactory instance = new BaseDaoFactory();public static BaseDaoFactory getInstance() {return instance;}private BaseDaoFactory() {File file = new File(Environment.getExternalStorageDirectory(), "update");if (!file.exists()) {file.mkdirs();}sqliteDatabasePath = file.getAbsolutePath() + "/user.db";openDatabase();}public synchronized <T extends BaseDao<M>, M> T getDataHelper(Class<T> clazz, Class<M> entityClass) {BaseDao baseDao = null;if (map.get(clazz.getSimpleName()) != null) {return (T) map.get(clazz.getSimpleName());}try {baseDao = clazz.newInstance();baseDao.init(entityClass, sqLiteDatabase);map.put(clazz.getSimpleName(), baseDao);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return (T) baseDao;}public synchronized <T extends BaseDao<M>, M> T getUserHelper(Class<T> clazz, Class<M> entityClass) {openUserDatabase(getPath());BaseDao baseDao = null;//反射得到对象类型try {baseDao = clazz.newInstance();baseDao.init(entityClass, userDatabase);map.put(clazz.getSimpleName(), baseDao);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return (T) baseDao;}private void openDatabase() {//打开数据库,如果不存在则创建sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqliteDatabasePath, null);}public String getPath() {UserDao userDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, User.class);if (userDao == null) {return null;}User currentUser = userDao.getCurrentUser();if (currentUser == null) {return null;}File file = new File(Environment.getExternalStorageDirectory(), "update");if (!file.exists()) {file.mkdirs();}File childFile = new File(file.getAbsolutePath(), currentUser.getUser_id());if(!childFile.exists()){childFile.mkdirs();}return file.getAbsolutePath() + "/" + currentUser.getUser_id() + "/logic.db";
}private void openUserDatabase(String userDBPath) {//打开数据库,如果不存在则创建userDatabase = SQLiteDatabase.openOrCreateDatabase(userDBPath, null);}
}

创建数据库脚本

public class CreateDb {//数据库表名private String name;//创建表的sql语句集合private List<String> sqlCreates;public CreateDb(Element ele) {name = ele.getAttribute("name");sqlCreates = new ArrayList<String>();NodeList sqls = ele.getElementsByTagName("sql_createTable");for (int i = 0; i < sqls.getLength(); i++) {String sqlCreate = sqls.item(i).getTextContent();this.sqlCreates.add(sqlCreate);}}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<String> getSqlCreates() {return sqlCreates;}public void setSqlCreates(List<String> sqlCreates) {this.sqlCreates = sqlCreates;}
}

数据库升级创建表脚本

public class CreateVersion {//版本信息private String version;//创建数据库表脚本private List<CreateDb> createDbs;public CreateVersion(Element ele) {version = ele.getAttribute("version");createDbs = new ArrayList<CreateDb>();NodeList cs = ele.getElementsByTagName("createDb");for (int i = 0; i < cs.getLength(); i++) {Element ci = (Element) (cs.item(i));CreateDb cd = new CreateDb(ci);this.createDbs.add(cd);}}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;}public List<CreateDb> getCreateDbs() {return createDbs;}public void setCreateDbs(List<CreateDb> createDbs) {this.createDbs = createDbs;}
}

复制单个文件(可更名复制)

public class FileUtil {public static void CopySingleFile(String oldPathFile, String newPathFile) {try {int bytesum = 0;int byteread = 0;File oldfile = new File(oldPathFile);File newFile = new File(newPathFile);File parentFile = newFile.getParentFile();if (!parentFile.exists()) {parentFile.mkdirs();}//文件存在时if (oldfile.exists()) {InputStream inStream = new FileInputStream(oldPathFile);FileOutputStream fs = new FileOutputStream(newPathFile);byte[] buffer = new byte[1024];while ((byteread = inStream.read(buffer)) != -1) {bytesum += byteread; //字节数 文件大小fs.write(buffer, 0, byteread);}inStream.close();}} catch (Exception e) {e.printStackTrace();}}
}

更新数据库脚本

public class UpdateDb {//数据库名称private String dbName;private List<String> sqlBefores;private List<String> sqlAfters;public UpdateDb(Element ele) {dbName = ele.getAttribute("name");sqlBefores = new ArrayList<String>();sqlAfters = new ArrayList<String>();NodeList sqlsBefore = ele.getElementsByTagName("sql_before");for (int i = 0; i < sqlsBefore.getLength(); i++) {String sql_before = sqlsBefore.item(i).getTextContent();this.sqlBefores.add(sql_before);}NodeList sqlsAfter = ele.getElementsByTagName("sql_after");for (int i = 0; i < sqlsAfter.getLength(); i++) {String sql_after = sqlsAfter.item(i).getTextContent();this.sqlAfters.add(sql_after);}}public String getDbName() {return dbName;}public void setDbName(String dbName) {this.dbName = dbName;}public List<String> getSqlBefores() {return sqlBefores;}public void setSqlBefores(List<String> sqlBefores) {this.sqlBefores = sqlBefores;}public List<String> getSqlAfters() {return sqlAfters;}public void setSqlAfters(List<String> sqlAfters) {this.sqlAfters = sqlAfters;}
}

升级更新数据库

public class UpdateDbXml {//升级脚本列表private List<UpdateStep> updateSteps;//升级版本private List<CreateVersion> createVersions;public UpdateDbXml(Document document) {// 获取升级脚本NodeList updateSteps = document.getElementsByTagName("updateStep");this.updateSteps = new ArrayList<UpdateStep>();for (int i = 0; i < updateSteps.getLength(); i++) {Element ele = (Element) (updateSteps.item(i));UpdateStep step = new UpdateStep(ele);this.updateSteps.add(step);}//获取各升级版本NodeList createVersions = document.getElementsByTagName("createVersion");this.createVersions = new ArrayList<CreateVersion>();for (int i = 0; i < createVersions.getLength(); i++) {Element ele = (Element) (createVersions.item(i));CreateVersion cv = new CreateVersion(ele);this.createVersions.add(cv);}}public List<UpdateStep> getUpdateSteps() {return updateSteps;}public void setUpdateSteps(List<UpdateStep> updateSteps) {this.updateSteps = updateSteps;}public List<CreateVersion> getCreateVersions() {return createVersions;}public void setCreateVersions(List<CreateVersion> createVersions) {this.createVersions = createVersions;}
}

数据库升级脚本信息

public class UpdateStep {//旧版本private String versionFrom;//新版本private String versionTo;//更新数据库脚本private List<UpdateDb> updateDbs;public UpdateStep(Element ele) {versionFrom = ele.getAttribute("versionFrom");versionTo = ele.getAttribute("versionTo");updateDbs = new ArrayList<UpdateDb>();NodeList dbs = ele.getElementsByTagName("updateDb");for (int i = 0; i < dbs.getLength(); i++) {Element db = (Element) (dbs.item(i));UpdateDb updateDb = new UpdateDb(db);this.updateDbs.add(updateDb);}}public List<UpdateDb> getUpdateDbs() {return updateDbs;}public void setUpdateDbs(List<UpdateDb> updateDbs) {this.updateDbs = updateDbs;}public String getVersionFrom() {return versionFrom;}public void setVersionFrom(String versionFrom) {this.versionFrom = versionFrom;}public String getVersionTo() {return versionTo;}public void setVersionTo(String versionTo) {this.versionTo = versionTo;}
}

数据库脚本管理

public class UpdateManager {private static final String TAG = "UpdateManager";private static final String INFO_FILE_DIV = "/";private List<User> userList;private File parentFile = new File(Environment.getExternalStorageDirectory(), "update");private File bakFile = new File(parentFile, "backDb");public UpdateManager() {if (!parentFile.exists()) {parentFile.mkdirs();}if (!bakFile.exists()) {bakFile.mkdirs();}}public void checkThisVersionTable(Context context) {UserDao userDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, User.class);userList = userDao.query(new User());UpdateDbXml xml = readDbXml(context);String thisVersion = getVersionName(context);CreateVersion thisCreateVersion = analyseCreateVersion(xml, thisVersion);try {executeCreateVersion(thisCreateVersion, true);} catch (Exception e) {}}//开始升级public void startUpdateDb(Context context) {UpdateDbXml updateDbxml = readDbXml(context);if (getLocalVersionInfo()) {//拿到当前版本String thisVersion = getVersionName(context);//拿到上一个版本String lastVersion = lastBackupVersion;UpdateStep updateStep = analyseUpdateStep(updateDbxml, lastVersion, thisVersion);if (updateStep == null) {return;}List<UpdateDb> updateDbs = updateStep.getUpdateDbs();CreateVersion createVersion = analyseCreateVersion(updateDbxml, thisVersion);try {//更新每个用户的数据库for (User user : userList) {String logicDbDir = parentFile.getAbsolutePath() + "/update" + "/" + user.getUser_id() + "/logic.db";String logicCopy = bakFile.getAbsolutePath() + "/" + user.getUser_id() + "/logic.db";FileUtil.CopySingleFile(logicDbDir, logicCopy);}//备份总数据库String user = parentFile.getAbsolutePath() + "/user.db";String user_bak = bakFile.getAbsolutePath() + "/user.db";FileUtil.CopySingleFile(user, user_bak);// 第二步:执行sql_before语句,删除以及备份相关旧表executeDb(updateDbs, -1);// 第三步:检查新表,创建新表executeCreateVersion(createVersion, false);Log.d(TAG, "第三步检查新表完成!");// 第四步:从备份表中恢复数据,恢复后删除备份表executeDb(updateDbs, 1);} catch (Exception e) {e.printStackTrace();}// 第五步:升级成功,删除备份数据库if (userList != null && !userList.isEmpty()) {for (User user : userList) {String logicDbDir = parentFile.getAbsolutePath() + "/update" + "/" + user.getUser_id() + ".db";File file = new File(logicDbDir);if (file.exists()) {file.delete();}}}File userFileBak = new File(bakFile.getAbsolutePath() + "user_bak.db");if (userFileBak.exists()) {userFileBak.delete();}Log.d(TAG, "升级成功");}}//根据建表脚本,核实一遍应该存在的表private void executeCreateVersion(CreateVersion createVersion, boolean isLogic) throws Exception {if (createVersion == null || createVersion.getCreateDbs() == null) {throw new Exception("createVersion or createDbs is null;");}for (CreateDb cd : createVersion.getCreateDbs()) {if (cd == null || cd.getName() == null) {throw new Exception("db or dbName is null when createVersion;");}if (!"logic".equals(cd.getName())) {continue;}// 创建数据库表sqlList<String> sqls = cd.getSqlCreates();SQLiteDatabase sqlitedb = null;try {// 逻辑层数据库要做多用户升级if (userList != null && !userList.isEmpty()) {// 多用户建新表for (int i = 0; i < userList.size(); i++) {// 获取dbsqlitedb = getDb(cd, userList.get(i).getUser_id());executeSql(sqlitedb, sqls);sqlitedb.close();}}} catch (Exception e) {e.printStackTrace();} finally {// 关闭数据库if (sqlitedb != null) {sqlitedb.close();}}}}//执行针对db升级的sql集合 type:小于0为建表前,大于0为建表后private void executeDb(List<UpdateDb> updateDbs, int type) throws Exception {if (updateDbs == null) {throw new Exception("updateDbs is null;");}for (UpdateDb db : updateDbs) {if (db == null || db.getDbName() == null) {throw new Exception("db or dbName is null;");}List<String> sqls = null;//更改表if (type < 0) {sqls = db.getSqlBefores();} else if (type > 0) {sqls = db.getSqlAfters();}SQLiteDatabase sqlitedb = null;try {// 逻辑层数据库要做多用户升级if (userList != null && !userList.isEmpty()) {// 多用户表升级for (int i = 0; i < userList.size(); i++) {sqlitedb = getDb(db, userList.get(i).getUser_id());executeSql(sqlitedb, sqls);sqlitedb.close();}}} catch (Exception e) {e.printStackTrace();} finally {if (null != sqlitedb) {sqlitedb.close();}}}}//执行sql语句private void executeSql(SQLiteDatabase sqlitedb, List<String> sqls) throws Exception {// 检查参数if (sqls == null || sqls.size() == 0) {return;}// 事务sqlitedb.beginTransaction();for (String sql : sqls) {sql = sql.replaceAll("\r\n", " ");sql = sql.replaceAll("\n", " ");if (!"".equals(sql.trim())) {try {// Logger.i(TAG, "执行sql:" + sql, false);sqlitedb.execSQL(sql);} catch (SQLException e) {}}}sqlitedb.setTransactionSuccessful();sqlitedb.endTransaction();}//新表插入数据private UpdateStep analyseUpdateStep(UpdateDbXml xml, String lastVersion, String thisVersion) {if (lastVersion == null || thisVersion == null) {return null;}// 更新脚本UpdateStep thisStep = null;if (xml == null) {return null;}List<UpdateStep> steps = xml.getUpdateSteps();if (steps == null || steps.size() == 0) {return null;}for (UpdateStep step : steps) {if (step.getVersionFrom() == null || step.getVersionTo() == null) {} else {// 升级来源以逗号分隔String[] lastVersionArray = step.getVersionFrom().split(",");if (lastVersionArray != null && lastVersionArray.length > 0) {for (int i = 0; i < lastVersionArray.length; i++) {// 有一个配到update节点即升级数据if (lastVersion.equalsIgnoreCase(lastVersionArray[i]) && step.getVersionTo().equalsIgnoreCase(thisVersion)) {thisStep = step;break;}}}}}return thisStep;}//根据xml对象获取对应要修改的db文件private SQLiteDatabase getDb(UpdateDb db, String userId) {return getDb(db.getDbName(), userId);}private SQLiteDatabase getDb(CreateDb db, String userId) {return getDb(db.getName(), userId);}//创建数据库,获取数据库对应的SQLiteDatabaseprivate SQLiteDatabase getDb(String dbname, String userId) {String dbfilepath = null;SQLiteDatabase sqlitedb = null;File file = new File(parentFile, userId);if (!file.exists()) {file.mkdirs();}if (dbname.equalsIgnoreCase("logic")) {dbfilepath = file.getAbsolutePath() + "/logic.db";// logic对应的数据库路径} else if (dbname.equalsIgnoreCase("user")) {dbfilepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/user.db";// service对应的数据库}if (dbfilepath != null) {File f = new File(dbfilepath);f.mkdirs();if (f.isDirectory()) {f.delete();}sqlitedb = SQLiteDatabase.openOrCreateDatabase(dbfilepath, null);}return sqlitedb;}//解析出对应版本的建表脚本private CreateVersion analyseCreateVersion(UpdateDbXml xml, String version) {CreateVersion cv = null;if (xml == null || version == null) {return cv;}List<CreateVersion> createVersions = xml.getCreateVersions();if (createVersions != null) {for (CreateVersion item : createVersions) {// 如果表相同则要支持xml中逗号分隔String[] createVersion = item.getVersion().trim().split(",");for (int i = 0; i < createVersion.length; i++) {if (createVersion[i].trim().equalsIgnoreCase(version)) {cv = item;break;}}}}return cv;}//读取升级xmlprivate UpdateDbXml readDbXml(Context context) {InputStream is = null;Document document = null;try {is = context.getAssets().open("updateXml.xml");DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();document = builder.parse(is);} catch (Exception e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}if (document == null) {return null;}UpdateDbXml xml = new UpdateDbXml(document);return xml;}//获取APK版本号public String getVersionName(Context context) {String versionName = null;try {PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);versionName = info.versionName;} catch (PackageManager.NameNotFoundException e) {}return versionName;}//保存下载APK版本信息public boolean saveVersionInfo(Context context, String newVersion) {boolean ret = false;FileWriter writer = null;try {writer = new FileWriter(new File(parentFile, "update.txt"), false);writer.write("V003" + INFO_FILE_DIV + "V002");writer.flush();ret = true;} catch (IOException e) {} finally {if (writer != null) {try {writer.close();} catch (IOException e) {e.printStackTrace();}}}return ret;}//获取本地版本相关信息private String existVersion;private String lastBackupVersion;private boolean getLocalVersionInfo() {boolean ret = false;File file = new File(parentFile, "update.txt");if (file.exists()) {int byteread = 0;byte[] tempbytes = new byte[100];StringBuilder stringBuilder = new StringBuilder();InputStream in = null;try {in = new FileInputStream(file);while ((byteread = in.read(tempbytes)) != -1) {stringBuilder.append(new String(tempbytes, 0, byteread));}String[] infos = stringBuilder.toString().split(INFO_FILE_DIV);if (infos.length == 2) {existVersion = infos[0];lastBackupVersion = infos[1];ret = true;}} catch (Exception e) {} finally {if (null != in) {try {in.close();} catch (IOException e) {e.printStackTrace();}in = null;}}}return ret;}
}

模拟用户登录

@DbTable("tb_user")
public class User {public String name;public String password;public String user_id;public Integer status;public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}public String getUser_id() {return user_id;}public void setUser_id(String user_id) {this.user_id = user_id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
public class UserDao extends BaseDao<User> {private static final String TAG = "UserDao";@Overridepublic String createTable() {return "create table if not exists tb_user( name TEXT, password TEXT, user_id Text,status Integer);";}@Overridepublic long insert(User entity) {List<User> list = query(new User());User where = null;for (User user : list) {where = new User();where.setUser_id(user.getUser_id());user.setStatus(0);update(user, where);}Log.d(TAG, "用户" + entity.getName() + "登录");entity.setStatus(1);return super.insert(entity);}//得到当前登录的Userpublic User getCurrentUser() {User user = new User();user.setStatus(1);List<User> list = query(user);if (list.size() > 0) {return list.get(0);}return null;}
}

模拟用户下载数据

@DbTable("tb_photo")
public class Photo {public String time;public String path;public String getTime() {return time;}public void setTime(String time) {this.time = time;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}
}
public class PhotoDao extends BaseDao<Photo> {@Overridepublic String createTable() {return "create table if not exists tb_photo(\n" +"                time TEXT,\n" +"                path TEXT,\n" +"                to_user TEXT\n" +"                )";}
}

测试

public class MainActivity extends AppCompatActivity {UpdateManager updateManager;UserDao baseDao;int i = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);updateManager = new UpdateManager();baseDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, User.class);}public void login(View view) {User user = new User();user.setName("V00" + (i++));user.setPassword("123456");user.setName("jack" + i);user.setUser_id("N000" + i);baseDao.insert(user);updateManager.checkThisVersionTable(this);}public void insert(View view) {Photo photo = new Photo();photo.setPath("data/data/my.jpg");SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");photo.setTime(dateFormat.format(new Date()));PhotoDao photoDao = BaseDaoFactory.getInstance().getUserHelper(PhotoDao.class, Photo.class);photoDao.insert(photo);}public void write(View view) {//写入版本updateManager.saveVersionInfo(this, "V002");}public void update(View view) {updateManager.checkThisVersionTable(this);updateManager.startUpdateDb(this);}
}

在Assets文件夹加入升级脚本

<!-- 请保证该文档一定是 UTF-8编码 -->
<updateXml><createVersion version="V003"><createDb name="user"><!-- 设备与软件关联信息 --><sql_createTable>create table if not exists tb_user(name TEXT,password TEXT,loginName TEXT,lastLoginTime,user_id Integer primary key);</sql_createTable></createDb><createDb name="logic"><!-- 设备与软件关联信息 --><sql_createTable>create table if not exists tb_photo(time TEXT,path TEXT,to_user TEXT,sendTime TEXT);</sql_createTable></createDb></createVersion><updateStepversionFrom="V002"versionTo="V003"><updateDb name="logic"><sql_before>alter table tb_photo rename to bak_tb_photo;</sql_before><sql_after>insert into tb_photo(time,path)select time,pathfrom bak_tb_photo;</sql_after><sql_after>drop table if exists bak_tb_photo;</sql_after></updateDb><updateDb name="user"><sql_before>alter table tb_user rename to bak_t_user;</sql_before><sql_after>insert into tb_user(name,password)select name,passwordfrom bak_tb_user;</sql_after><sql_after>drop table if exists bak_t_user;</sql_after></updateDb></updateStep>
</updateXml>

注意当前版本与升级脚本的一致

转载于:https://www.cnblogs.com/cj5785/p/10664611.html

移动架构-数据库分库和全版本升级相关推荐

  1. 数据库分库分表中间件对比(很全)

    数据库(分库分表)中间件对比 分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm. 根据一定的规则把数据文件(MYD)和索引文件( ...

  2. mysql分库分表 ppt_数据库分库分表中间件架构解析.ppt

    数据库分库分表中间件架构解析 Processor(1) Processor(n) MySQL MySQL MySQL Cobar结构 Front-end Communication Applicati ...

  3. 亿级流量网站架构核心技术之“数据库分库分表策略”

    本文节选自<亿级流量网站架构核心技术--跟开涛学搭建高可用高并发系统>一书 张开涛 著 电子工业出版社出版 小编会从留言中选择获赞最多的前五名用户免费送出此书哦!规则见文末. 数据库分库分 ...

  4. 数据库分库分表解决方案汇总

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | butterfly100 来源 | cnblo ...

  5. 数据库分库分表解决方案

    数据库分库分表解决方案 前言 MySQL表大小限制 分表方案 垂直分表 水平分表 按月分表 MySQL分区表 分库方案 按业务分库 按表分库 拆分后的问题及常见的解决方案 垂直拆分 跨库Join问题 ...

  6. 数据库分库分表思路流程

    阅读文本大概需要10分钟. 数据切分 关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库.优化索引, ...

  7. 一文搞懂MySQL数据库分库分表

    如果数据量过大,大家一般会分库分表.分库需要注意的内容比较少,但分表需要注意的内容就多了. 工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过 ...

  8. 数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量...

    当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产 品可供参考,同时很多团队也会选择自主开发实现,而不管是 ...

  9. 转数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7696085 ,转载请注明出处!本文着重介绍sharding切分策略,如果你对数据库sh ...

最新文章

  1. python批量做线性规划(每次的约束条件参数有变换)
  2. 实践卡尔曼滤波--小球追踪
  3. 深度学习——用向量重新组织输入数据
  4. 手绘线条图画机器人_怎么把照片转换成手绘图画?怎么加水印?
  5. java 坦克重叠_【Java】我所知道坦克大战(单机版)之画出坦克的实心圆、让圆动起来、双缓冲解决闪烁问题...
  6. 为什么专家都看好这本书
  7. [LevelDB] 编译和使用
  8. 湘潭大学计算机网络试卷答案,湘潭大学计算机网络试卷
  9. sqlite查到找db文件
  10. 零电压开关(ZVS)电路原理与设计(整理)
  11. 如何编写一个程序,将一个给定的整数插到原本有序的整数序列中,使结果序列仍然有序。
  12. Windows 2000进程细述.
  13. js将HTML导出生成word文档
  14. java mail 回复邮件_JavaMail - 退回邮件( Bounced Messages)
  15. 解决IDEA 打不开问题
  16. 从经济学角度解读人工智能
  17. 麦当劳宣布20年来最大规模收购 提高服务智能化
  18. 大数据离线---网站日志流量分析系统---日志数据原始信息
  19. 爬虫利器 xpath 实践案例
  20. 五种外观缺陷检测方法,不分优劣,应用场景不同使用的技术不同

热门文章

  1. vue-cli3.0使用及配置(部分)
  2. 一、Objective-C之Runtime的概念
  3. console.log()与alert()的区别
  4. HTML5基础一:常用布局标签
  5. 别说我不会玩,我来告诉你iPhone有多烂!iPhone缺点集
  6. Linux信号处理机制
  7. 一般一个前端项目完成需要多久_一种按周迭代的敏捷式项目管理方法
  8. @Value和Hibernate问题
  9. vue如何过滤html标签,去除富文本中的html标签及vue、react、微信小顺序中的过滤器...
  10. mysql memory=off_MySQL内存调优