// *********** 关于读取分表的数据*********** { // 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