標籤: 網站設計公司

  • Zabbix-(三)監控主機CPU、磁盤、內存並創建監控圖形

    Zabbix-(三)監控主機CPU、磁盤、內存並創建監控圖形

    Zabbix-(三)監控主機CPU、磁盤、內存並創建監控圖形

    一.前言

    前文中已經講述了兩種方式對Zabbix的搭建,本文將講述如何在zaibbx上添加需要監控的主機,以及使用Zabbix自帶模板和自定義模板對主機的CPU、磁盤、內存進行監控,並觸發問題,並且在Zabbix儀錶盤創建實時監控圖形。

    準備

    • Zabbix Server (Zabbix 4.4) (ip:192.168.152.140)
    • 被監控主機A (Centos7.6),下文簡稱 Server-A (ip:192.168.152.142)
    • 被監控主機B (Centos7.6),下文簡稱 Server-B (ip:192.168.152.143)

    二.為被監控主機安裝zabbix-agent

    1. Server-A、Server-B分別安裝zabbix-agent

      # rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/7/x86_64/zabbix-release-4.4-1.el7.noarch.rpm
      
      # yum install -y zabbix-agent

    2. Server-A、Server-B配置zabbix-agent

      # vim /etc/zabbix/zabbix_agentd.conf

      修改以下配置:

      • Server-A的zabbix_agentd.conf
      Server=192.168.152.140
      ServerActive=192.168.152.140
      
      # Hostname要與在Zabbix界面配置的Hostname(主機名稱)保持一致
      Hostname=Server-A
      • Server-B的zabbix_agentd.conf
      Server=192.168.152.140
      ServerActive=192.168.152.140
      
      # Hostname要與在Zabbix界面配置的Hostname(主機名稱)保持一致
      Hostname=Server-B

    3. 分別啟動zabbix-agent

      # systemctl start zabbix-agent

      可以查看agent日誌

      # tailf /var/log/zabbix/zabbix_agentd.log

      可能會出現以下內容,是由於zabbix界面上沒有配置主機,接下來將在zabbix頁面上進行主機配置

        6981:20191030:111132.151 no active checks on server [192.168.152.140:10051]: host [Server-A] not found

    三.Zabbix添加主機

    通過頁面操作,將需要監控的主機添加到zabbix中

    1. 登錄Zabbix,默認賬號:Zabbix,默認密碼:admin (可在zabbix數據庫 users表查詢)

    2. 點擊【配置】-【主機】-【創建主機】,添加需要被監控的主機

      首先配置【主機】信息,添加Server-A,輸入配置項

      配置項
      * 主機名稱 Server-A
      可見的名稱 Server-A
      * 群組 Linux servers (進行選擇)
      * agent代理程序的接口 IP地址: 192.168.152.142 端口: 10050

      再配置【模板】信息,點擊【添加】,選擇群組 Templates,勾選 Template OS Linux by Zabbix agent,點擊【選擇】

      最後點擊【保存】

    3. 在【主機】頁面可以看到Server-A已經成功添加了

      同時,Server-A的zabbix-agent日誌也不再打印

      注: 由於在之前在安裝Zabbix server時,也在zabbix server上安裝了zabbix-agent,因此圖例上除了Server-A主機以外,還有zabbix server主機

    4. 通過全克隆添加主機Server-B

      選擇需要複製的主機Server-A

      點擊【全克隆】(full clone)

      修改主機名稱agent IP地址等信息

      修改配置項
      *主機名稱 Server-B
      *agent IP 192.168.152.143

      最後點擊【添加】,等待Server-B與zabbix server建立通信

    四.創建自定義模板(Template)

    在添加主機步驟中,添加了2台需要監控的主機,添加監控項時也可以給每台主機單獨添加監控項,但是隨着主機數量增多,就會出現過多重複的操作,因此可以使用zabbix的Templates(模板)Items(監控項Triggers(觸發器)等眾多配置定義在模板中,將主機鏈接到定義好的模板上,就可以免去重複的操作。

    下面將自定義模板,定義監控磁盤剩餘空間監控項,並配置觸發器當磁盤剩餘空間低於一定閾值時觸發告警。

    1. 創建自定義模板

      點擊【配置】-【模板】-【創建模板】

    2. 輸入模板信息,完成後點擊【添加】

      配置項
      * 模版名稱 Template Disk Free Size
      可見的名稱 Template Disk Free Size
      * 群組 Linux servers (選擇)
      描述 自定義磁盤剩餘空間模板

      注: 讀者也可以自定義一個群組,並在自定義群組中創建模板,這個步驟本文不再示範

    五.創建磁盤剩餘空間監控項和觸發器

    1. 創建自定義磁盤監控項(Item)

      進入自定義模板的監控項模塊

      點擊【創建監控項】

      輸入監控參數

      配置項
      * 名稱 磁盤剩餘空間監控項
      類型 Zabbix 客戶端
      * 鍵值 vfs.fs.size[/,free]
      單位 B
      ……其他配置項 根據需要填寫

      這裏的鍵值 vfs.fs.size[/,free]是指,監控根路徑下,空餘的磁盤大小

      點擊【添加】

      注:創建監控項(Items)可以參考, 更多的鍵值(Keys)可以參考

    2. 創建觸發器(Trigger)

      觸發器可以配置當監控項監控到的數據達到一定閾值,從而觸發問題。

      在Template Disk Free Size模板中選擇【觸發器】,點擊【創建觸發器】

      輸入觸發器參數

      配置項
      * 名稱 磁盤剩餘空間觸發器
      嚴重性 嚴重(選擇)
      * 表達式/問題表現形式 {Template Disk Free Size:vfs.fs.size[/,free].last()}<15000000000 (可通過選擇監控項)
      事件成功迭代 恢復表達式(選擇)
      * 恢復表達式 {Template Disk Free Size:vfs.fs.size[/,free].last()}>=15000000000
      問題事件生成模式 多重(選擇)

      表達式/問題表示形式

      選擇已配置的磁盤剩餘空間監控項

      配置結果 < 15000000000, 監控項中單位為B,這裏15GB換算成15000000000B

      點擊【插入】,可以看到如下錶達式,表達式意思是,當檢測到磁盤弓箭剩餘不足15GB時,將觸發問題

      {Template Disk Free Size:vfs.fs.size[/,free].last()}<15000000000

      因此可以直接輸入問題恢復表達式,即磁盤剩餘空間高於15GB時,恢復問題

      {Template Disk Free Size:vfs.fs.size[/,free].last()}>=15000000000

      點擊【添加】

      再將該自定義模板,鏈接到Server-A、Server-B主機的模板中,參考,不過在篩選模板時,群組要選擇Linux servers(與創建模板時群組保持一致),添加後點擊【更新】

      進入【配置】-【主機】-【Server-A】(或者 Server-B)-【監控項】中,可以搜索到磁盤剩餘空間監控項已經添加成功

      注:如果監控項狀態不為【已啟動】可以查看zabbix server日誌進行排查

    3. 測試一下

      當前Server-A主機磁盤剩餘空間,為15G

      上傳一些文件到Server-A,此時磁盤剩餘空間為14G

      等待Zabbix監控到Server-A磁盤變化,查看儀錶盤,出現問題,配置成功

      刪除Server-A大文件,等待Zabbix監控到主機磁盤恢復,儀錶盤問題恢復

    六.監控CPU空閑率

    在添加主機時,由於已經鏈接了模板(該模板還鏈接了Template Module Linux CPU by Zabbix agent等若干個其他模板),Template Module Linux CPU by Zabbix agent模板自帶了許多監控項,其中包括CPU idle time 監控項,因此可以直接使用該監控項監控主機CPU空閑率數值,無需自定義監控項,只需要添加一個觸發器(Trigger)來讀取監控項觸發告警即可。

    注: zabbix自帶模板中,有許多監控項可以直接利用起來,無需再單獨創建監控項,使用時可先在已有模板中查找下可用的監控項。

    1. 使用自帶模板中監控項

      直接使用CPU idle time 監控項即可,可以在【配置】-【主機】,【Server-A】的【監控項】中搜索到該監控項(在下圖中可以看到該監控項鏈接了模板)

    2. 在已有模板中添加觸發器(trigger)

      這裡在模板Template Module Linux CPU by Zabbix agent添加一個觸發器。

      點擊【配置】-【模板】搜索模板Template Module Linux CPU by Zabbix agent,並進入【觸發器】配置

      創建觸發器操作流程參考上面步驟中的,這裏說明一下配置參數

      配置項
      * 名稱 CPU空閑率觸發器
      嚴重性 嚴重 (選擇)
      表達式/問題表現式 {Template Module Linux CPU by Zabbix agent:system.cpu.util[,idle].avg(5m)}>=80
      事件成功迭代 恢復表達式(選擇)
      * 恢復表達式 {Template Module Linux CPU by Zabbix agent:system.cpu.util[,idle].avg(5m)}<80

      表達式/問題表現式:表示在5分鐘內CPU平均空閑率如果高於80%,那麼將觸發問題

      添加表達式示例:

      system.cpu.util[,idle]官方說明

      注:這裏修改了zabbix自帶的模板(Template Module Linux CPU by Zabbix agent),為其添加了一個新的觸發器,在實際使用中,要謹慎操作,因為鏈接了該模板的主機觸發器都會被修改,因此實際使用中需要對這種操作進行評估。

    3. 測試一下

      等待5分鐘,Zabbix server、Server-A、Server-B的CPU空閑率都高於80%,Dashboard界面觸發了問題,由於Zabbix server主機也鏈接了模板,因此修改Template Module Linux CPU by Zabbix agent模板,Zabbix server的CPU空閑率也被監控,所以在修改模板時要。

    七.監控內存佔用率

    在上面的步驟中添加了磁盤剩餘空間、CPU空閑率監控,直接使用了Zabbix 客戶端類型的監控項的鍵值,但是有些監控項可能不能直接獲取,需要通過計算的方式來獲取,例如監控內存佔用率,雖然可以使用vm.memory.size這個鍵值,但是得到值並不是我們所期望的,參考下面官方的解釋,雖然mode中有pused (used, percentage),但是“used”=”total – free”“available”=”free + buffers + cached”(內核版本Linux<3.14),實際是想要的值:

    (available - total) / total

    因此需要使用可計算的鍵值類型

    官方對vm.memory.size以及參數解釋:

    1. 在Template OS Linux by Zabbix agent模板新增監控項

      配置項
      * 名稱 內存佔用率監控項
      類型 可計算的
      * 鍵值 memory.utilization (自定義)
      * 公式 100*(last(“vm.memory.size[total]”)-last(“vm.memory.size[available]”))/last(“vm.memory.size[total]”)
      信息類型 浮點數
      單位 %
      ……其他配置項 默認即可

      自定義鍵值可自己輸入,具體規則參考官方

    這裏就不再創建觸發器了,感興趣的讀者可以自行創建,可參考上面的

    八.Dashboard創建圖形

    可以在首頁儀錶盤裡創建圖形,實時查看監控項的數據值。

    1. 回到zabbix首頁,點擊【編輯儀錶盤】-【添加構件】

    2. 創建磁盤剩餘空間圖形

      輸入基本信息

      添加【主機】和【監控項】

      左邊一欄選擇主機Server-A,右邊一欄選擇Server-A的磁盤監控項

      再【添加新數據集】,同樣操作將Server-B的磁盤監控也添加到圖形中

    3. 添加CPU空閑率圖形

      按照,添加Server-A,Server-B的CPU空閑率圖形

    4. 添加內存佔用率圖形

      同樣按照,添加Server-A,Server-B的內存佔用率圖形

    5. 保存設置並在儀錶盤中查看

      點擊【保存設置】

      在儀錶盤頁面查看圖形

    九.參考文檔

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※試算大陸海運運費!

  • 2019全球電力碳排放降2% 達30年來最大降幅 歸因燃煤發電減少

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※試算大陸海運運費!

  • 上世紀毒梟艾斯科巴 引入非洲河馬當寵物

    摘錄自2020年3月11日公視報導

    哥倫比亞上世紀最囂張的毒販——艾斯科巴,已經過世27年。不過他留下很特殊的遺產,就是他養的四頭寵物河馬,但這些年來族群數量暴增,數量已經超過60隻,變成大問題。

    1980年代,富可敵國的毒梟艾斯科巴,把自家莊園變成野生動物園,引進大象、長頸鹿等稀有野生動物,包括四頭河馬。艾斯科巴死後,財產充公,他的豪華莊園變成主題公園。當局把珍禽異獸都送走,唯獨噸位龐大又暴躁的河馬難以處理,就撒手不管,留在莊園的大池塘。一公三母很快發展成大家族,突破圍欄,進駐1500公里長的馬格達萊納河,成為排擠在地生物的水陸霸主。河馬大量在水中排便的習性,也導致壞菌跟有害藻類增加,衝擊水質與生態體系。

    河邊的多拉戴爾鎮,河馬逛大街已經司空見慣,隨著族群增加,朝人口稠密的地方擴散,未來攻擊人類的事件恐怕難以避免,民眾對此看法兩極。哥倫比亞去年第一次,在野外為母河馬動結紮手術,獸醫他們坦承,可能還做得不夠快,預計河馬數量將在未來10年增為四倍,最終可能達到數千隻之多。

    動物福利
    國際新聞
    河馬
    飼養

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    台灣寄大陸海運貨物規則及重量限制?

    大陸寄台灣海運費用試算一覽表

    台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

  • 車王電、華德動能聯手搶攻智慧電動巴士

    台灣電動巴士廠商車王電與華德動能宣布,兩家公司將就電動公車展開智慧車聯網技術的研發工作,推出商務行動辦公室,最快在今年第四季就可量產。台灣、中國大陸與東南亞國家都是市場目標。

    車王電董事長蔡裕慶表示,電動車結合車聯網的模式,未來將席捲全球,因此車王電與華德動能合作,整合端、網、雲系統,所涉及的技術包括:車載通訊、行動影音娛樂、先進駕駛安全輔助(ADAS)與行車管理等系統,推出專為電動巴士所設計的完整車聯網系統平台。

    蔡裕慶表示,電動巴士加車聯網的全新營運模式,初期將會以台灣本土市場為主要目標,未來也會嘗試進入中國大陸、印度、香港、新加坡、越南等更多市場。他也指出,車王電與華德動能的合作主要在平台整合,進入各地市場之際,還會根據各市場的需求打造不同車體。

    藉著智慧化車聯網平台方案,蔡裕慶估計每輛車輛的售價將可提高一至二成。他認為,車用電子市場潛力龐大,車聯網與綠能都是未來發展的主要潮流。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※試算大陸海運運費!

  • 北汽新能源獲得首張純電動車生產資質牌照

    經過了一系列審核後,國家發改委於3月23日發佈了關於“北京新能源汽車股份有限公司純電動乘用車建設項目核准的批復”。

    這是《新建純電動乘用車企業管理規定》自2015年7月1日開始實施後,國家發改委批復的第一個純電動乘用車生產資質。

    根據《規定》要求,發改委審批之後,獲批企業還要通過工信部《乘用車生產企業及產品准入管理規則》和《新能源汽車生產企業及產品准入管理規則》的考核,列入《車輛生產企業及產品公告》。完成這一步即是正式獲得了純電動汽車的生產資質。

    在發改委對北汽新能源批復內容中顯示,此次批復專案為兩部分:一是位於北京采育的2萬輛產能基地,一是位於青島萊西的5萬輛產能基地。投資金額共計11.49億元,目前這兩個建設專案均已建設完成並投入運營。

    按照《新建純電動乘用車企業管理規定》要求,申請對象為純電動乘用車生產企業,不能生產任何以內燃機為驅動動力的汽車產品。這意味著北汽新能源將徹底放棄插電式混合動力路線。但規定中稱,純電動乘用車包含增程式(具備外接充電功能的串聯式混合動力)乘用車。

    目前,北汽新能源正在謀求獨立上市。在拿到了第一張純電動乘用車生產牌照後,將對其上市進程起到推動作用。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    台灣寄大陸海運貨物規則及重量限制?

    大陸寄台灣海運費用試算一覽表

    台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

  • 千萬數據量數據表分表實踐

    千萬數據量數據表分表實踐

    需求

    • 對平均 1200w 數據量的數據表進行優化
    • 數據表中有 2016年,2017 年,2018 年,2019 年數據
    • 只查詢最近半年的數據
    • 後台增加歷史數據查詢功能
    • 盡量減少代碼改動

    數據表

    • 積分日誌表 tb_user_points_log
    • 虛擬充值表 tb_order_recharge
    • 虛擬充值執行表 tb_order_recharge_do

    注意

    先備份數據,在備份的數據表的基礎上進行分表,不直接操作原始表!

    步驟

    將源數據表備份一份,依次將對應年份的數據歸檔,每成功歸檔一次,就將備份數據表中對應數據刪除(目的減少查詢數據量),最後根據備份表最小 ID,刪除源數據表 小於 ID 的所有數據。

    該步驟可以直接通過 SQL 執行,也可通過腳本執行。

    腳本執行

    刪除源數據表數據操作,建議通過手動執行 SQL完成,其他操作通過腳本執行

    以積分日誌表 tb_user_points_log 為例

    方式一、手動執行SQL

    1. 備份 tb_user_points_log 得到 tb_user_points_copy

      2016年數據歸檔

    2. 將數據表 tb_user_points_copy 2016 年的數據歸檔存入 2016 年數據表 tb_user_points_log_2016

      CREATE TABLE tb_user_points_log_2016 LIKE tb_user_points_log_copy;
      INSERT INTO tb_user_points_log_2016 SELECT * FROM tb_user_points_log_copy WHERE add_time < 1483200000;
      
    3. 對比數量

      SELECT COUNT(id) FROM tb_user_points_log_2016;
      SELECT COUNT(id) FROM tb_user_points_log_copy WHERE add_time < 1483200000;
      
    4. 一致則刪除 tb_user_points_copy 的 2016 年數據

      DELETE FROM tb_user_points_log_copy WHERE add_time < 1483200000;
      

      2017年數據歸檔

    5. 將數據表 tb_user_points_copy 2017 年的數據歸檔存入 2017 年數據表 tb_user_points_log_2017

      CREATE TABLE tb_user_points_log_2017 LIKE tb_user_points_log_copy;
      INSERT INTO tb_user_points_log_2017 SELECT * FROM tb_user_points_log_copy WHERE add_time < 1514736000;
      
    6. 對比數量

      SELECT COUNT(id) FROM tb_user_points_log_2017;
      SELECT COUNT(id) FROM tb_user_points_log_copy WHERE add_time < 1514736000;
      
    7. 一致則刪除 tb_user_points_copy 的 2017 年數據

      DELETE FROM tb_user_points_log_copy WHERE add_time < 1514736000;
      

      2018年數據歸檔

    8. 將數據表 tb_user_points_copy 2018 年的數據歸檔存入 2018 年數據表 tb_user_points_log_2018

      CREATE TABLE tb_user_points_log_2018 LIKE tb_user_points_log_copy;
      INSERT INTO tb_user_points_log_2018 SELECT * FROM tb_user_points_log_copy WHERE add_time < 1546272000;
      
    9. 對比數量

      SELECT COUNT(id) FROM tb_user_points_log_2018;
      SELECT COUNT(id) FROM tb_user_points_log_copy WHERE add_time < 1546272000;
      
    10. 一致則刪除 tb_user_points_copy 的 2018 年數據

      DELETE FROM tb_user_points_copy WHERE add_time < 1546272000;
      

      2019年數據歸檔

    11. 現在是 11 月,將 5 月之前的數據歸檔

      CREATE TABLE tb_user_points_log_2019 LIKE tb_user_points_log_copy;
      INSERT INTO tb_user_points_log_2019 SELECT * FROM tb_user_points_log_copy WHERE add_time < 1556640000;
      
    12. 對比數量

      SELECT COUNT(id) FROM tb_user_points_log_2019;
      SELECT COUNT(id) FROM tb_user_points_log_copy WHERE add_time < 1556640000;
      
    13. 一致則刪除 tb_user_points_copy 的 2019 年 5 月之前的數據

      DELETE FROM tb_user_points_log_copy WHERE add_time < 1556640000;
      

      刪除原始數據

    14. 根據最小 tb_user_points_copy 的最小 ID,刪除原始表 小於 ID 的所有數據

      DELETE FROM tb_user_points_log WHERE id < (SELECT id FROM tb_user_points_log_copy ORDER BY id asc LIMIT 1);
      
    15. 刪除臨時表

      DELETE FROM tb_user_points_log_copy;
      
    16. 數據表分表完成!

    17. 增量歸檔

      每日凌晨,執行腳本將最近半年之前的數據歸檔

    方式二、腳本執行

    <?php
    /**
     * Description: 將6個月前數據歸檔
     */
    
    namespace wladmin\cmd;
    
    
    use think\console\Command;
    use think\console\Input;
    use think\console\Output;
    use think\Db;
    
    class DataArchiving extends Command
    {
        protected function configure()
        {
            $this->setName('DataArchiving')->setDescription('將6個月前數據歸檔');
        }
    
        /**
         * 將6個月前數據歸檔
         * php think DataArchiving
         * @param Input $input
         * @param Output $output
         *
         * @return int|void|null
         */
        protected function execute(Input $input, Output $output)
        {
            try {
                $this->archiveData('tb_user_points_log', 'id', 'add_time');
                $this->archiveData('tb_order_recharge', 'or_id', 'create_time');
                $this->archiveData('tb_order_recharge_do', 'ord_id', 'create_time');
                echo '歸檔完成';
            } catch (\Exception $e) {
                mylog($e->getMessage(),'歸檔發生錯誤:'.PHP_EOL);
            }
        }
      
             /**
         * 歸檔數據表
         * @param string $sourceTable 源數據表名
         * @param string $primaryKey 主鍵名
         * @param string $timeKey 時間鍵名
         *
         * @author Dong.cx 2019-11-18 18:05
         * @version V4.0.1
         */
        private function archiveData($sourceTable, $primaryKey, $timeKey)
        {
            try {
                date_default_timezone_set('PRC');
                // 1.複製源數據表
                $copyTable = $sourceTable . '_copy';
                $isExist = $this->tableExist($copyTable, $sourceTable);
                if (!$isExist) {
                    echo "開始複製源數據表{$copyTable}" . PHP_EOL;
                    $archivingTimeLine = time();
                    $sql = "INSERT IGNORE INTO {$copyTable} SELECT * FROM {$sourceTable} WHERE {$timeKey} < {$archivingTimeLine}";
                    Db::execute($sql);
                    echo "複製源數據表{$copyTable}完成" . PHP_EOL;
                }
                echo "{$copyTable} 開始歸檔" . PHP_EOL;
                // 歸檔
                $this->archive(2016, $sourceTable, $primaryKey, $timeKey);
                $this->archive(2017, $sourceTable, $primaryKey, $timeKey);
                $this->archive(2018, $sourceTable, $primaryKey, $timeKey);
                $this->archive(2019, $sourceTable, $primaryKey, $timeKey);
                echo "{$copyTable} 歸檔完成";
    
            } catch (\Exception $e) {
                echo '歸檔發生錯誤:' . $e->getMessage() .PHP_EOL;
            }
        }
    
        /**
         * 歸檔操作
         * @param int $year 年份
         * @param string $sourceTable 源數據表名
         * @param string $primaryKey 主鍵名
         * @param string $timeKey 時間鍵名
         *
         * @return bool
         * @throws \Exception
         * @author Dong.cx 2019-11-18 18:12
         * @version V4.0.1
         */
        private function archive($year, $sourceTable, $primaryKey, $timeKey)
        {
            try {
                $copyTable = $sourceTable . '_copy';
                echo "{$copyTable} 開始歸檔{$year}年數據--->" . PHP_EOL;
                if ($year == date('Y')) {
                    // 注意現在是 11月份,可以簡單這樣寫,如果是小於6月,則要相應修改
                    $archivingTimeLine = strtotime('-6 month', strtotime('today'));
                } else {
                    $archivingTimeLine = mktime(0,0,0,1,1,$year+1);
                }
    
                $sql = "SELECT COUNT({$primaryKey}) as num FROM {$copyTable} WHERE {$timeKey} < {$archivingTimeLine}";
                $res = Db::query($sql);
                if (!$res || !$res[0]['num']) {
                    echo "{$copyTable} {$year}年數據歸檔完成,未查詢到需要歸檔的數據" . PHP_EOL;
                    return true;
                }
    
                // 需歸檔數量
                $targetNum = $res[0]['num'];
                // 歸檔表名
                $tableArchivingName = $sourceTable . '_' . $year;
                $this->tableExist($tableArchivingName, $sourceTable);
    
                // 分批歸檔
                $this->archivingBatch($tableArchivingName, $copyTable, $primaryKey,$timeKey, $archivingTimeLine, $year, $targetNum);
    
                return true;
            } catch (\Exception $e) {
                throw $e;
            }
        }
    
        /**
         * 分批歸檔
         * @param string $tableArchivingName 歸檔表名稱
         * @param string $copyTable 複製表名
         * @param string $primaryKey 主鍵名
         * @param string $timeKey 時間鍵
         * @param int $archivingTimeLine 歸檔時間線
         * @param string $year 歸檔年
         * @param int $targetNum 需歸檔的數據量
         *
         * @throws \Exception
         * @author Dong.cx 2019-11-19 13:10
         * @version V4.0.1
         */
        private function archivingBatch($tableArchivingName, $copyTable, $primaryKey,$timeKey, $archivingTimeLine, $year, $targetNum)
        {
            // 歸檔表起始ID
            $res = Db::query("SELECT {$primaryKey} FROM {$tableArchivingName} ORDER BY {$primaryKey} DESC LIMIT 1");
            $startID = $res ? $res[0][$primaryKey] : 0;
    
            $totalDelNum = 0;
            $batchNum = 10000;
            $taskNum = ceil($targetNum/$batchNum);
            $minID = Db::query("SELECT {$primaryKey} FROM {$copyTable} ORDER BY {$primaryKey} ASC LIMIT 1");
            if (!$minID) throw new \Exception('$minID為空!');
            $minID = $minID[0][$primaryKey];
            $maxID = Db::query("SELECT {$primaryKey} FROM {$copyTable} WHERE {$timeKey} < {$archivingTimeLine} ORDER BY {$primaryKey} DESC LIMIT 1");
            if (!$maxID) throw new \Exception('$max 為空!');
            $maxID = $maxID ? $maxID[0][$primaryKey] : 0;
    
            for ($i = 1; $i <= $taskNum; $i++) {
                if ($i == $taskNum) {
                    // 歸檔
                    $sql = "INSERT IGNORE INTO {$tableArchivingName} SELECT * FROM {$copyTable} WHERE {$primaryKey} <= {$maxID} AND {$timeKey} < {$archivingTimeLine}";
                    Db::execute($sql);
                    // 刪除
                    $sql = "DELETE FROM {$copyTable} WHERE {$primaryKey} <= {$maxID} AND {$timeKey} < {$archivingTimeLine}";
                    $totalDelNum += Db::execute($sql);
                } else {
                    $end = $minID + $i * $batchNum;
                    // 歸檔
                    $sql = "INSERT IGNORE INTO {$tableArchivingName} SELECT * FROM {$copyTable} WHERE {$primaryKey} <= {$end} AND {$timeKey} < {$archivingTimeLine}";
                    Db::execute($sql);
                    // 刪除
                    $sql = "DELETE FROM {$copyTable} WHERE {$primaryKey} <= {$end} AND {$timeKey} < {$archivingTimeLine}";
                    $totalDelNum += Db::execute($sql);
                }
            }
            // 成功歸檔數據量
            $num = Db::query("SELECT COUNT({$primaryKey}) as num FROM {$tableArchivingName} WHERE {$primaryKey} > {$startID}")[0]['num'];
            if ($targetNum != $num) throw new \Exception("歸檔數據不一致,過期數據量{$targetNum},歸檔量{$num},刪除量{$totalDelNum}");
            if ($num != $totalDelNum) throw new \Exception("刪除數據不一致,歸檔量{$num},刪除量{$totalDelNum}");
    
            echo "{$copyTable} {$year}年數據歸檔完成,過期數據量{$targetNum},歸檔量{$num},刪除量{$totalDelNum}" . PHP_EOL;
            
            // 刪除源數據表數據
            //echo "開始刪除源數據表 {$sourceTable}已歸檔數據" . PHP_EOL;    
            //$num = Db::execute("DELETE FROM {$sourceTable} WHERE {$primaryKey} < (SELECT id FROM {$copyTable} ORDER BY {$primaryKey} asc LIMIT 1)");
           //echo "源數據表 {$sourceTable}已歸檔數據刪除完成,刪除數據量{$num}" . PHP_EOL; 
          
            //echo "開始刪除臨時表 {$copyTable}" . PHP_EOL;    
            // 刪除臨時表
            //Db::execute("DELETE FROM {$copyTable}");
            //echo "臨時表{$copyTable}刪除完成" . PHP_EOL;
        }
    

    最後由於是要刪除源數據表,屬於敏感操作,(腳本最後註釋部分) 建議再複查一次數據歸檔正確性,確認無誤后,手動執行 SQL操作。

    DELETE FROM {$sourceTable} WHERE {$primaryKey} < (SELECT {$primaryKey} FROM {$copyTable} ORDER BY {$primaryKey} asc LIMIT 1;
    DELETE FROM {$copyTable};
    

    增量歸檔腳本

    <?php
    /**
     * Description: 將6個月前數據歸檔
     */
    
    namespace wladmin\cmd;
    
    
    use think\console\Command;
    use think\console\Input;
    use think\console\Output;
    use think\Db;
    
    class DataArchiving extends Command
    {
        protected function configure()
        {
            $this->setName('DataArchiving')->setDescription('將6個月前數據歸檔');
        }
    
        /**
         * 將6個月前數據歸檔
         * php think DataArchiving
         * @param Input $input
         * @param Output $output
         *
         * @return int|void|null
         */
        protected function execute(Input $input, Output $output)
        {
            try {
                $this->archiveDataEveryDay('tb_user_points_log', 'id', 'add_time');
                $this->archiveDataEveryDay('tb_order_recharge', 'or_id', 'create_time');
                $this->archiveDataEveryDay('tb_order_recharge_do', 'ord_id', 'create_time');
                echo '歸檔完成';
            } catch (\Exception $e) {
                mylog($e->getMessage(),'歸檔發生錯誤:'.PHP_EOL);
            }
        }
    
        /**
         * 歸檔數據
         * @param string $sourceTable 源數據表名
         * @param string $primaryKey 源數據表主鍵名
         * @param string $timeKey 時間控制鍵名
         *
         * @return bool
         * @throws \Exception
         * @author Dong.cx 2019-11-15 18:36
         * @version V4.0.1
         */
        private function archiveDataEveryDay($sourceTable, $primaryKey, $timeKey)
        {
            try {
                //mylog("{$sourceTable} 開始歸檔".PHP_EOL);
                // 歸檔時間線
                $archivingTimeLine = strtotime('-6 month', strtotime('today'));
                // 歸檔表的年份
                $year = date('Y', $archivingTimeLine);
                // 歸檔表名
                $tableArchivingName = $sourceTable . '_' . $year;
    
                // 需要歸檔的數據量
                $sql = "SELECT COUNT({$primaryKey}) as num FROM {$sourceTable} WHERE {$timeKey} < {$archivingTimeLine}";
                $res = Db::query($sql);
                // 沒有需要歸檔的,直接返回
                if (!$res) {
                    mylog("{$sourceTable} 歸檔完成,未查詢到需要歸檔的數據");
                    return true;
                }
                $count = $res[0]['num'];
    
                // 檢測數據表是否存在,不存在則創建
                $this->tableExist($tableArchivingName, $sourceTable);
                $sql = "INSERT IGNORE INTO {$tableArchivingName} SELECT * FROM {$sourceTable} WHERE {$timeKey} < {$archivingTimeLine}";
    
                // 1.開始歸檔
                // 歸檔表起始ID
                $res = Db::query("SELECT {$primaryKey} FROM {$tableArchivingName} ORDER BY {$primaryKey} DESC LIMIT 1");
                $startID = $res ? $res[0][$primaryKey] : 0;
                Db::execute($sql);
                // 成功歸檔數據量
                $num = Db::query("SELECT COUNT({$primaryKey}) as num FROM {$tableArchivingName} WHERE {$primaryKey} > {$startID}")[0]['num'];
                if ($count != $num) throw new \Exception("歸檔數據不一致,過期數據量{$count},歸檔量{$num}");
                $lastID = Db::query("SELECT {$primaryKey} FROM {$tableArchivingName} ORDER BY {$primaryKey} DESC LIMIT 1")[0][$primaryKey];
    
                // 2.刪除源數據
                $sql = "DELETE FROM {$sourceTable} WHERE {$primaryKey} <= {$lastID}  AND {$timeKey} < {$archivingTimeLine}";
                $delNum = Db::execute($sql);
                if ($delNum != $count) throw new \Exception("刪除數據不一致,過期數據量{$count},刪除量{$delNum}");
                //mylog("{$sourceTable} 歸檔完成,過期數據量{$count},歸檔量{$count},刪除量{$delNum}" . PHP_EOL);
                return true;
            } catch (\Exception $e) {
                Db::rollback();
                throw $e;
            }
        }
    
        /**
         * 檢測數據表是否存在,不存在則創建
         * @param $table
         * @param $likeTable
         */
        private function tableExist($table, $likeTable)
        {
            $sql = "SHOW TABLES LIKE '{$table}'";
            $isExist = Db::query($sql);
    
            if (!$isExist) {
                Db::execute("CREATE TABLE {$table} LIKE {$likeTable}");
            }
        }
    }
    

    歷史數據查詢

    在數據訪問層中根據需要查詢時間 動態修改數據表名即可

    這裏使用的是 thinkphp Query 類中的 setTable()getTable()

     if (isset($params['history']) && !empty($params['history'])) {
                $this->model()->setTable($this->model()->getTable().'_'.$params['history']);
            }
    

    遇到的問題

    • 開發中,曾嘗試使用事務控制,數據量太多會導致提交過慢,因此使用邏輯控制
    • DB 一次性執行100多w刪除操作后,發現程序不繼續向下執行,未找到原因,因此將數據分批進行處理,但是分批可能存在問題,因為主鍵可能不是連續的,如果間隔不大的話,影響不大。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※試算大陸海運運費!

  • 克羅埃西亞強震 鄰國斯洛維尼亞核電廠未受影響

    摘錄自2020年3月22日聯合報報導

    中歐國家克羅埃西亞今天(22日)上午遭遇規模5.3地震襲擊,鄰國斯洛維尼亞隨後表示,境內唯一一座位在克斯科(Krsko)的克斯科核電廠(NEK)並未受到影響。

    克斯科核電廠是斯洛維尼亞(Slovenia)和克羅埃西亞共有。斯洛維尼亞核子安全局長塞奇(Igor Sirc)在地震後表示:「這座核電廠持續以全產能運作。」但當局已展開正常預防程序,對核電廠的系統與設備進行檢查

    克羅埃西亞首都薩格勒布(Zagreb)北方發生規模5.3強震,引發人們奔逃上街,並造成建築物損害、車輛遭崩塌的瓦礫掩埋,還發生多起火警。

    核能
    災害
    能源議題
    土地水文
    國際新聞
    克羅埃西亞
    斯洛維尼亞
    地震
    核電廠

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※試算大陸海運運費!

  • 東奧聖火抵日 傳遞即將開跑 福島飯館村去污後輻射仍超標

    文:宋瑞文(媽媽監督核電廠聯盟特約撰述)

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    台灣寄大陸海運貨物規則及重量限制?

    大陸寄台灣海運費用試算一覽表

    台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

  • 福特計畫推出全新新能源車型 或將命名為Model E

    據海外媒體報導稱福特計畫推出一款全新新能源車型,其很有可能會命名為Model E。

    福特公司把這款Model E定位於一款緊湊車型,這款車會推出混動、插電式混動以及純電動版本,主要取代的是純電動版福克斯以及混動版和插電式混動版C-MAX。

    另外,福特公司將會投資16億美元的資金,在墨西哥San Luis Potosi建設全新的工廠,並且這款Model E也將會在這座工廠生產。這款車將在2018年正式亮相,在2019年投放市場。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※試算大陸海運運費!

  • 低速電動車國家標準公開徵求意見

    2016年4月14日,國家標準化管理委員會在其網站上對2016年第一批擬立項國家標準專案公開徵求意見。2016年第一批擬立項標準,《四輪低速電動乘用車技術條件》在列!

    低速電動車是指行駛速度低、續駛里程短,電池、電機等關鍵部件技術水準較低的電動乘用車。因具有小型化、配置簡單、價格低廉等特點,低速電動車滿足了部分群眾,特別是低收入群體的交通出行需求,在部分中小城市迅速發展,並逐步向大城市蔓延。據統計,目前全國共有低速電動車生產企業超過100家,產能超過100萬輛,產業規模近年來持續快速增長。

    但低速電動車存在一些突出問題:一是生產企業多為沒有汽車生產資質的中小規模企業,缺乏汽車研發生產所必備的設施條件,大多數產品不符合國家相關標準,沒有經過必要的實驗驗證,安全性能較差。二是駕駛人員大多未取得機動車駕駛證,安全意識差,違法行為多,駕車上路後給自身和其他車輛造成嚴重安全隱患。三是使用的鉛酸電池在回收、冶煉過程中環境污染較大,容易造成鉛污染,危害人體健康。四是大部分地方對低速電動車的生產、使用缺乏管理制度和措施,有些地方已出臺的使用、報廢等管理辦法不符合相關法律法規規定。為了保障行車安全、引導企業的正規生產,加強管理,需要制定本標準。

     

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    台灣寄大陸海運貨物規則及重量限制?

    大陸寄台灣海運費用試算一覽表

    台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!