数据库中有三种类型的表,分钟粒度、小时粒度、天粒度,现在需要为三种类型的表涉及分区自动维护的存储过程,首先创建元数据信息表:
mysql> select * from op_tb_partition; +-------------------------------------+ | tb_name | +-------------------------------------+ | NL_BRS_AJAX_ERRORS_HOST_MIN | | NL_BRS_AJAX_ERRORS_URL_MIN | | NL_BRS_AJAX_HOST_MIN | | NL_BRS_AJAX_OVERVIEW_MIN | | NL_BRS_AJAX_PAGE_MIN | | NL_BRS_AJAX_URL_MIN | | NL_BRS_APPLICATION_OVERVIEW_BIN_MIN | | NL_BRS_APPLICATION_OVERVIEW_MIN | | NL_BRS_COMBO_MIN | | NL_BRS_GEO_MIN | | NL_BRS_JS_ERRORS_BROWSER_MIN | | NL_BRS_JS_ERRORS_MIN | | NL_BRS_JS_ERRORS_PAGE_MIN | | NL_BRS_PAGE_HOST_MIN | | NL_BRS_PAGE_URL_BIN_MIN | | NL_BRS_PAGE_URL_MIN | | NL_BRS_WEB_BROWSER_MIN | | NL_BRS_WEB_BROWSER_VERSION_MIN | +-------------------------------------+ 18 rows in set (0.00 sec) mysql> select * from op_tb_partition_hour; +--------------------------------------+ | tb_name | +--------------------------------------+ | NL_BRS_AJAX_ERRORS_HOST_HOUR | | NL_BRS_AJAX_ERRORS_URL_HOUR | | NL_BRS_AJAX_HOST_HOUR | | NL_BRS_AJAX_OVERVIEW_HOUR | | NL_BRS_AJAX_PAGE_HOUR | | NL_BRS_AJAX_URL_HOUR | | NL_BRS_APPLICATION_OVERVIEW_BIN_HOUR | | NL_BRS_APPLICATION_OVERVIEW_HOUR | | NL_BRS_COMBO_HOUR | | NL_BRS_GEO_HOUR | | NL_BRS_JS_ERRORS_BROWSER_HOUR | | NL_BRS_JS_ERRORS_HOUR | | NL_BRS_JS_ERRORS_PAGE_HOUR | | NL_BRS_PAGE_HOST_HOUR | | NL_BRS_PAGE_URL_BIN_HOUR | | NL_BRS_PAGE_URL_HOUR | | NL_BRS_WEB_BROWSER_HOUR | | NL_BRS_WEB_BROWSER_VERSION_HOUR | +--------------------------------------+ 18 rows in set (0.06 sec) mysql> select * from op_tb_partition_day; +-------------------------------------+ | tb_name | +-------------------------------------+ | NL_BRS_AJAX_ERRORS_HOST_DAY | | NL_BRS_AJAX_ERRORS_URL_DAY | | NL_BRS_AJAX_HOST_DAY | | NL_BRS_AJAX_OVERVIEW_DAY | | NL_BRS_AJAX_PAGE_DAY | | NL_BRS_AJAX_URL_DAY | | NL_BRS_APPLICATION_OVERVIEW_BIN_DAY | | NL_BRS_APPLICATION_OVERVIEW_DAY | | NL_BRS_COMBO_DAY | | NL_BRS_GEO_DAY | | NL_BRS_JS_ERRORS_BROWSER_DAY | | NL_BRS_JS_ERRORS_DAY | | NL_BRS_JS_ERRORS_PAGE_DAY | | NL_BRS_PAGE_HOST_DAY | | NL_BRS_PAGE_URL_BIN_DAY | | NL_BRS_PAGE_URL_DAY | | NL_BRS_WEB_BROWSER_DAY | | NL_BRS_WEB_BROWSER_VERSION_DAY | +-------------------------------------+ 18 rows in set (0.00 sec)
创建日志表,用于记录存储过程执行的详细信息,如下:
mysql> desc change_partition_log; +------------+---------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +------------+---------------+------+-----+-------------------+-----------------------------+ | tm_base | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | | op_type | varchar(20) | YES | | NULL | | | change_sql | varchar(2000) | YES | | NULL | | +------------+---------------+------+-----+-------------------+-----------------------------+ 3 rows in set (0.02 sec)
编写分钟表的存储过程,包括添加分区和删除分区两个存储过程及调度event,如下:
-- 添加分区的存储过程 DELIMITER ;; CREATE PROCEDURE lens_browser_data.`add_partition_min`() BEGIN declare table_name varchar(255) default 0; declare tmp_sql varchar(255) default ""; declare max_day_now varchar(255) default ""; declare max_day_will varchar(255) default ""; declare difference int default 0; declare i int default 1; declare tmp_day varchar(255) default ""; declare tmp_day_value varchar(255) default ""; declare par_name varchar(255) default ""; declare alter_sql varchar(255) default ""; declare done int default -1; declare myCursor cursor for select tb_name from op_tb_partition; declare continue handler for not found set done = 1; set @tmp_sql = concat("select date_format(date_add(now(),interval 6 day), '%Y%m%d') into @max_day_will"); prepare stmt from @tmp_sql; execute stmt; open myCursor; myLoop:LOOP fetch myCursor into table_name; if done = 1 then leave myLoop; end if; set @tmp_sql = concat("SELECT max(substring(partition_name,5)) FROM INFORMATION_SCHEMA.partitions WHERE TABLE_NAME = '",table_name,"' and TABLE_SCHEMA ='lens_browser_data' into @max_day_now"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select to_days('",@max_day_will,"') - to_days('",@max_day_now,"') into @difference"); prepare stmt from @tmp_sql; execute stmt; while i <= @difference do set @tmp_sql = concat("select date_format(date_add('",@max_day_now,"' ,interval ",i," day), '%Y%m%d') into @tmp_day"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select nl_to_timestamp(date_format(date_add('",@max_day_now,"' ,interval 1+",i," day), '%Y%m%d')) into @tmp_day_value"); prepare stmt from @tmp_sql; execute stmt; set @par_name = concat("par_",@tmp_day); set @alter_sql = concat("alter table ",table_name," add partition(partition ",@par_name," values less than (",@tmp_day_value,"))"); insert into change_partition_log values( now(),"add_min", @alter_sql); prepare stmt from @alter_sql; execute stmt; set i = i+1; end while; set i = 1; end loop myLoop; close myCursor; END ;; DELIMITER ; -- 删除分区的存储过程 DELIMITER ;; CREATE PROCEDURE lens_browser_data.`del_partition_min`() BEGIN declare table_name varchar(255) default 0; declare tmp_sql varchar(255) default ""; declare max_par_now varchar(255) default ""; declare par_del_num varchar(255) default ""; declare par_del varchar(255) default ""; declare alter_sql varchar(255) default ""; declare i int default 0; declare done int default -1; declare myCursor cursor for select tb_name from op_tb_partition; declare continue handler for not found set done = 1; open myCursor; myLoop:LOOP fetch myCursor into table_name; if done = 1 then leave myLoop; end if; set @tmp_sql = concat("select count(*) FROM INFORMATION_SCHEMA.partitions WHERE TABLE_NAME = '",table_name,"' and TABLE_SCHEMA ='lens_browser_data' into @max_par_now"); prepare stmt from @tmp_sql; execute stmt; set @par_del_num = @max_par_now-31-7; while i < @par_del_num do set @tmp_sql = concat("select partition_name from INFORMATION_SCHEMA.partitions where TABLE_SCHEMA ='lens_browser_data' and table_name='",table_name,"' order by partition_name limit 1 into @par_del"); prepare stmt from @tmp_sql; execute stmt; set @alter_sql = concat("alter table ",table_name," drop partition ",@par_del); prepare stmt from @alter_sql; execute stmt; insert into change_partition_log values(now(),"drop_min", concat(i,"--",@par_del,"--",@alter_sql)); set i = i+1; end while; set i = 0; end loop myLoop; close myCursor; END ;; DELIMITER ; -- 调度Event DELIMITER ;; CREATE EVENT `manager_partition_min` ON SCHEDULE EVERY 1 DAY STARTS '2015-09-07 00:30:00' ON COMPLETION PRESERVE ENABLE DO BEGIN call add_partition_min; call del_partition_min; END ;; DELIMITER ;
编写小时表的存储过程,包括添加分区和删除分区两个存储过程及调度event,如下:
-- 添加分区的存储过程 DELIMITER ;; CREATE PROCEDURE lens_browser_data.`add_partition_hour`() BEGIN declare table_name varchar(255) default 0; declare tmp_sql varchar(255) default ""; declare diff int default 0; declare diffenence int default 0; declare last_weekend varchar(255) default ""; declare max_weekend_now varchar(255) default ""; declare max_weekend_will varchar(255) default ""; declare tmp_weekend varchar(255) default ""; declare tmp_weekend_value varchar(255) default ""; declare tmp_weekend_before varchar(255) default ""; declare tmp_year varchar(255) default ""; declare tmp_week varchar(255) default ""; declare difference int default 0; declare i int default 1; declare alter_sql varchar(255) default ""; declare done int default -1; declare myCursor cursor for select tb_name from op_tb_partition_hour; declare continue handler for not found set done = 1; set @tmp_sql = concat("select dayofweek(now())-1 into @diff"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select date_format(date_add(now(),interval -",@diff," day), '%Y%m%d') into @last_weekend"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select date_format(date_add('",@last_weekend,"' ,interval 7*3 day), '%Y%m%d') into @max_weekend_will"); prepare stmt from @tmp_sql; execute stmt; open myCursor; myLoop:LOOP fetch myCursor into table_name; if done = 1 then leave myLoop; end if; set @tmp_sql = concat("select nl_to_date(max(PARTITION_DESCRIPTION+0)) from INFORMATION_SCHEMA.partitions WHERE TABLE_NAME = '",table_name,"' and TABLE_SCHEMA ='lens_browser_data' into @max_weekend_now"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select (to_days('",@max_weekend_will,"') - to_days('",@max_weekend_now,"')) div 7 into @difference"); prepare stmt from @tmp_sql; execute stmt; while i <= @difference do set @tmp_sql = concat("select date_format(date_add('",@max_weekend_now,"' ,interval 7*",i," day), '%Y%m%d') into @tmp_weekend"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select nl_to_timestamp('",@tmp_weekend,"') into @tmp_weekend_value"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select date_format(date_add('",@tmp_weekend,"' ,interval -1 day), '%Y%m%d') into @tmp_weekend_before"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select week('",@tmp_weekend_before,"',4) into @tmp_week"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select year('",@tmp_weekend_before,"') into @tmp_year"); prepare stmt from @tmp_sql; execute stmt; if @tmp_week <10 then set @par_name = concat("par_",@tmp_year,"w0",@tmp_week); else set @par_name = concat("par_",@tmp_year,"w",@tmp_week); end if; set @alter_sql = concat("alter table ",table_name," add partition(partition ",@par_name," values less than (",@tmp_weekend_value,"))"); insert into change_partition_log values( now(), "add_hour", @alter_sql); prepare stmt from @alter_sql; execute stmt; set i = i+1; end while; set i = 1; end loop myLoop; close myCursor; END ;; DELIMITER ; -- 删除分区的存储过程 DELIMITER ;; CREATE PROCEDURE lens_browser_data.`del_partition_hour`() BEGIN declare table_name varchar(255) default 0; declare tmp_sql varchar(255) default ""; declare max_par_now varchar(255) default ""; declare par_del_num varchar(255) default ""; declare par_del varchar(255) default ""; declare alter_sql varchar(255) default ""; declare i int default 0; declare done int default -1; declare myCursor cursor for select tb_name from op_tb_partition_hour; declare continue handler for not found set done = 1; open myCursor; myLoop:LOOP fetch myCursor into table_name; if done = 1 then leave myLoop; end if; set @tmp_sql = concat("select count(*) FROM INFORMATION_SCHEMA.partitions WHERE TABLE_NAME = '",table_name,"' and TABLE_SCHEMA ='lens_browser_data' into @max_par_now"); prepare stmt from @tmp_sql; execute stmt; set @par_del_num = @max_par_now-13-3; while i < @par_del_num do set @tmp_sql = concat("select partition_name from INFORMATION_SCHEMA.partitions where TABLE_SCHEMA ='lens_browser_data' and table_name='",table_name,"' order by partition_name limit 1 into @par_del"); prepare stmt from @tmp_sql; execute stmt; set @alter_sql = concat("alter table ",table_name," drop partition ",@par_del); prepare stmt from @alter_sql; execute stmt; insert into change_partition_log values(now(),"drop_hour", concat(i,"--",@par_del,"--",@alter_sql)); set i = i+1; end while; set i = 0; end loop myLoop; close myCursor; END ;; DELIMITER ; -- 调度Event DELIMITER ;; CREATE EVENT `manager_partition_hour` ON SCHEDULE EVERY 1 WEEK STARTS '2015-09-06 00:30:00' ON COMPLETION PRESERVE ENABLE DO BEGIN call add_partition_hour; call del_partition_hour; END ;; DELIMITER ;
编写天表的存储过程,包括添加分区和删除分区两个存储过程及调度event,如下:
-- 添加分区的存储过程 DELIMITER ;; CREATE PROCEDURE lens_browser_data.`add_partition_day`() BEGIN declare table_name varchar(255) default 0; declare tmp_sql varchar(255) default ""; declare diff int default 0; declare diffenence int default 0; declare now_month varchar(255) default ""; declare now_year varchar(255) default ""; declare max_day_will varchar(255) default ""; declare max_day_now varchar(255) default ""; declare tmp_month varchar(255) default ""; declare tmp_month_before varchar(255) default ""; declare tmp_month_value varchar(255) default ""; declare tmp_year varchar(255) default ""; declare tmp_quarter varchar(255) default ""; declare difference int default 0; declare i int default 1; declare alter_sql varchar(255) default ""; declare done int default -1; declare myCursor cursor for select tb_name from op_tb_partition_day; declare continue handler for not found set done = 1; set @tmp_sql = concat("select month(now()) into @now_month"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select year(now()) into @now_year"); prepare stmt from @tmp_sql; execute stmt; if @now_month >= 1 and @now_month < 4 then set @tmp_day=concat(@now_year,'0101'); elseif @now_month >=4 and @now_month < 7 then set @tmp_day=concat(@now_year,'0401'); elseif @now_month >=7 and @now_month < 10 then set @tmp_day=concat(@now_year,'0701'); elseif @now_month >=10 and @now_month <=12 then set @tmp_day=concat(@now_year,'1001'); end if; set @tmp_sql = concat("select date_format(date_add(",@tmp_day,",interval 9 month), '%Y%m%d') into @max_day_will"); prepare stmt from @tmp_sql; execute stmt; open myCursor; myLoop:LOOP fetch myCursor into table_name; if done = 1 then leave myLoop; end if; set @tmp_sql = concat("select nl_to_date(max(PARTITION_DESCRIPTION+0)) from INFORMATION_SCHEMA.partitions WHERE TABLE_NAME = '",table_name,"' and TABLE_SCHEMA ='lens_browser_data' into @max_day_now"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select (year('",@max_day_will,"')*12 + month('",@max_day_will,"') - year('",@max_day_now,"')*12 - month('",@max_day_now,"')) div 3 into @difference"); prepare stmt from @tmp_sql; execute stmt; while i <= @difference do set @tmp_sql = concat("select date_format(date_add('",@max_day_now,"' ,interval 3*",i," month), '%Y%m%d') into @tmp_month"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select nl_to_timestamp('",@tmp_month,"') into @tmp_month_value"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select date_format(date_add('",@tmp_month,"' ,interval -1 day), '%Y%m%d') into @tmp_month_before"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select quarter('",@tmp_month_before,"') into @tmp_quarter"); prepare stmt from @tmp_sql; execute stmt; set @tmp_sql = concat("select year('",@tmp_month_before,"') into @tmp_year"); prepare stmt from @tmp_sql; execute stmt; set @par_name = concat("par_",@tmp_year,"q",@tmp_quarter); set @alter_sql = concat("alter table ",table_name," add partition(partition ",@par_name," values less than (",@tmp_month_value,"))"); insert into change_partition_log values( now(), "add_day", @alter_sql); prepare stmt from @alter_sql; execute stmt; set i = i+1; end while; set i = 1; end loop myLoop; close myCursor; END ;; DELIMITER ; -- 删除分区的存储过程 DELIMITER ;; CREATE PROCEDURE lens_browser_data.`del_partition_day`() BEGIN declare table_name varchar(255) default 0; declare tmp_sql varchar(255) default ""; declare max_par_now varchar(255) default ""; declare par_del_num varchar(255) default ""; declare par_del varchar(255) default ""; declare alter_sql varchar(255) default ""; declare i int default 0; declare done int default -1; declare myCursor cursor for select tb_name from op_tb_partition_day; declare continue handler for not found set done = 1; open myCursor; myLoop:LOOP fetch myCursor into table_name; if done = 1 then leave myLoop; end if; set @tmp_sql = concat("select count(*) FROM INFORMATION_SCHEMA.partitions WHERE TABLE_NAME = '",table_name,"' and TABLE_SCHEMA ='lens_browser_data' into @max_par_now"); prepare stmt from @tmp_sql; execute stmt; set @par_del_num = @max_par_now-8-3; while i < @par_del_num do set @tmp_sql = concat("select partition_name from INFORMATION_SCHEMA.partitions where TABLE_SCHEMA ='lens_browser_data' and table_name='",table_name,"' order by partition_name limit 1 into @par_del"); prepare stmt from @tmp_sql; execute stmt; set @alter_sql = concat("alter table ",table_name," drop partition ",@par_del); prepare stmt from @alter_sql; execute stmt; insert into change_partition_log values(now(),"drop_day",concat(i,"--",@par_del,"--",@alter_sql)); set i = i+1; end while; set i = 0; end loop myLoop; close myCursor; END ;; DELIMITER ; -- 调度Event DELIMITER ;; CREATE EVENT `manager_partition_day` ON SCHEDULE EVERY 3 MONTH STARTS '2015-10-01 00:30:00' ON COMPLETION PRESERVE ENABLE DO BEGIN call add_partition_day; call del_partition_day; END ;; DELIMITER ;