顯示具有 postgresql 標籤的文章。 顯示所有文章
顯示具有 postgresql 標籤的文章。 顯示所有文章

2013/04/12

SQL Injection Prevention - Postgresql

這是一個 C 版本的 postgresql database 存取
#include <libpq-fe.h>

#define UPDATE_COMMAND   \
        "UPDATE employee SET password='%s' WHERE username='%s';"

int db_update(char *username, char *password)
{
  PGconn            *conn;
  PGresult          *res;
  ExecStatusType    status;
  char              query[1024];

  // connect to server

  /*
   * Set parameter
   */
  snprintf(query, sizeof(query), UPDATE_COMMAND, password, username);

  /*
   * Execute the query.
   */
  res = PQexec(conn, query);
  if (res) {
    status = PQresultStatus(res);
    if (status == PGRES_COMMAND_OK)) {
      printf("Update successfully\n");
    } else {
      printf("error message=[%s]\n", PQresultErrorMessage(res));
    }
  }
}
初學者容易犯的錯誤就是把 user input 直接跟 SQL query 串接在一起,如果 username, password 存在不安全的字眼,很有可能會造成 SQL injection,切記永遠不要相信 user 的資料,該做的檢查、防呆都不能少。


改成參數形式就可以避免 :)
Database client library 都會有提供類似的用法
#include <libpq-fe.h>

#define UPDATE_COMMAND   \
        "UPDATE employee SET password=$1 WHERE username=$2;"
#define PREPARED_STMT    "my_update"
#define NPARAMS          2

int db_update(char *username, char *password)
{
  PGconn            *conn;
  PGresult          *res;
  ExecStatusType    status;
  char              *params[NPARAMS];

  // connect to server

  /*
   * Set parameter
   */
  params[0] = password;
  params[1] = username;

  res = PQprepare(conn, PREPARED_STMT, UPDATE_COMMAND, NPARAMS, NULL);
  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
    printf("PQprepare() failed [%s]", PQresultErrorMessage(res));
    return -1;
  }

  /*
   * Execute the query.
   */
  res = PQexecPrepared(conn, PREPARED_STMT, NPARAMS, 
                       (const char **)params, NULL, NULL, 0);
  if (res) {
    status = PQresultStatus(res);
    if (status == PGRES_COMMAND_OK)) {
      printf("Update successfully\n");
    } else {
      printf("error message=[%s]\n", PQresultErrorMessage(res));
    }
  }
}
關於 PQprepare()、PQexecPrepared() 的使用方式可以參考官方文件

2011/10/04

Postgresql + pgpool-II

抓一張官方的示意圖:

特色
  • Connection Pooling: 減少建立connection的overhead
  • Load Balance: 依照負載去dispatch
  • Replication: 所有的修改都會replication到底下所有database
  • Parallel Query
不外乎就是要來增加throughput啦。

設定
可以參考官方網站,在這邊以下列的架構為例




pgpool 192.168.0.2
DB1 192.168.0.3
DB2 192.168.0.4


2011/09/26

Postgresql建立索引

有沒有建索引的查詢速度真的差很多,預設是使用binary-tree來實作index,時間複雜度是O(logN)。從N變成logN,是有指數級的差距!

建index的方法可以參考


以下舉幾個例子,假如我們的table叫account,email這個欄位很常用來當查詢條件,那我們會為email建立index:
postgres=> CREATE INDEX account_email_idx ON account (email);
postgres=> \d account;
Indexes:
    "account_pkey" PRIMARY KEY, btree (id)   # Primary key預設就會建立index了
    "account_email_idx" btree (email)

Composite index?
Composite indexes are used when two or more columns are best searched as a unit or if many queries reference only the columns specified in the index.
All the columns in a composite index must be in the same table.
我自己把它解釋成當一個query同時帶多個條件時,composite index可以加快查詢的速度。
postgres=> CREATE INDEX account_composite_idx ON account (name, email);
postgres=> \d account;
Indexes:
    "account_pkey" PRIMARY KEY, btree (id)
    "account_composite_idx" btree (name, email)


除了建索引,定期清理(VACUUM) database 也可以加快存取速度
postgres=> VACUUM VERBOSE ANALYZE;

2011/09/21

Postgresql 小記

常用指令
# Start
su postgres -c "/usr/local/pgsql/bin/pg_ctl start -D /usr/local/pgsql/data"

# Stop
su postgres -c "/usr/local/pgsql/bin/pg_ctl stop -D /usr/local/pgsql/data"

# restart
su postgres -c "/usr/local/pgsql/bin/pg_ctl restart -D /usr/local/pgsql/data"

# Init postgres
sudo mkdir /usr/local/pgsql/data
chown postgres:postgres /usr/local/pgsql/data
su postgres -c "/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data"

# Create user
/usr/local/pgsql/bin/createuser -U postgres -P userA

# Drop user
/usr/local/pgsql/bin/dropuser -U postgres userA

# Create db
/usr/local/pgsql/bin/createdb -O userA -U postgres testdb

# Drop db
/usr/local/pgsql/bin/dropdb -U postgres testdb

# Dump db
/usr/local/pgsql/bin/pg_dump -U postgres testdb > dump.sql

# Restore db
/usr/local/pgsql/bin/psql -U postgres -d testdb < dump.sql

# Grant all privileges
/usr/local/pgsql/bin/psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE testdb TO userA;"

# Enter postgresql command line
/usr/local/pgsql/bin/psql -U postgres -d poesgres -h localhost -p 5432


基本設定
  • /usr/local/pgsql/data/postgres.conf
listen_addresses = '192.168.0.3'   # 設定listen IP

  • /usr/local/pgsql/data/pg_hba.conf
host    all             all             127.0.0.1/32              trust
host    all             all             192.168.0.0/16            trust
host    all             all             10.10.1.5/32              password


Log分析
推薦使用pgFouine - a PostgreSQL log analyzer,它可以分析出某段時間內,做了幾次query,處理時間最久的,次數最多的...可以看一下Sample reports長怎樣。


效能測試:
pgbench
使用 pgbench 进行数据库压力测试
pgbench -U postgres -i -s 50 postgres 
pgbench -U postgres -c 100 -t 100 -S postgres


Performance Tuning PostgreSQL