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)));
        }

    }
}
时间: 2024-10-22 05:43:06

discuz X3.1 关于分表 和 分表数据迁移的相关文章

django:删除表后怎么重新数据迁移生成表

1.将对应app下的migrations文件夹下面的除了__init__.py文件外全部删除 2.delete from django_migrations where app='app_name' 3.重新执行 python manage.py makemigrations python manage.py migrate 原文地址:https://www.cnblogs.com/gcgc/p/11766329.html

[转]一种可以避免数据迁移的分库分表scale-out扩容方式

原文地址:http://jm-blog.aliapp.com/?p=590 目前绝大多数应用采取的两种分库分表规则 mod方式 dayofweek系列日期方式(所有星期1的数据在一个库/表,或所有?月份的数据在一个库表) 这两种方式有个本质的特点,就是离散性加周期性. 例如以一个表的主键对3取余数的方式分库或分表: 那么随着数据量的增大,每个表或库的数据量都是各自增长.当一个表或库的数据量增长到了一个极限,要加库或加表的时候, 介于这种分库分表算法的离散性,必需要做数据迁移才能完成.例如从3个扩

mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.

一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 10000;优化后:Select id from uinfo_jifen where jifen>600000; 2.应尽量避免在where子句中对字段进行函数操作,这将导致mysql放弃使用索引 select uid from imid where datediff(create_time,'2011-11

sql server 更新表,每天的数据分固定批次设置批次号sql

按表中的字段 UpdateTime 按每天进行编号,每天的编号都从1开始编号,并附带表的主键 cid,把数据存入临时表中 WITH temp AS (SELECT cid,updatetime, ROW_NUMBER() OVER (PARTITION BY CONVERT(varchar(10), UpdateTime, 20) ORDER BY updatetime) AS Row_Num FROM Customer_Transfer ) 从临时表中根据主键cid进行更新 BatchNo,给

数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案

作为一种数据存储层面上的水平伸缩解决方案,数据库Sharding技术由来已久,很多海量数据系统在其发展演进的历程中都曾经历过分库分表的Sharding改造阶段.简单地说,Sharding就是将原来单一数据库按照一定的规则进行切分,把数据分散到多台物理机(我们称之为Shard)上存储,从而突破单机限制,使系统能以Scale-Out的方式应对不断上涨的海量数据,但是这种切分对上层应用来说是透明的,多个物理上分布的数据库在逻辑上依然是一个库.实现Sharding需要解决一系列关键的技术问题,这些问题主

Discuz X3.1微信打通版,发布回复时出现提示:您的请求来路不正确或表单验证串不符,无法提交问题的解决

Discuz X3.1微信打通后,手机上发布回复时出现提示:"您的请求来路不正确或表单验证串不符,无法提交"问题的解决: 找到网站目录下\source\class\helper\helper_form.php: 在此行下面增加红色文字所标注部分即可. if($allowget || ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_GET['formhash']) && $_GET['formhash']

CSS3/HTML5实现漂亮的分步骤注册登录表单

分步骤的登录注册表单现在也比较多,主要是能提高用户体验,用户可以有选择性的填写相应的表单信息,不至于让用户看到一堆表单望而却步.今天和大家分享的就是一款基于HTML5和CSS3的分步骤注册登录表单,外观不用说,非常漂亮.你看一下DEMO就知道了. 这里是在线演示,你可以先看看效果. 接下来我们要来一起看看实现的过程是怎样的.代码有点复杂,主要由HTML代码.CSS3代码以及Javascript代码组成. HTML代码: <form id="msform"> <!--

mysql15--垂直分表水平分表

?分表技术(表的结构不能变) 分表技术有(水平分割和垂直分割) 当一张越来越大时候,即使添加索引还慢的话,我们可以使用分表 以qq用户表来具体的说明一下分表的操作. 思路如图 : 首先我创建三张表 user0 / user1 /user2 , 然后我再创建 uuid表,该表的作用就是提供自增的id, 插入的时候插入到不同的表中去. 走代码: create table user0( id int unsigned primary key , name varchar(32) not null de

【转】document.form.action,表单分向提交

document.form.action,表单分向提交,javascript提交表单 同一个表单可以根据用户的选择,提交给不同的后台处理程序.即,表单的分向提交.如,在编写论坛程序时,如果我们希望实现用户在发送贴子的时候,既发送提交功能又有预览功能时,就会遇到上述问题.即,当用户点击提交按钮时,我们希望表单提交给"提交"处理程序:而当用户点击预览按钮时,我们希望表单提交给"预览"处理程序.那么,如何实现上述功能呢?下面代码可以很好的解决这个问题. <form