MongoDB 效能調校紀錄

mongodb

最近剛好在實作 Prometheus + Grafana 的時候,對 MongoDB 做了容器 CPU 使用率 (container_cpu_usage_seconds_total) 的監控,Metrics 寫法如下:

1
2
3
sum(
    rate(container_cpu_usage_seconds_total{name!~"(^$|^0_.*)"}[1m]))
by (name)

從上面的 Metrics 可以拉長時間來看,會發現專案的 MongoDB 非常不穩定,起起伏伏,這時候就需要來看看資料庫到底哪邊慢,以及看看哪個語法造成 CPU 飆高?

接著為了看 MongoDB 的 Log 紀錄,把 Grafana 推出的 Loki,也導入專案系統,將容器所有的 Log 都導向 Loki,底下可以看看 docker-compose 將 Log 輸出到 loki

1
2
3
4
5
6
7
    logging:
      driver: loki
      options:
        loki-url: "http://xxxxxxx/loki/api/v1/push"
        loki-retries: "5"
        loki-batch-size: "400"
        loki-external-labels: "environment=production,project=mongo"

先看看結論,做法其實很簡單,找出相對應 Slow Query,把相關的欄位加上 Index,就可以解決了

[Read More]

將 Postgres 資料轉換到 CSV 格式

postgres

時常用到 Postgres 轉換資料的功能,來即時協助 PM 了解目前使用者實際狀況,底下紀錄常用的指令。首先安裝 Postgres 環境,這邊其實就是用 Docker 方式來啟動一個全新的 Postgres DB。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
  db:
    image: postgres:12
    restart: always
    volumes:
      - pg-data:/var/lib/postgresql/data
    logging:
      options:
        max-size: "100k"
        max-file: "3"
    environment:
      POSTGRES_USER: db
      POSTGRES_DB: db
      POSTGRES_PASSWORD: db

上面的 environment 參數可以自由調整,接著透過 docker-compose up -d 來啟動資料庫進行 App 串接。

[Read More]

在 PostgreSQL 時區轉換及計算時間

postgres

通常在使用資料表時,都會在每一筆紀錄上面寫入當下時間,而這個時間會根據目前系統所在的時區而有所不同,當然我們都會使用 UTC+0 作為標準時區,而欄位我們則會是使用 timestamp 或者是 unix time 格式,兩者最大的差異就是在前者 (timestamp) 會根據目前系統的時區來記錄,而後者 (unix time) 則是紀錄秒數差異 (Jan 01 1970) 而不會隨著系統時區改變而變化。如果是發展開源專案,則會使用後者居多,這樣不會因為使用者時區變化,而產生不同的差異,在 Gitea 開源專案保留了兩者,但是只要計算時間則是用 (unix time) 作轉換。

[Read More]

增加 phpMyAdmin 登入時間

phpMyAdmin 是一套管理 MySQL 資料庫的 UI 介面工具,預設登入時間為 1440 秒,這時間是定義在 libraries/config.default.php 內,phpMyAdmin 也是透過 gc-maxlifetime 來決定 Session 存在與否,所以如果要增加登入時間,比如說設定一年 (3600 * 24 * 365) 好了,請按照底下設定 PHP 設定檔 如果是裝 php-fpm 請修改 /etc/php5/fpm/php.ini 路徑 1 2 3 ;After this number of seconds, stored data will be seen as \'garbage\' and ; cleaned up by the garbage collection process. ; http://php.net/session.gc-maxlifetime session.gc_maxlifetime = 315360000 重新啟動 php-fpm 1 $ /etc/init.d/php5-fpm restart phpMyAdmin 設定檔 修改 config.inc.php 如果找不到此檔案,請複製 config.sample.inc.php 為 config. [Read More]

[資料庫] 如何轉換 Mysql varchar type 到 int type

先來說明為什麼有時候需要用到轉換 varchar 到 int 型態,就是因為 order by 的問題,幫學校修改 Mysql 錯誤排序,前人設計全部都用 varchar 型態去存資料,當然包含了學生入學年度,以前不會遇到這問題,但是到了民國100年,就會發生排序錯誤,底下來講個例子,這樣大家就可以瞭解了。 建立 test 資料表,並且先增兩個欄位分別是 a(varchar) 跟 b(int),個別輸入 100, 90 兩列資料

mysql> select * from test;
+------+------+
| a    | b    |
+------+------+
| 100  |  100 |
| 90   |   90 |
+------+------+
先針對 varchar 排序 order by a DESC
mysql> select * from test order by a desc;
+------+------+
| a    | b    |
+------+------+
| 90   |   90 |
| 100  |  100 |
+------+------+
再來針對 int 排序 order by b DESC
mysql> select * from test order by b desc;
+------+------+
| a    | b    |
+------+------+
| 100  |  100 |
| 90   |   90 |
+------+------+
[Read More]

