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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM