2020年12月31日 星期四

MySQL 記一次還原指定日期資料且避開auto increment問題

 1 mysqldump 只能備份所有欄位

 無法跳過有auto increment column,

所以必須複製一個相同table, 然後刪掉不要的欄位,再dump出來

2 mysqldump 常用參數

//用cluster 請勿使用 --no-autocommit

mysqldump -u root -p --skip-add-drop-table --skip-add-locks --no-create-db --no-create-info --no-autocommit --complete-insert --net-buffer-length=1000000 --max-allowed-packet=1000000000 

--skip-add-drop-table  還原時不drop原有table

--skip-add-locks  還原時不lock

--no-create-db 還原時不create db

--no-create-info 還原時不create table

--no-autocommit 還原時不auto commit

--complete-insert 備份完整scheme

--net-buffer-length=1000000 加大網路buffer, 適用大檔還原

--max-allowed-packet=1000000000 加大網路packet,適用大檔還原

3 完整mysqldump參數

mysqldump -u root -p --skip-add-drop-table --skip-add-locks --no-create-db --no-create-info --complete-insert --no-autocommit --net-buffer-length=1000000 --max-allowed-packet=1000000000 --where="(date >='2020-12-21' and date<'2020-12-22')" db table | gzip >  table.sql.gz

只dump db 的 指定table內的 where 條件的資料

4 還原(因為備份時有指定參數,所以大檔也適用)

myslq login

use db;

source /home/..... sql file


5 完整流程

CREATE new_table LIKE old_table;

INSERT INTO new_table SELECT * FROM old_table;

ALTER TABLE new_table DROP COLUMN column;

mysqldump ....

restore ....

2020年12月2日 星期三

MySQL規格與基本優化

 

MySQL版本

5.7 (配合gcp 的 cloud sql)

DB引擎

InnoDB

DB規格

character 使用 UTF8mb4
collate 使用 utf8mb4_unicode_ci
CREATE DATABASE  database_name 
	character set UTF8mb4 collate utf8mb4_unicode_ci;

Table規格

character 使用 UTF8mb4
collate 使用 utf8mb4_unicode_ci
CREATE TABLE tbl_name (column_list) ENGINE=INNODB 
	CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

my.cnf設定