[網站] 好站連結 (七) Android, javascript, Css, PHP, Perl, FreeBSD, Linux

Windows C# C# 比較字串 MSDN 比較字串 Request.Form Collection Request Query String / Form Parametrs ASP.NET QueryString Usage Using include files with ASP.NET html [將所有 的內容包到一個 中][7] apache Fixing mod_rewrite and .htaccess on GoDaddy Hosting javascript jQuery Week Calendar Javascript: reference the parent window from a popup How to get and set form element values with jQuery How to check and uncheck a checkbox with jQuery Loop through parameters passed to a Javascript function perl-completion. [Read More]

PHP+MySQL 環境下 SQL Injection 攻防戰

OurMySQL Blog 看到這篇:『PHP+MySQL环境下SQL Injection攻防总结』寫的相當不錯,裡面有一些觀念,可以讓初學 PHP & MySQL 的使用者知道如何防護 SQL Injection (資料隱碼),內容提到 magic_quotes_gpc 在 on 跟 off 的狀況如何防護,但是可以清楚看到 PHP 官方文件提到在 PHP 5.3.0 magic_quotes_gpc 預設已經是關閉,在 PHP 6.0 之後正式移除,所以內容寫的 magic_quotes_gpc 狀況,可以大致上瞭解就好,真正防護 SQL Injection 是需要寫程式或者是考慮很多方式去防護。 一般在做文章查詢,都會使用 /articles.php?id=123 網址傳送方式,以 $_GET[‘id’] 送到 PHP 頁面去做處理,如果駭客想要測試是否可以利用 SQL Injection 做攻擊,可以在網址列加上 /articles.php?id=123,請注意網址後面多出 ,如果沒有把 $_GET[‘id’] 做處理的話,就會出現底下錯誤訊息:

supplied argument is not a valid MySQL result resource in 這是因為平常在寫 SQL 語法,會是底下這種寫法:

$sql = "SELECT id, title, content FROM articles WHERE id = '".$_GET['id']."'";
$result = mysq_query($sql);
因為沒有處理跳脫字元 ',所以造成 SQL 語法錯誤,才會出現該錯誤訊息,但是如果又針對跳脫字元做防護得時候,還有另一種攻擊方式:

/articles.php?id=0 union select 1,2,load_file(char(47,101,116,99,47,112,97,115,115,119,100)) 其中的數字就是/etc/passwd 字符串的ASCII,除此之外,還可以使用字串 16 進位方式:

/articles.php?id=0 union select 1,2,load_file(0×2f6574632f706173737764) 可以參考一下 MySQL LOAD_FILE(file_name),底下文章提到了很多方式解決。

[Read More]
php 

[SQL] Microsoft SQL Server 2008 Management Studio 防止儲存需要資料表重建的變更

最近要寫 ASP.Net 專案,弄 MSSQL Server 2008 當作 Database,利用 SQL 2008 SQL Server Management Studio 管理資料庫,有點類似 MySQL Navicat Lite 軟體,或者是 Web 介面的 phpMyAdmin,在資料表填入欄位新增第一次之後,接下來要去修改資料表,發現會出現錯誤訊息:『防止儲存需要資料表重建的變更MSSQL2008_01 (by appleboy46) 解決方法其實很簡單:工具->選項->左邊選單 Designers,裡面把**防止儲存需要資料表重建的變更**,取消掉,就可以了 MSSQL2008_02 (by appleboy46) 參考資料:[SQL]使用SQL 2008 SQL Server Management Studio 更改資料表結構 出現錯誤訊息不允許儲存變更

[SQL] MySQL ROW_NUMBER Simulation

在台大 PTT Database 版看到有人問一個問題,我覺得還不錯,問題如下:網頁版

小弟在練習做一個系統遇到以下問題 志願 | 系所 | 功能 1 | a | 退選 2 | b | 退選 3 | c | 退選 4 | d | 退選 5 | e | 退選 網頁介面如上(用for迴圈+mysql_fetch_object抓出資料) 報名序號 | 姓名 | 志願1 | 志願2 | 志願3 | 志願4 | 志願5 1001 小王 a b c d e 資料庫欄位內容如上 想請問若使用者想退選志願3~~照理說用update把志願3欄位清掉 網頁再一次抓資料會變成志願3的系所變空的(如下表) 志願 | 系所 | 功能 1 | a | 退選 2 | b | 退選 3 | | 退選 4 | d | 退選 5 | e | 退選 有沒有辦法在select的時候排除空的那欄 也就是說抓資料的時候,以上述為例,只抓出4筆,變成下表 志願 | 系所 | 功能 1 | a | 退選 2 | b | 退選 3 | d | 退選 4 | e | 退選

[Read More]