discuz X3.1 关于分表 和 分表数据迁移
// *********** 关于读取分表的数据***********
{
// forum_thread 分表代码片段 -- 帖子列表
{
// 定位某个板块的帖子落在哪个表(forum_thread_0)
// ... // 到指定的表(forum_thread_0、forum_thread_1)中,读取帖子列表
// 注意:(分表的时候,要分得刚刚好,同一个板块的帖子不能跨表,不然会查不到)
$threadlist = array_merge($threadlist, C::t('forum_thread')->fetch_all_search($filterarr, $tableid, $start_limit, $_G['tpp'], $_order, '', $indexadd)); // !!!
} // forum_post 分表代码片段 -- 回复列表
{ // 读取某个帖子(forum_post)的内容,并定位改帖子在处于哪个分表(forum_post_0、forum_post_1)
function get_thread_by_tid($tid, $forcetableid = null) {
global $_G; // 加载分表的配置
loadcache('threadtableids');
$threadtableids = array(0);
if(!empty($_G['cache']['threadtableids'])) {
if($forcetableid === null || ($forcetableid > 0 && !in_array($forcetableid, $_G['cache']['threadtableids']))) {
$threadtableids = array_merge($threadtableids, $_G['cache']['threadtableids']);
} else {
$threadtableids = array(intval($forcetableid));
}
} $threadtableids = array_unique($threadtableids);
foreach($threadtableids as $tableid) {
$tableid = $tableid > 0 ? $tableid : 0;
$ret = C::t('forum_thread')->fetch($tid, $tableid);
if($ret) {
$ret['threadtable'] = C::t('forum_thread')->get_table_name($tableid);
$ret['threadtableid'] = $tableid; // 帖子落在哪个表
$ret['posttable'] = 'forum_post'.($ret['posttableid'] ? '_'.$ret['posttableid'] : '');
break;
}
}
} // 分表后:读取某个帖子的回复列表(forum_post)
// 注意:(分表的时候,要分得刚刚好,同一个帖子的回复不能跨表,不然会查不到)
{
foreach(C::t('forum_post')->fetch_all_by_tid_range_position($posttableid, $_G['tid'], $start, $end, $maxposition, $ordertype) as $post) { // ...
if($post['invisible'] != 0) {
$have_badpost = 1;
}
$cachepids[$post[position]] = $post['pid'];
$postarr[$post[position]] = $post;
$lastposition = $post['position'];
}
}
}
} // *********** 关于创建分表和对分表数据进行迁移 ***********
{
// 0. 查看表的状态
{
// SHOW TABLE STATUS LIKE 'pg_common_trade';
$status = DB::fetch_first("SHOW TABLE STATUS LIKE '".str_replace('_', '\_', $tablename)."'");
$status['Data_length'] = $status['Data_length']; // 数据的字节数
$status['Index_length'] = $status['Index_length']; // 索引的字节数
} // 1. 创建目标表
{
$maxtableid = getmaxposttableid(); // 最大分表的ID
DB::query('SET SQL_QUOTE_SHOW_CREATE=0', 'SILENT');
$tableinfo = C::t('forum_post')->show_table_by_tableid(0);
$createsql = $tableinfo['Create Table']; // 表的创建语句
$targettable = $maxtableid + 1;
$newtable = 'forum_post_'.$targettable;
$createsql = str_replace(getposttable(), $newtable, $createsql); // 创建语句
DB::query($createsql); // 创建表
} // 2. 定位要迁移的数据
{
$count = C::t('forum_post')->count_by_first($fromtableid, 1); // 帖子数
if($count) {
$tids = C::t('forum_post')->fetch_all_tid_by_first($fromtableid, 1, 0, 1000); // 帖子id列表,一次迁移1000条
movedate($tids); // 解析迁移
} else {
cpmsg('postsplit_done', 'action=postsplit&operation=optimize&tableid='.$fromtableid, 'form');
}
} // 3. 进行迁移数据
{
function movedate($tids) {
global $sourcesize, $tableid, $movesize, $targettableid, $hash, $tableindex, $threadtableids, $fieldstr, $fromtableid, $posttable_info; $fromtable = getposttable($fromtableid, true);
C::t('forum_post')->move_table($targettableid, $fieldstr, $fromtable, $tids); // 迁移数据
if(DB::errno()) {
C::t('forum_post')->delete_by_tid($targettableid, $tids);
} else {
foreach($threadtableids as $threadtableid) {
// 更新主帖子表的条目 forum_thread
$affected_rows = C::t('forum_thread')->update($tids, array('posttableid' => $targettableid), false, false, $threadtableid);
if($affected_rows == count($tids)) {
break;
}
}
C::t('forum_post')->delete_by_tid($fromtableid, $tids); // 删除主回复表的条目 forum_post
}
$status = helper_dbtool::gettablestatus(getposttable($targettableid, true), false);
$targetsize = $sourcesize + $movesize * 1048576; // 已经迁移的数据
$nowdatasize = $targetsize - $status['Data_length']; // 主表剩余的数量 if($status['Data_length'] >= $targetsize) { // 迁移完毕,进行优化
cpmsg('postsplit_done', 'action=postsplit&operation=optimize&tableid='.$fromtableid, 'form');
} // 循环重定向
cpmsg('postsplit_doing', 'action=postsplit&operation=movepost&fromtable='.$tableid.'&movesize='.$movesize.'&targettable='.$targettableid.'&hash='.$hash.'&tindex='.$tableindex, 'loadingform', array('datalength' => sizecount($status['Data_length']), 'nowdatalength' => sizecount($nowdatasize)));
}
} // 4. 优化
{
$fromtableid = intval($_GET['tableid']);
$optimize = true;
$tablename = getposttable($fromtableid);
if($fromtableid && $tablename != 'forum_post') {
$count = C::t('forum_post')->count_table($fromtableid); // 原表的记录数
if(!$count) {
C::t('forum_post')->drop_table($fromtableid); // 没数据,就进行删除 unset($posttable_info[$fromtableid]);
C::t('common_setting')->update('posttable_info', $posttable_info);
savecache('posttable_info', $posttable_info);
update_posttableids();
$optimize = false;
} }
if($optimize) {
C::t('forum_post')->optimize_table($fromtableid);
}
} //...
class table_forum_post extends discuz_table
{
/**
* 表的列表
*/
public function show_table() {
return DB::fetch_all("SHOW TABLES LIKE '".DB::table('forum_post')."\_%'");
} /**
* 表的创建语句
*/
public function show_table_by_tableid($tableid) {
return DB::fetch_first('SHOW CREATE TABLE %t', array(self::get_tablename($tableid)));
} /**
* 表的列
*/
public function show_table_columns($table) {
$data = array();
$db = &DB::object();
if($db->version() > '4.1') {
$query = $db->query("SHOW FULL COLUMNS FROM ".DB::table($table), 'SILENT');
} else {
$query = $db->query("SHOW COLUMNS FROM ".DB::table($table), 'SILENT');
}
while($field = @DB::fetch($query)) {
$data[$field['Field']] = $field;
}
return $data;
} /**
* 优化表
*/
public function optimize_table($tableid) {
return DB::query('OPTIMIZE TABLE %t', array(self::get_tablename($tableid)), true);
} /**
* 帖子数量
*/
public function count_by_first($tableid, $first) {
return DB::result_first('SELECT count(*) FROM %t WHERE %i', array(self::get_tablename($tableid), DB::field('first', $first)));
} /**
* 帖子id列表
*/
public function fetch_all_tid_by_first($tableid, $first, $start = 0, $limit = 0) {
return DB::fetch_all('SELECT tid FROM %t WHERE first=%d '.DB::limit($start, $limit), array(self::get_tablename($tableid), $first));
} /**
* 迁移数据
*/
public function move_table($tableid, $fieldstr, $fromtable, $tid) {
$tidsql = is_array($tid) ? 'tid IN(%n)' : 'tid=%d';
return DB::query("INSERT INTO %t ($fieldstr) SELECT $fieldstr FROM $fromtable WHERE $tidsql", array(self::get_tablename($tableid), $tid), true);
} /**
* 表的记录数
*/
public function count_table($tableid) {
return DB::result_first('SELECT COUNT(*) FROM %t', array(self::get_tablename($tableid)));
} }
}
discuz X3.1 关于分表 和 分表数据迁移的更多相关文章
- django:删除表后怎么重新数据迁移生成表
1.将对应app下的migrations文件夹下面的除了__init__.py文件外全部删除 2.delete from django_migrations where app='app_name' ...
- 一种可以避免数据迁移的分库分表scale-out扩容方式
原文地址:http://jm-blog.aliapp.com/?p=590 目前绝大多数应用采取的两种分库分表规则 mod方式 dayofweek系列日期方式(所有星期1的数据在一个库/表,或所有?月 ...
- [转]一种可以避免数据迁移的分库分表scale-out扩容方式
原文地址:http://jm-blog.aliapp.com/?p=590 目前绝大多数应用采取的两种分库分表规则 mod方式 dayofweek系列日期方式(所有星期1的数据在一个库/表,或所有?月 ...
- 一种可以避免数据迁移的分库分表scale-out扩容模式
转自: http://jm.taobao.org/ 一种可以避免数据迁移的分库分表scale-out扩容方式 目前绝大多数应用采取的两种分库分表规则 mod方式 dayofweek系列日期方式(所有星 ...
- 用sql从一张表更新数据到另外一张表(多表数据迁移)
update TBL_1 A, TBL_2 B, TBL_3 Cset a.email=c.email_addrwhere a.user_id=b.user_id and b.un_id=c.un_i ...
- Discuz! X3 数据表、数据字段说明
pre_common_admincp_cmenu 后台菜单收藏表 字段名 数据类型 默认值 允许非空 自动递增 备注 id smallint(6) unsigned NO 是 title v ...
- mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.
一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 100 ...
- CSS3/HTML5实现漂亮的分步骤注册登录表单
分步骤的登录注册表单现在也比较多,主要是能提高用户体验,用户可以有选择性的填写相应的表单信息,不至于让用户看到一堆表单望而却步.今天和大家分享的就是一款基于HTML5和CSS3的分步骤注册登录表单,外 ...
- 数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案
作为一种数据存储层面上的水平伸缩解决方案,数据库Sharding技术由来已久,很多海量数据系统在其发展演进的历程中都曾经历过分库分表的Sharding改造阶段.简单地说,Sharding就是将原来单一 ...
随机推荐
- SQL Agent服务无法启动如何破
问题现象 从阿里云上镜像过来的一台的数据库服务器,SQL Agent服务启动不了,提示服务启动后停止.(原数据库服务器是正常的,怀疑跟镜像有关) 如下是系统日志和SQL Agent的日志 SQLSer ...
- MySQL 忘记root密码解决办法
标签:root密码不为空 概述 很多时候mysql安装完root用户的默认密码不为空,这时候就需要通过其它办法登入到mysql重置密码. 步骤 方法1:查看/root/.mysql_secret文件 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6 获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 ...
- Android 解决方法数 65536 (65k) 限制
可能出现的错误信息: Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: ...
- JavaWeb表单数据的获取方式
表单页面 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&q ...
- Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析
这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默 ...
- 获取Linux主机的CPU、内存、主板、BIOS的信息(Centos)
#!/usr/bin/env python #coding:utf-8 import subprocess import re def Cmd_Exec(cmd): ''' 执行获取信息命令 :par ...
- 前端:图文混排-怎么在不使用float的情况下实现想要的效果呢?
异常处理汇总-前端系列 http://www.cnblogs.com/dunitian/p/4523015.html 举个例子 重点:display:flex (参考:http://www.360do ...
- EF-DbUpdateException--实体类和数据库列不对应的解决方案
错误信息 1.VS实体类里面的字段 2数据库里面的字段 猜测是因为字段数不匹配导致的 3删除多余字段 5.结果 错误信息贴上: -------------------------Log_Header- ...
- [C#]想说一说嵌套数组
今天早上,随感而发,随便写了点东西.结果下午的时候看了看评论,吓我一跳.估计是不是写代码的人看散文看得太少了,还是因为现在的人读的书太少了,似乎有有些大惊小怪. 关于Y美女,我声明一下,尽管她很脱俗, ...