[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
#紀錄slow query 
log-slow-queries = /var/log/mysql/mysql-slow.log 
long_query_time = 2
log-long-format
key_buffer 能夠把所有index 載入最好

基本優化觀念

至少看以下項目:
  • 1 資料正規化/反正規化
  • 2 Primary Key / Index 建立概念
  • 3 資料庫記憶體管理
  • 4 基本效能評估

  • 基本優化方向

  • 1 基本上遵循資料正規化,有必要時就反正規化,不必拘泥於規則。
  • 2 減少資料量
  • 3 使用速度快的資料類型
  • 4 優化查詢語句速度
  • 5 硬體的影響:RAM > SSD > CPU。MySQL可以快取,RAM越大越好。

  • 基本優化項目

  • 1 RAM最好>=DB資料的3倍,避免swap SSD。
  • 2 資料類型的SQL計算速度
  • 1boolean > int > timestamp > datetime > double > char > varchar
  • 3 日期盡量用timestamp,因為速度快,且有cache
  • timestamp儲存UTC時間,會依據time zone設定返回不同時間


  • 4 有where就要建index,有order就要建index
  • primary key / index 屬性速度
    1boolean > int > char > varchar
    
  • 5 ID盡量不要使用string,因為ID是所有查詢的基本,使用string 佔空間、速度又慢。
  • 6 可以算的先算,不要讓MySQL去算。
  • 雖然MySQL有很多內建函式,但是不會比你程式算的快,而且不好維護。
    
    //使用MySQL內建函式
    SELECT * FROM table WHERE DATE_ADD(NOW(),INTERVAL 10 DAY) > create_date;
    
    //更好,先算好時間
    SELECT * FROM table WHERE DATE_ADD('2019-01-01 00:00:00',INTERVAL 10 DAY) > create_date;
    
    //更好,改成int
    SELECT * FROM table WHERE DATE_ADD(1324335674,INTERVAL 10 DAY) > create_date;
    
  • 7 order by 的標的要設成index,因為order by會讓MySQL指定key做index搜尋,權重大於WHERE條件式。
  • MySQL 常用查詢優化

    分頁查詢

    limit m,n

    limit offset m ,只取n

    實際上mysql 會取m+n,最後返回丟掉m


    MySQL Partition

     

    Partition

    官方文件
    用來把大表資料分區,分不同檔案存放。
    
    Partitioning enables you to distribute portions of individual tables 
    across a file system according to rules which you can set largely as needed. 
    In effect, different portions of a table are stored as separate tables 
    in different locations. — MySQL 5.7
    

    Partitioning 方式

    MySQL partitioning 支援 4 種分區方式,分別是 range、list、hash、key,
    要採用哪種分區方式要取決於需求以及資料本身特性,
    如果選到不適合的分區方式,效能甚至會不進反退。
    不同的分區方式,也有不同的維護方法,在決定方式前一定都要考量到

    • Range:範圍分區。例如用時間當做 partition key,每一個月為一個分區。
    • CREATE TABLE table (
          id INT NOT NULL,
          data varchar(255) NOT NULL
          timeMS timestamp
      );
      //用id 當 range
      PARTITION BY RANGE (id) (
          PARTITION p0 VALUES LESS THAN (11),
          PARTITION p1 VALUES LESS THAN (21),
          PARTITION p2 VALUES LESS THAN (31),
          PARTITION p3 VALUES LESS THAN MAXVALUE);
      
      //用 timeMS 當 range
      PARTITION BY RANGE (timeMs) (
          PARTITION p0 VALUES LESS THAN (1430409600000),
          PARTITION p201505 VALUES LESS THAN (1433088000000),
          ...中略
          PARTITION p202005 VALUES LESS THAN (1590940800000),
          PARTITION p202006 VALUES LESS THAN (1593532800000),
          PARTITION p202007 VALUES LESS THAN (1596211200000),
          PARTITION pMax VALUES LESS THAN MAXVALUE); 
            
          //p0 為台灣時區 2015/5/1 以前的資料
          //p201505 為台灣時區 2015/05 的資料 (2015/5/1 ~ 2015/5/31),而後每個月依此類推,
          //p202007 為台灣時區 2020/07 的資料 (2020/7/1 ~ 2020/7/31)
          //pMax 為台灣時區 2020/8/1 之後的資料,
          //pMax 不應該有資料,因為會預先建立未來月份的分區,讓資料寫入對應月份分區。
          //pMax 有兩個目的,其一個是捕捉不預期時間的資料,例如未來時間,另一個則是為了用來建立新分區
        

      若是InnoDB,且 innodb_file_per_table 有開啟,
      產生的分區檔案:table#p#p0.ibd、table#p#p1.ibd、table#p#p2.ibd、table#p#p3.ibd

    • List:用預設的集合分區,指定集合內的元素分別屬於哪個分區。例如以國家當做 partition key,自定義集合如下圖,國家代碼 1 就會屬於 partition 1。
    • CREATE TABLE tb (
          id INT NOT NULL,
          data varchar(255) NOT NULL
      );
      PARTITION BY LIST (id) (
          PARTITION pA VALUES IN (1,3,5),
          PARTITION pB VALUES IN (12,15));
      

      id 等於 1、3、5,分在 pA 區
      id 等於 12、15,分在 pB 區
      如果寫入的資料不在這些範圍會出錯。

    • Hash:指定分區數量 N,以單一 int 欄位或
      以回傳 int 的表達式結果 mod N決定資料屬於哪個分區。
    • CREATE TABLE tb (
          id INT NOT NULL,
          mydate DATE NOT NULL DEFAULT '1970-01-01'
      );
      PARTITION BY HASH(mydate)
      PARTITIONS 3;
        

      依據 mydate 進行 HASH 分區在 3 個 partition。
      也可以使用函式,例如 PARTITION BY HASH(YEAR(mydate)),
      每次有異動,YEAR()都會執行一次,所以複雜的運算會影響效能。

    • Key:指定分區數量 N,支援多個欄位為 partition key,用內建 hash function 決定資料屬於哪個分區。
      跟 HASH 分區類似,差在 HASH 分區使用使用者自訂的運算方式,
      KEY 分區使用 MySQL server 內部的運算方式。
    •   
      CREATE TABLE tb (
          mydate DATE NOT NULL DEFAULT '1970-01-01',
          data varchar(255) NOT NULL
      );
      PARTITION BY KEY(mydate);
      PARTITIONS 3;
        
    • 子分區
    •   //Range 分區底下,再建立 Range 分區
      CREATE TABLE tb (
          id INT NOT NULL,
          data varchar(255) NOT NULL
      );
      PARTITION BY RANGE(id)
      SUBPARTITION BY RANGE(id)(
          PARTITION p0 VALUES LESS THAN (10)(
              PARTITION s0 VALUES LESS THAN (6),
              PARTITION s1 VALUES LESS THAN MAXVALUE
          ),
          PARTITION p1 VALUES LESS THAN MAXVALUE(
              PARTITION s2 VALUES LESS THAN (30),
              PARTITION s3 VALUES LESS THAN MAXVALUE
          )
      );
        

    Partitioning key 必須是Primary key

    如果partition key 不是 pk, 那麼可以將兩個做成組合鍵

    新增 Partitioning

     
    //語法1
    ALTER TABLE tb ADD PARTITION (PARTITION p0 VALUES LESS THAN(11));
    
    //語法2
    ALTER TABLE 'tb2' REORGANIZE PARTITION pMax INTO (
        PARTITION p202008 VALUES LESS THAN (1598889600000),
        PARTITION pMax VALUES LESS THAN MAXVALUE
    );
    

    合併相鄰分區

     ALTER TABLE aa REORGANIZE PARTITION s0,s1 INTO (
        PARTITION p0 VALUES LESS THAN (11));
    

    刪除分區(刪除後,儲存在該分區的資料也會不見)

    ALTER TABLE aa DROP PARTITION p0;

    2020年12月1日 星期二

    Golang pprof

     

    go tool pprof

    pprof 是 go 內建的執行狀態分析工具

    參考1

    參考2

    pprof兩類

    runtime/pprof 是收集程式 runtime 資訊

    net/http/pprof  是收集 http 執行時資訊


    使用方式

    直接生成報告

    web interface:使用web介面

    terminal interface:使用終端介面


    可以分析什麼

    cpu profiling:依據頻率收集監控程式的cpu使用情況

    memory profiling:收集監控程式的記憶體heap,stack使用狀況。可監控是否記憶體洩漏。

    mutex profiling:阻塞分析,監控goroutine阻塞等待狀況。

    block profiling:互斥分析,報告互斥鎖競爭狀況。


    使用http pprof

    import _ net/http/pprof
    //啟動http server 會自動掛載到 default mux
    http.ListenAndServer("0.0.0.0:6060",nil)
    //會有 localhost/debug/pprof endpoint 可瀏覽

    然後可使用瀏覽器瀏覽:
    
    http://localhost:6060/debug/pprof
    會列出各種可分析的項目

    也可使用終端機取的資訊
    go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60
    go tool pprof http://localhost:6060/debug/pprof/heap
    go tool pprof http://localhost:6060/debug/pprof/block
    go tool pprof http://localhost:6060/debug/pprof/mutex
    go tool pprof http://localhost:6060/debug/pprof/threadcreate
    go tool pprof http://localhost:6060/debug/pprof/trace

    指定輸出格式
    go tool pprof http://localhost:6060/debug/pprof/profile > cpu.pprof
    //會輸出protobuf格式
    觀看檔案
    go tool pprof cpu.pprof

    指定輸出圖檔:(需要安裝 Graphviz)
    go tool pprof -png http://localhost:6060/debug/pprof/heap > out.png

    特別紀錄:

    輸出trace的檔案,要用trace觀看
    go tool pprof http://localhost:6060/debug/pprof/trace > trace.out
    要用 go tool trace trace.out 觀看

    2020年11月30日 星期一

    Golang tool

    go tool runs specific tool


     go tool [-n] command [args...]


    列出所有tool

    eg .go tool

    addr2line

    api

    asm

    buildid

    cgo

    compile

    cover

    dist

    doc

    fix

    link

    nm

    objdump

    pack

    pprof

    test2json

    trace

    vet


    tool用法說明

    go tool <command> --help

    eg. go tool api --help


    tool詳細介紹

    go doc cmd/<command>

    eg. go doc cmd/api

    2020年9月6日 星期日

    2020年8月1日 星期六

    Github

    Github 觀念

    Git是分散式管理系統

    git不是集中式管理系統,概念不同,須先搞懂。

    Repo分專案

    clone / fork

    專案分枝與合併

    master / branch / merge

    專案合併管理

    push / pull request / code review / merge


    Github 權限管理

    Branch merge 保護設定(public repo 免費,private repo 要升級)


    概念:
    每個 Repository 可以加入 Collaborators,但是主要 branch 設定 merge 保護,確保
    不被隨便 merge 。

    設定 Repository 的 branch protections rule 強制要求需要code review 才能 merge

    Setting:
    位置 Setting/Branches/Branch Protections Rule
    • 增加 Branch Protection Rule apply to 某個 branch,通常是 staging or mater
    • 在要設定權限的 branch 加一個 .github 資料夾,裡面新增 CODEOWNERS 檔案。
    • branch 設定 required pull request review before merging
    • collaborators 發 pull request
    • 之後這個 brach 要 merge,都需要 code owner approve pull request

    用組織管理權限(免費,可依據各 repo 設定 member 權限)

    管理者建立一個組織,然後加入其他人為組織成員
    每個成員可設定為組織 member 或 owner

    針對 member 可設定加入的 repo,並且可以設定其權限
    read, write, admin
    在每個 repo 的 Setting/Manage access 裡面

    Read: read, clone open comments on issues and pull requests.
    Trige: read, clone, manage issue and pull requests.
    Write: read, clone, push, manage issue and pull requests.
    Maintain: read, clone, push, mange issues, pull requests, setting
    Admin: all




    2020年7月23日 星期四

    Golang godoc

    godoc with gopath

    如果專案不用 go module,或是在專案外執行 godoc

    那就是 gopath mode

    godoc server 會從 gopath 去找src

    godoc with go module

    如果用go module,要確定module 模式是否正確
    1. 專案目錄如果有 vendor 要刪掉
    2.  在專案目錄 go env GOMOD
       看是否有顯示 go.mod 的絕對路徑
    3. 如果有,那就正確
    4. 啟動 godoc -http=:6060
    5. 瀏覽器 localhost:6060, 專案說明會在 pkg 下

    Using wget to get godoc


    1. Edit robots.txt in the go root dir,  and remove "Disallow:/"
    2. godoc -http=:6060
    3. wget -r -np -E -p -k http://localhost:6060/pkg/pathToPackage
    4. wget -m -k -q -erobots=off --no-host-directories --no-use-server-timestamps http://localhost:6060
    -r  : download recursive
    -np : don't ascend to the parent directory
    -N  : don't retrieve files unless newer than local
    -E  : add extension .html to html files (if they don't have)
    -p  : download all necessary files for each page (css, js, images)
    -k  : convert links to relative

    注釋說明

    詳細參考

    http://c.biancheng.net/view/4035.html


    package、const、variable、func 都支援註釋

    只支援public (大寫開頭)的member 註釋輸出



    註釋格式就是直接在member 上加上說明,

    但是 func 的註釋要以 func名稱開頭

    //PublicFunc

    func PublicFunc(){

    }


    const(

       //ConExample 是註釋範例

       ConExample =10

    )


    var (

        //VarExample是註釋範例

        VarExample =10

    )




    const 內的 會顯示在 Constants 區段

    var 內的 會顯示在  Variables 區段





    建立範例 example

    example_packageName_test.go

    func exampleFuncName

    func ExampleFuncName() {

    logger.Info("hello, world.")

    }

    Bug 標示

    這樣會顯示bug 標示


    //BUG(rsc): 

    func BadFunc(){

    }



    2020年7月14日 星期二

    Linux 使用資源限制

    資源的限制

    Two types of ulimits

    Hard limit is the maximum value that is allowed for the soft limit. Any changes to the hard limit require root access.

    Soft limit is the value that Linux uses to limit the system resources for running processes. The soft limit cannot be greater than the hard limit.

    Hard 設定給 soft 的最大值。任何 hard 改變都需要 root 權限。
    Soft 是 linux 限制給每個 process 的上限。Soft 不能超過 hard 上限。

    ulimit -aH 顯示 hard 全部設定
    ulimit -aS 顯示 soft 全部設定

    Soft Hard 區別

    ulimit 參數詳解


    依據設定的層級分系統級、user級

    分系統級、User級。
    user級不能超越系統級。


    • 可針對 user 做個別設定,在 /etc/security/limits.conf。其中 * 代表所有 user。
    • 限制設定落實到 user 啟動的 process。
    • 限制設定是繼承性的,子 process 繼承父 process 的設定值。

    範例:
    User 起動 shell, shell 的設定來自系統預設及 /etc/security/limits.conf。
    User 在 shell 中啟動 process,此時 process 繼承 shell 的設定。

    臨時設定
    shell 中使用 ulimit 命令設定,但結束 session就沒有了。
    ulimit -s unlimited //設定 stack unlimited
    ulimit -n 2048. //open file 數 2048

    永久設定 
    更改 /etc/security/limits.conf
    更改後重新 login 就可套用新設定


    查詢當前user / process 設定

    ulimit -aH //顯示所有設定 hard
    ulimit -aS //顯示所有設定 soft
    core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 31204
    max locked memory       (kbytes, -l) 64
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 1024         (file descriptor)
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 0
    stack size              (kbytes, -s) 8192
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 31204
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited
    

    查詢 pocess 設定

    cat /proc/{pid}/limits
    
    //example cat /proc/1888/limits
    
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             31204                31204                processes 
    Max open files            1024                 4096                 files     
    Max locked memory         65536                65536                bytes     
    Max address space         unlimited            unlimited            bytes     
    Max file locks            unlimited            unlimited            locks     
    Max pending signals       31204                31204                signals   
    Max msgqueue size         819200               819200               bytes     
    Max nice priority         0                    0                    
    Max realtime priority     0                    0                    
    Max realtime timeout      unlimited            unlimited            us  
    
    //Max processes 是可開啟執行緒上限持

    查詢 pocess 資源使用量

    cat /proc/xxxxx/stat
    cat /proc/xxxxx/status

    //顯示某 process file descriptor數量
    
    lsof -p 28290
    lsof -a -p 28290
    
    or 
    //列出
    ls -l /proc/28290/fd | less
    
    //計算總數
    ls -l /proc/28290/fd | wc -l
    

    系統總上限

    sysctl fs.file-nr

    fs.file-nr    //顯示已經分配的 fd 數量、可分配的 fd 數量、系統總 fd 數量

    fs.file-max  //系統所有 process 可使用的總 fd 數量


    查看系統設定

    sysctl fs.file-nr //輸出 fs.file-nr = 1020 0 70000 1. 1020 The number of allocated file handles. 2. 0 The number of unused-but-allocated file handles. 3. 70000 The system-wide maximum number of file handles. cat /proc/sys/fs/file-max 或是看上限設定 sysctl fs.file-max 臨時性修改 sysctl -w fs.file-max=102400 永久修改 sudo vim /etc/sysctl.conf fs.file-max = 70000 //這個數值對應於hard limit sysctl -p 使修改生效

    系統設定的user上限

    fs.nr_open

    系統級user的單一process開檔數限制

    查看
    cat /proc/sys/fs/nr_open
    
    或是
    sysctl fs.nr_open
    
    修改
    sudo /etc/sysctl.conf
    nr_open=1000000

    實際真正個人上限

    vi /etc/security/limits.conf
    * hard nofile 102400  //針對所有user,不包括root
    * soft nofile 102400  //針對所有user,不包括root
    
    httpd hard nofile 102400  //針對httpd這個user
    httpd soft nofile 102400  //針對httpd這個user
    
    root hard nofile 102400  //針對root
    root soft nofile 102400  //針對root
    
    
    

    結論

    user的每個process開檔上限這些限制
    1 fs.file-max:系統總上限
    2 fs.nr_open:系統設定的個人上限,限制 limits.conf設定的上限
    3 /etc/security/limits.conf中nofile設定:實際真正能使用的數量
    # /etc/security/limits.conf
    
    //設定值
    //
    core - 限制内核文件的大小
    date - 最大数据大小
    fsize - 最大文件大小
    memlock - 最大锁定内存地址空间
    nofile - 打开文件的最大数目
    rss - 最大持久设置大小
    stack - 最大栈大小
    cpu - 以分钟为单位的最多CPU时间
    noproc - 进程的最大数目
    as - 地址空间限制
    maxlogins - 此用户允许登录的最大数目
    
    # * 代表针对所有用户
    * soft nofile 102400  
    * hard nofile 102400
    * soft stack unlimited  //開啟stack 無限制
    # /etc/security/limits.conf
    * soft nproc 100  //不能太大
    * hard nproc 100 //不能太大
    
    # /etc/security/limits.conf
    * - nproc 100
    * - nofile 102400
    

    2020年7月13日 星期一

    Linux Command free

    free

    顯示系統記憶體使用狀況
    free是從 /proc/meminfo讀取資料

    free
    free -b  //單位Bytes
    free -m  //單位MB
    free -g  //單位GB
    free -t  //實體記憶體加上swap 

    total
    used
    fee
    shared
    buffers:(buffer cache)relatively temporary storage for raw disk blocks.
    cached:(page cache)in memory cache for files read from disk, doesn't include swapcache 

    Linux 查找記憶體洩漏

    top

    顯示process的記憶體使用
    top -p pid
    top 列出所有process, 再按 p, m等指令去切換

    VIRT一直增加,可能是有洩漏

    VIRT virtual memory usage 虛擬記憶體
            包括lib, code, data等
             process申請的虛擬記憶體大小,如果申請了100m, 但是只用20m,那還是100m
      
    RES resident memory usage 常駐記憶體
           當前使用的記憶體大小,不包括swap out
           包括其他process共享記憶體
           如果申請100m,只用10m,那就是10m

    SHR shared memory 共享記憶體
          process本身使用的共享記憶體
          包括整個共享lib 的大小,就算只用了其中一個lib
          計算process使用的物理記憶體使用量 RES-SHR
          swap out之後會降下來

    DATA 資料佔用的記憶體
          top 沒顯示,按 f 鍵可顯示
          真正的process 要求的資料空間

    free

    顯示系統記憶體使用狀況
    free -m

    pmap

    顯示process 記憶體使用映射

    sudo pmap pid
    sudo pmap -X pid
    sudo pmap -XX pid

    writeable/private 是實際使用記憶體,不含share lib
    一直增加就可能有洩漏

    2020年6月20日 星期六

    MySQL 8 更改 remote access

    //Create the root user 
    1  nano /etc/my.cnf  //centos7
    
     comment the bind_address  (好像不需要)
     或是 
     bind_address 0.0.0.0
    
    
    2 create user root
    //(yes, a new user because what exists is 'root@localhost'
    // which is local access only):
    
    CREATE USER 'root'@'%' IDENTIFIED BY '123';
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
    
    
    3 restart
    sudo systemctl restart mysqld
    

    2020年6月10日 星期三

    2020年5月18日 星期一

    MySQL Variables / Status / 優化

    MySQL connections variables

    Apple MySQL 必要修正一些預設值

    //show
    mysql> show variables like '%conn%'l;

    //set
    mysql> set global max_connections=10240;

    //select
    mysql> select @@global.sort_buffer_size;

    • max_connections
      最大連線數。
      要比歷史連線數 status 的 Max_used_connections 高。
      預設:100
      建議:看系統

    • max_user_connections
      每個使用者最大連線數

    • max_connection_errors
      最大連線錯誤數,如果連線錯誤超過此數會出錯。
      連線錯誤是指例如帳密錯誤之類。
      這個設定沒有實際作用,
      是讓你看有多少錯誤。
      預設:
      建議:1844674407370954751,越大越好

    • connect_timeout
      連線逾時(秒)
      預設:5
      建議:10-15

    golang 的 sql package connections 設定

    golang mysql api

    Understanding maxLifeTime on MySQL
    • SetMaxIdleConns
      the maximum number of connections in the idle connection pool.
      連接池中的最大閒置連線數。

    • SetMaxOpenConns ¶
      最大同時開啟連線錯數。

    • SetConnMaxLifetime
      連接池中閒置的連線當時間達到設定,就會被關閉。
      使用中的連線不會被關閉,

    MySQL connections status

    mysql=> show status like 'conn%';
    • Connection_errors_accept
    • Connection_errors_internal
    • Connections_errors_max_connections
    • Connections
      The number of connection attempts (successful or not) to the MySQL server.
      有史以來總連接數

    • Max_used_connections
      最大同時連接數

    • Max_used_connections_time
      最大連線使用時間

    • Thread_connected
      The number of currently open connections.
      當前連接數

    • Locked_connects

    顯示當前連線及執行緒狀況

    mysqladmin -u -p extended-status | grep -wi 'threads_connected\|threads_running' 
    | awk '{ print $2,$4}'
    
    //output
    Threads_connected 12
    
    Threads_running 1  
    
    Threads_connected: Number of connections
    
    Threads_running: connections currently running some sql
    


    官方文件

    MySQL 8 Variables 官方文件

    MySQL 5.7 Variables 官方文件

    網上說明

    MySQL 8.0 預設值

    優化

    my.cnf優化

    Fix poor mySQL default variables

    改 variable 及 my.conf

    open_files_limit  default 10000, optimize 10000
    這是read only variable
    需要編輯 /usr/lib/systemd/system/mysqld.service
    LimitNOFILE=infinity
    LimitMEMLOCK=infinity
    Then run systemctl daemon-reload and systemctl restart mysql.service.


    innodb_open_files default 4000,  
    指定MySQL可同时打开.ibd文件的最大个数,独立于open_files_limit

    max_connections  default 151, optimize  5000

    max_user_connections default 0,   optimize 0  //沒限制

    max_connect_errors  default 100, optimize  1844674407370954751 //越大越好,這個值沒用

    connect_timeout default 10, optimize 15   //加5秒

    table_open_cache default 4000, optimize 4000
    所有线程打开表的数目。它的作用就是缓存表文件描述符,降低打开关闭表的频率,

    table_open_cache_instances default 16, optimize 16
    表缓存实例数,为通过减小会话间争用提高扩展性,表缓存会分区为table_open_cache/table_open_cache_instances大小的较小的缓存实例。DML语句会话只需要锁定所在缓存实例,这样多个会话访问表缓存时就可提升性能(DDL语句仍会锁定整个缓存)。默认该值为1,当16核以上可设置为8或16


    2020年3月31日 星期二

    編程範式:Functional / Imperative / OO / Procedure Programming

    常見的編程範式有以下幾種:
    functional programming(函數式編程)
    imperative programming(命令式編程)
    Objective-Oriented programming(物件導向式編程)
    procedure programming(程序式編程)

    Functional Programming

    Functional programming 沒有只是構想,沒有絕對的規定。
    視程式設計為數學函式,每個函式各自獨立,彼此互不影響,
    只要每個各自獨立的函式是正確的,那麼整個程式就是正確的。

    各程式語言實作不同,但是有共通點:

    • No Side Effect-在表示式(Expression)內不可以造成值的改變。
    • First-Class Function-函數被當作一般值,可當傳入參數、傳出結果。
    • 資料放在堆疊stack-或由堆疊指向heap。
    • 盡量避免[狀態]與[可變資料],一切與函式內部無關。

    優點

    • Unit test 相對容易。以函式為單位,且只檢查輸入、輸出是否正確,不管其他狀態。
    • 好除錯,因為沒有外部變數影響,所以錯誤容易重現,好找。
    • 因為可以保留函式內狀態(closure)所以程式可以精簡。
    • 適合寫併發(Concurrency)程式,因為不共享記憶體、沒執行緒、不上鎖、不擔心Critical Section。

    Functional Programming到底做了什麼?

    • Higher-Order Functions-可接受函式當參數,或以函式為回傳值的函式,稱為 higher-order function,容易進行資料處理(排序、過濾、對應)。
    • Currying-用currying方式,定義特殊化函式。例如,有個函數為power(x, y),會計算出x的y次方,那麼事先將參數y指定為2,就可以定義一個平方函數square(x)。
    • Lazy Evaluation-表示式可拖到真正需要執行才執行,因此編譯器有更大的優化空間。
    • Continuations-將一個函數的傳出值,傳進另一個函數當作傳入值,也可以產生循序執行的效果。
    • Pattern Matching-模式比對的方式,可以讓系統自動幫我們進行分支與變數的指定。降低switch/case依賴、多型依賴。
    • Closure-函式離開後,其context依然保留,保留在內部函式,可當傳出值。
    • List processing-有好用的list處理函式。
    • Meta-Programming-許多FP語言都提供方便的Meta-Programming工具,讓你可以設計自己的Domain specific language

    Imperative Programming(命令式編程)

    Imperativ programming 認為程式的執行,就是一連串狀態的改變。
    資料大量放在heap中。利用大量的流程控制,或狀態判斷還選擇執行的程式。
    例如switch/case就是最好的例子。

    Objective-Oriented Programming

    2020年3月21日 星期六

    Javascript mocha

    mocha in webstorm

    1. npm install mocha --save-dev  //安裝在專案目錄
    2. npm init esm                  //讓test file 可以使用 es6 syntax
       //如果是舊專案 npm i esm
    
    3. 
    現在test file 可以使用 require (nodejs)
    test file 可以使用 import es6 語法
    
    4. webstorm 設定
    Preferences=>
    Language & Frameworks=>
    Javascript=> Libraries
    
    Add 搜尋 mocha 
    新增後名稱是 @types/mocha
    (這樣mocha 語法不會顯示錯誤)
    
    5. package.json
     "scripts": {
        "test": "mocha -r esm"     //使用es6語法
       }
    
    
    6. 執行測試
     npm test
     會執行 test 目錄下的 裡面有 mocha test 的檔案 xxx.test.js
    

    2020年3月12日 星期四

    gitlab SSH

    Gitlab SSH

    官方說明


    //create ssh key
    eg. rsa ssh key
    ssh-keygen -t rsa -b 4096 -C "email@example.com"
    
    
    //如果有多組 ssh key,可指定使用哪一組
    
    寫入config檔
    ~/username/.ssh/config
    
    //範例
    # GitLab.com
    Host gitlab.com
      Preferredauthentications publickey
      IdentityFile ~/.ssh/gitlab_com_rsa
    
    # Private GitLab instance
    Host gitlab.company.com
      Preferredauthentications publickey
      IdentityFile ~/.ssh/example_com_rsa
    
    //測試
    ssh -T git@gitlab.com
    
    如果成功,會詢問是否把domain加到known_hosts
    
    //刪除 known_hosts
    所有的ssh 都會重新詢問一次
    
    
    

    2020年3月1日 星期日

    Javascript OOJS 物件導向JS

    prototype 語言

    Javascript 是基於 prototype 的語言,
    意思是他是利用 prototype 建立起整個語言架構。

    有一個最基礎的 null,
    然後所有物件的基礎物件 Object 就是繼承自 null 這個 prototype,
    Object 本身自己有一個 prototype 屬性,
    這個屬性是他讓別人繼承的,
    也就是別的物件要繼承自 Object 時,
    他其實繼承的是 Object 的 prototype 屬性(這個屬性裡可以包含很多東西)。

    所以用 Javascript 寫的程式,
    就是這樣,一個物件繼承自另一個物件的 prototype 屬性,逐步建立起整個程式。

    建立物件的方式一:function 回傳物件

    利用函式回傳一個物件。
    沒彈性,而且每一個物件都是 object。

    function createNewPerson(name) {
      var obj = {};
      obj.name = name;
      obj.greeting = function () {
        alert('Hi! I\'m ' + this.name + '.');
      }
      return obj;
    }
    

    建立物件的方式二:Object()建構子

    //new Object() 建立空白物件
    //再把屬性加上去
    var person1 = new Object();
    person1.name = 'Chris';
    person1['age'] = 38;
    person1.greeting = function() {
      alert('Hi! I\'m ' + this.name + '.');
    }
    
    
    //或是直接傳入一個物件當參數
    var person1 = new Object({
      name : 'Chris',
      age : 38,
      greeting : function() {
        alert('Hi! I\'m ' + this.name + '.');
      }
    });
    
    

    建立物件的方式三:Object.create() 函式 IE8不支援



    var person2 = Object.create(person1);
    
    //person2.name
    //person2.greeting()
    
    

    建立物件的方式四:建構子函式 constructor function

    WDN
    Constructor funciton 是一種特殊的函式,
    用來建立物件。
    比用傳統方式建立物件好很多。

    function Person(name,interests) {
      this.name = name;
      this.interests=interests;
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
    }
    
    var person1 = new Person('Bob',[1,2,3]);
    var person2 = new Person('Sarah',[1,2,3]);
    
    console.log(person1['name']);        //可以這樣取
    console.log(person1.interests[1]);   //可以這樣取
    console.log(person1.greeting());
    console.log(person2.name);
    console.log(person2.greeting());
    
    

    用建構子函式實體化的物件

    建構子函式實體化的物件,
    建構子函式定義的prototype屬性,只會有一份,
    不會複製到每個實體上。

    繼承(更接近於delegate 委託)

    Javascript 的繼承,是[原型繼承](Prototypal inheritance)。
    子物件不會把父物件可繼承的屬性複製過來,
    而是用原型鍊連結他繼承的屬性。
    子物件的繼承其實不是繼承,而是連接,
    連接父物件prototype屬性。
    所以一個父物件,不管延伸出多少子物件,
    子物件繼承的屬性都只有一份,
    就是存在父物件 prototype 屬性的那份。

  • 繼承方式一:實體化一份父物件,但是owner設成自己


  •    
      //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
         
        var t=new Teacher("a","b",3,1,"book","math");
        console.log(t.name);     //{"a","b"}
    
    



  • 繼承方式二:繼承父物件的 prototype 屬性


  • 每個物件的 prototype 屬性,是要繼承下去的。
    所以父物件的 prototype 屬性要連結在子物件的 prototype 屬性上。
    而子物件要讓孫物件繼承的屬性,也加到自己的 prototype 屬性上。



     
       //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
       //繼承父物件的 prototype 屬性
       Teacher.prototype=Object(Person.prototype);
      //**記得要把 constructor 設成自己,否則會是 Person 
       Teacher.prototype.constructor = Teacher;    
    
       var t=new Teacher("a","b",3,1,"book","math");
       console.log(t.name);     //{"a","b"}
       console.log(t.greeting());   //繼承自父物件的屬性
    
    

    複寫繼承自父物件的屬性

     
       //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            console.log('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
       
       //繼承父物件的 prototype 屬性
       Teacher.prototype=Object(Person.prototype); 
       //**記得要把 constructor 設成自己,否則會是 Person
       Teacher.prototype.constructor = Teacher; 
    
       //複寫父物件的 greeting
       //**要在 Teacher.prototype=Object(Person.prototype) 之後,才有複寫到
       Teacher.prototype.greeting=function(){
             console.log('Hi! I\'m teacher.');
       }   
    
       var t=new Teacher("a","b",3,1,"book","math");
       console.log(t.name);     //{"a","b"}
       console.log(t.greeting());   //變成自己的屬性
    
    

    Javascript npm

    INSTALL

    npm install takes 3 exclusive, optional flags which save or update the package version in your main package.json

    npm install (with no args, in package dir)
    npm install [<@scope>/]
    npm install [<@scope>/]@
    npm install [<@scope>/]@
    npm install [<@scope>/]@
    npm install 
    npm install 
    npm install 
    npm install 
    npm install /
    


  • S, --save: Package will appear in your dependencies.
  • -D, --save-dev: Package will appear in your devDependencies.
  • -O, --save-optional: Package will appear in your optionalDependencies.


  • install command example

    npm install module-name
    //npm 只會安裝module
    //需手動把 module and version 寫到 package.json 的 dependencies 區塊裡。
    
    npm install module-name -save
    //npm 安裝 module
    //並且把 module and version 寫到 package.json 的 dependencies 區塊裡。
    
    
    npm install module-name -save-dev
    //npm 安裝 module
    //並且把 module and version 寫到 package.json 的 devDependencies 區塊裡。
    
    npm install module-name -save-optional
    //npm 安裝 module
    //並且把 module and version 寫到 package.json 的 optionalDependencies 區塊裡。
    
    

    假設 package.json 已經有 dependencies

    npm install //package.json 中 dependencies 和 devDependencies 都會安裝。 npm install --production //package.json 中 dependencies 會安裝。

    2020年2月20日 星期四

    Javascript this

    this

    不同地方有不同意義

    • 獨立的this(全域),指向他的擁有者,就是windows 物件
    • 非嚴謹模式下,在function中,是 global 物件
    • 嚴謹模式下,在function中,是 undefined
    • 在物件 event callback中, 是接收這個event的物件(實際執行callback的物件),也可解釋為擁有者
    • call(),apply()中,this是自己傳入,可以是任意物件
    It has different values depending on where it is used:
    
    In a method, this refers to the owner object.
    Alone, this refers to the global object.
    In a function, this refers to the global object.
    In a function, in strict mode, this is undefined.
    In an event, this refers to the element that received the event.
    Methods like call(), and apply() can refer this to any object.
    

    2020年1月8日 星期三

    Javascript JSON - Object 轉換

    JSON - Object 轉換

    Object to JSON

    //Object to JSON 
    var obj={
          a:2,
          b:1,
        }
    
    var str=JSON.stringify(obj);
    
    

    JSON to object

    //JSON to object
    
    var obj={
          a:2,
          b:1,
        }
    var obj2=JSON.parse(obj)
    
    

    JSON to function object

    //JSON to function object
    function Foo(obj) // CONSTRUCTOR CAN BE OVERLOADED WITH AN OBJECT
    {
        this.a = 3;
        this.b = 2;
        this.test = function() {
         return this.a*this.b;
        };
        // IF AN OBJECT WAS PASSED THEN INITIALISE PROPERTIES FROM THAT OBJECT
        for (var prop in obj) {
         this[prop] = obj[prop];
        }
    }
    
    //var fooObj = new Foo();
    //alert(fooObj.test() ); //Prints 6
    
    // INITIALISE A NEW FOO AND PASS THE PARSED JSON OBJECT TO IT
    var fooJSON = new Foo(JSON.parse('{"a":4,"b":3}'));
    
    alert(fooJSON.test() ); //Prints 12
    
    

    Object assign (IE及小於45以下 android chrome不支援)

    const target = { a: 1, b: 2 };
    const source = { b: 4, c: 5 };
    
    const returnedTarget = Object.assign(target, source);
    
    console.log(target);
    // expected output: Object { a: 1, b: 4, c: 5 }
    
    console.log(returnedTarget);
    // expected output: Object { a: 1, b: 4, c: 5 }
    
    //returnedTarget跟target是同一個物件
    
    returnedTarget.a=0;
    console.log(target);
    // expected output: Object { a: 0, b: 4, c: 5 }