Aug 25

PHP 自 5.3.0 開始,引入 mysqlnd 這個 extension。
5.3.0 的 Full ChangeLog 中可以看到這行:

Added mysqlnd extension as replacement for libmysql for ext/mysql, mysqli and PDO_mysql. (Andrey, Johannes, Ulf)

依照個人的過往經驗,native driver 的效能都會比較好,而 mysqlnd 也不例外(有興趣的可以看看這篇文章)。

比較可惜的是,mysqlnd 在 Windows 平台的 PHP 是預設套件;在 *NIX 平台,使用前必須在編譯前就先做好設定(configure;參數可參考 PHP 官方的mysqlnd 安裝文件)。

剛才,很高興看到 FreeBSDPHP5 ports 加入了 option,讓我們可以輕鬆搞定。 8)

Technorati Tags: , , ,

(Visited 629 times)
Aug 13

剛剛在 WLM(原稱 MSN)收到這種訊息:

###### 說:
看看誰把妳從他的MSN聯繫名單中刪除了。

http://www.#######chat.info?mid=13868233133262797975

心血來潮上來貼這篇文章。

這種訊息應該不少人都收過,這種網站也應該有很多人看過。
我無法理解的是,當一個陌生的網站要你輸入你在其他網站或軟體的帳號密碼時,你怎麼能安心的輸入?
你能保證這個網站不會紀錄你輸入的密碼,用你的帳號密碼為非作歹?

這樣還不懂的話,我舉個生活化一點的例子:

陌生人:「我能幫你查你在XX證券開立的帳戶裡目前總值是多少哦!」
網站標題:「我能幫你查看看有誰把你從 MSN 聯繫名單中刪除了哦!」

你:好啊好啊!我想知道!怎麼查?
陌生人:只要給我你的帳戶的帳號跟密碼,我就可以幫你查。
網站內容:「請輸入你的帳號跟密碼,我就可以幫你查!」

假如真的有陌生人這麼跟你說,你會給他帳號跟密碼嗎?
醒醒吧! :evil:

如果你已經把帳號密碼送給某個(或是某些)網站的話,就... 快點變更密碼吧。
如果你收到朋友傳送類似的訊息,或是怪怪的網站給你的話,請回訊給對方,提醒對方變更密碼,甚至是檢查電腦是否中毒。

Technorati Tags: , , ,

(Visited 989 times)
Aug 08

發現 MongoDB 是好一陣子前的事,而我也在某台機器上把它裝起來。
之前玩的時候,發現 MongoDB 不須帳號與密碼就可以連接,而且也無法配置使用者權限,所以把它丟在旁邊。

前幾天,我在網路上看到網友詢問 MongoDB 有沒有辦法作 JOIN,得到的答案是否定的。
趁著今天在家閒閒沒事作,書也看完幾個段落,就透過 PHP 來試試這種 ODBMS 如何實作資料關聯。

MongoDB 與常見的資料庫(例如:MySQL)有些微的不同:

資料庫 資料表
MongoDB 稱之為 Database(DB) Collection
MySQL 稱之為 Database(DB) Table

先把這個觀念講清楚,底下的範例程式碼才不會看得霧煞煞。 8)

首先,先建立 DB 與 Collection:

// 連接 MongoDB
$m = new Mongo();

// 連接資料庫,名稱就是 test
$testDB = $m->selectDB( 'test' );

// 建立 Collection,名稱分別是 user 與 sex
$testDB->createCollection( 'user' );
$testDB->createCollection( 'sex' );
  • MongoDB 沒有 createDB 這種指令。只要選擇資料庫,建立 Collection 之後,系統就會自動產生 DB。
  • 指令列模式下,選擇資料庫的指令跟 MySQL 相同(USE DB_NAME)。

再來,存入性別資料:

// 連接 MongoDB
$m = new Mongo();

// 連接資料庫,名稱就是 test
$testDB = $m->selectDB( 'test' );

// 在 sex 這個 Collection 裡面放入資料,好讓程式分辨男性與女性
$testDB->sex->insert( array('sex_name' => 'Female') );
$testDB->sex->insert( array('sex_name' => 'Male') );

// 把 sex 這個 Collection 的資料倒出來看
$cursor = $testDB->sex->find();
$array = iterator_to_array($cursor);
var_dump($array);
  • 以往我們儲存在 Table 的 data row 會有個 id 值,方便我們建立關聯。MongoDB 這種資料庫則是在 Collection 裡面放物件,可以不需要 id 值。

開始存入使用者名稱,並紀錄他(她)們的性別:

// 連接 MongoDB
$m = new Mongo();

// 連接資料庫,名稱就是 test
$testDB = $m->selectDB( 'test' );

// 找出男性資料,並取得關聯值
$male = $testDB->sex->findOne( array('sex_name' => 'Male') );
$refMale = $testDB->sex->createDBRef( $male );

// 找出女性資料,並取得關聯值
$female = $testDB->sex->findOne( array('sex_name' => 'Female') );
$refFemale = $testDB->sex->createDBRef( $female );

// 存入使用者資料
$testDB->user->insert( array('name' => 'BoyName', 'sex' => $refMale) );
$testDB->user->insert( array('name' => 'GirlName', 'sex' => $refFemale) );

// 取出並顯示使用者資料
$cursor = $testDB->user->find();
$array = iterator_to_array($cursor);
foreach ( $array as $user ) {
        // 找出性別的關聯物件
        $sexRef = $testDB->user->getDBRef($user['sex']);
        echo "Name: {$user['name']}\tSex: {$sexRef['sex_name']}\n";
}

以上,簡單的試玩心得。 :oops:

Technorati Tags: , , , ,

(Visited 921 times)
Jul 14

昨晚在 PTT 的 PHP 板回了一篇文章,提到 PHP 的內建常數;現在來分享一下,順便作個紀錄,方便日後查詢。

PHP 有不少實用的內建常數,方便我們寫程式時直接呼叫。
有興趣研究的人,可以看看這個網頁,或是用 get_defined_constants() 把內建常數全部倒進陣列,再用 var_dump()print_r() 顯示。

下表列出一些我覺得常用的內建常數,範例值來自 64 位元版本的 FreeBSD ports 安裝之 PHP 5.3.2:

常數名稱 常數型態 範例值或說明 可用版本
PHP_VERSION string "5.3.2" 無限制
PHP_MAJOR_VERSION integer 5 5.2.7+
PHP_MINOR_VERSION integer 3 5.2.7+
PHP_RELEASE_VERSION integer 2 5.2.7+
PHP_EXTRA_VERSION string "" 5.2.7+
PHP_OS string "FreeBSD" 無限制
PHP_PREFIX string "/usr/local" 4.3.0+
PHP_BINDIR string "/usr/local/bin" 無限制
PHP_LIBDIR string "/usr/local/lib/php" 無限制
PHP_DATADIR string "${prefix}/share" 無限制
PHP_SYSCONFDIR string "/usr/local/etc" 無限制
PHP_LOCALSTATEDIR string "/usr/local/var" 無限制
PHP_CONFIG_FILE_PATH string "/usr/local/etc" 無限制
PHP_CONFIG_FILE_SCAN_DIR string "/usr/local/etc/php" 無限制
PHP_SHLIB_SUFFIX string "so" 4.3.0+
PHP_EOL string 此變數可用來判斷 "\n"、"\r"、"\r\n"(三個通吃,超好用)。 4.3.0+
PHP_MAXPATHLEN integer 1024 5.3.0+
PHP_INT_MAX integer 9223372036854775807 4.0.4+ 與 5.0.5+
DATE_COOKIE string "l, d-M-y H:i:s T"
輸出範例:
Wednesday, 14-Jul-10 20:25:07 CST
5.1.1+
DATE_ISO8601 string "Y-m-d\TH:i:sO"
輸出範例:
2010-07-14T20:26:18+0800
5.1.1+
DATE_RFC822 string "D, d M y H:i:s O"
輸出範例:
Wed, 14 Jul 10 20:27:39 +0800
5.1.1+
DATE_RFC850 string "l, d-M-y H:i:s T"
輸出範例:
Wednesday, 14-Jul-10 20:28:44 CST
5.1.1+
DATE_RFC1036 string "D, d M y H:i:s O"
輸出範例:
Wed, 14 Jul 10 20:29:40 +0800
5.1.1+
DATE_RFC1123
DATE_RSS
string "D, d M Y H:i:s T"
輸出範例:
Wed, 14 Jul 2010 20:31:51 CST
5.1.1+
DATE_RFC2822 string "D, d M Y H:i:s O"
輸出範例:
Wed, 14 Jul 2010 20:31:51 +0800
5.1.1+
DATE_RFC3339
DATE_ATOM
DATE_W3C
string "Y-m-d\TH:i:sP"
輸出範例:
2010-07-14T20:36:18+08:00
5.1.1+

Technorati Tags: ,

(Visited 1028 times)
Jun 18

WordPress 3.0 在十幾分鐘前 release 了,官方的文章 提供了這段影片作介紹:

2.9.2 升級可直接把下載下來的壓縮檔直接覆蓋原本的目錄,再透過瀏覽器執行升級程式( wp-admin/upgrade.php )。

因為 WordPress 3.0 的預設佈景主題換了,所以沒改過預設佈景主題的人記得開管理後台檢查一下。

WordPress 3.0 的壓縮檔裡面沒有這些檔案與目錄(注意: wp-content/themes/classic 與 wp-content/themes/default 列在其中),想讓目錄乾淨一點的可以清掉:

  • wp-admin/categories.php
  • wp-admin/edit-category-form.php
  • wp-admin/edit-page-form.php
  • wp-admin/edit-pages.php
  • wp-admin/images/browse-happy.gif
  • wp-admin/images/fav-top.png
  • wp-admin/images/screen-options-left.gif
  • wp-admin/images/wp-logo-vs.gif
  • wp-admin/images/wp-logo.gif
  • wp-admin/import
  • wp-admin/js/wp-gears.dev.js
  • wp-admin/js/wp-gears.js
  • wp-admin/options-misc.php
  • wp-admin/page-new.php
  • wp-admin/page.php
  • wp-admin/rtl.css
  • wp-admin/rtl.dev.css
  • wp-admin/update-links.php
  • wp-admin/wp-admin.css
  • wp-admin/wp-admin.dev.css
  • wp-content/themes/classic
  • wp-content/themes/default
  • wp-includes/js/codepress
  • wp-includes/js/jquery/interface.js
  • wp-includes/js/scriptaculous/prototype.js
  • wp-includes/js/tinymce/wp-tinymce.js

Technorati Tags: ,

(Visited 1561 times)
May 27

以前,我喜歡用 ADOdb 來連接資料庫;自從 PDO 被放進 PHP 5.1 後,它便成了我的新寵...

我在 PHP 5.1.6 環境上幫人家抓蟲時,看到以下兩段程式。

  1. $pdo = New PDO(......);
    
    $sql = "SELECT .....";
    $st = $pdo->prepare($sql);
    $st->execute();
    $rows = $st->fetchAll();
  2. $pdo = New PDO(......);
    
    $sql = "SELECT .....";
    $st = $pdo->query($sql);
    $rows = $st->fetchAll();

雖然以上兩段程式都可以取出 $rows ,但重複並交叉執行的話,就會出現問題。

  • 這段程式可以正確取出 $rows1 與 $rows2:
    $pdo = New PDO(......);
    
    $sql = "SELECT .....";
    $st = $pdo->query($sql);
    $rows1 = $st->fetchAll();
    
    $sql = "SELECT .....";
    $st = $pdo->prepare($sql);
    $st->execute();
    $rows2 = $st->fetchAll();
  • 這段程式只能正確取出 $rows1 ,$rows2 會是個空的陣列:
    $pdo = New PDO(......);
    
    $sql = "SELECT .....";
    $st = $pdo->prepare($sql);
    $st->execute();
    $rows1 = $st->fetchAll();
    
    $sql = "SELECT .....";
    $st = $pdo->query($sql);
    $rows2 = $st->fetchAll();

這問題有兩種解法:

Technorati Tags: , ,

(Visited 2525 times)
Apr 18

剛感到好奇,各在 C# 與 JAVA 寫測試程式。

  • C#:
    Object myObj1 = 1;
    Object myObj2 = myObj1;
    Object myObj3 = 1;
    
    Console.WriteLine("myObj2.Equals(myObj1) = " + myObj2.Equals(myObj1));
    Console.WriteLine("myObj3.Equals(myObj1) = " + myObj3.Equals(myObj1));
    
    Console.WriteLine("(myObj2 == myObj1) = " + (myObj2 == myObj1));
    Console.WriteLine("(myObj3 == myObj1) = " + (myObj3 == myObj1));

    結果:

    myObj2.Equals(myObj1) = True
    myObj3.Equals(myObj1) = True
    (myObj2 == myObj1) = True
    (myObj3 == myObj1) = False
  • JAVA:
    Object myObj1 = 1;
    Object myObj2 = myObj1;
    Object myObj3 = 1;
    
    System.out.println("myObj2.equals(myObj1) = " + myObj2.equals(myObj1));
    System.out.println("myObj3.equals(myObj1) = " + myObj3.equals(myObj1));
    
    System.out.println("(myObj2 == myObj1) = " + (myObj2 == myObj1));
    System.out.println("(myObj3 == myObj1) = " + (myObj3 == myObj1));

    結果:

    myObj2.equals(myObj1) = true
    myObj3.equals(myObj1) = true
    (myObj2 == myObj1) = true
    (myObj3 == myObj1) = true

Technorati Tags: ,

(Visited 3254 times)
Apr 16

FreeBSD ports tree 的 lang/php5 升級到 5.3.2, www/eaccelerator 也升級到 0.9.6。
但是... 目前,FreeBSD ports tree 的 www/pecl-APC 依然是 3.0.19,無法在 PHP 5.3 運作;為了讓它正常運作,jnlin送過 PR(我沒有先查詢,也送了一個 :oops: )。

其實 eAccelerator 0.9.6 在 2010 年 2 月初就已經釋出了,可是,從 changelog 看來,很多不錯的功能被砍掉(反璞歸真?):

Changes in this version:

* Support for PHP 5.3.
* The encoder is removed
* The user cache functions are removed
* The session handler is removed
* The minimal PHP version supported is now 5.1
* Some internal refactoring to clean up the code
* Fixed some bugs (and probably added some)

這麼看來,2008 年的這篇文章的參考價值就低了些...
為了滿足我自己的好奇心,就把 APC 3.1.3p1 裝起來測試看看。

系統/硬體:

  • CPU: Intel(R) Pentium(R) 4 CPU 3.00GHz
  • Memory: 6G(DDR2 800 MHz, Dual-Channel)
  • FreeBSD 8.0-RELEASE-p2 amd64
  • Apache HTTPD 2.2.14
  • PHP 5.3.2

設定:

  • eAccelerator 0.9.6:
    eaccelerator.shm_size="128"
    eaccelerator.cache_dir="/tmp/eaccelerator"
    eaccelerator.enable="1"
    eaccelerator.optimizer="1"
    eaccelerator.debug="0"
    eaccelerator.log_file="/var/log/eaccelerator.log"
    eaccelerator.name_space = ""
    eaccelerator.check_mtime="1"
    eaccelerator.filter=""
    eaccelerator.shm_max="0"
    eaccelerator.shm_ttl="0"
    eaccelerator.shm_prune_period="0"
    eaccelerator.shm_only="0"
    eaccelerator.compress="1"
    eaccelerator.compress_level="9"
    eaccelerator.keys="shm_and_disk"
  • APC 3.1.3p1:
    apc.enabled=1
    apc.shm_segments=1
    apc.shm_size=128
    apc.ttl=7200
    apc.user_ttl=7200
    apc.num_files_hint=1024
    apc.mmap_file_mask=/tmp/apc.cache
    apc.enable_cli=1

測試結果(ab -c5 -n500):

Pure PHP eAccelerator APC
WordPress 2.9.2 3.00 req./sec.
332.834 ms/req.
7.61 req./sec.
131.487 ms/req.
8.87 req./sec.
112.750 ms/req.
MediaWiki 1.15.3 1.81 req./sec.
552.822 ms/req.
2.75 req./sec.
363.124 ms/req.
5.93 req./sec.
168.580 ms/req.
Gallery 2.3.1 3.51 req./sec.
284.979 ms/req.
7.91 req./sec.
126.421 ms/req.
7.38 req./sec.
135.506 ms/req.

依照結果看來,APC 3.1.3p1 的確略勝 eAccelerator 0.9.6。 8)
可惜的是.. Xcache 目前的最新版本(1.3.0)沒辦法在 PHP 5.3 跑...

Technorati Tags: , , , , ,

(Visited 3128 times)
Apr 01

最近在 MySQL 處理包含 weekday 型態的資料,發覺... 在 MySQL 處理 weekday 真的是「輕鬆寫意」... 8)

根據 DAYOFWEEK()WEEKDAY() 的定義,回傳的資料都是數值。
而大多數 DBMS 都有取得 weekday 的方法。

我會說「 MySQL 處理 weekday 輕鬆寫意」的原因是... ENUM
我把將欄位型態定義為 enum('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
今天(2010/04/01,愚人節)是星期四,若是要抓出該欄位為 Thu 的資料,只要用這種語法:

SELECT ... WHERE `col`= DAYOFWEEK( NOW() )

用這類方法要注意的是,DAYOFWEEK()WEEKDAY() 對於每個 weekday,回傳的數值都不一樣。

Technorati Tags: , , ,

(Visited 3408 times)
Mar 08

我利用前兩天的空閒時間寫了個 PHP 的小程式,運用 PHP 的 PDO 元件,對 MySQL 進行小測試。

Server 作業系統與硬體:

  • 作業系統:FreeBSD 8.0-RELEASE
  • CPU:Intel(R) Pentium(R) 4 CPU 3.00GHz (3042.62-MHz 686-class CPU),Hyper-Threading 開啟
  • RAM:2G DDR2 800
  • 放資料庫的 HDD:WDC WD800JB-00JJA0,UDMA 100

MySQL 5.1.44 的設定(/etc/my.cnf):

# defult setting (maybe changed)
key_buffer_size = 128M
max_allowed_packet = 4M
table_open_cache = 4096
sort_buffer_size = 1M
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M

# added for tunning by Joe Horn
skip-name-resolve
connect_timeout = 60
join_buffer_size = 1M
max_connect_errors = 10000
max_connections = 100
max_heap_table_size = 1G
query_cache_size = 16M
slave_net_timeout = 30
sync_binlog=1
thread_cache_size = 512
thread_concurrency = 8
tmp_table_size = 1G
table_definition_cache = 512
# choose one ( depend on query amount )
#concurrent_insert=2
low_priority_updates=1

這台機器跑 Super Smack 的結果:

# super-smack -d mysql update-select.smack 80 1000
Query Barrel Report for client smacker
connect: max=14ms  min=1ms avg= 4ms from 80 clients
Query_type      num_queries  max_time  min_time  q_per_s
select_index    80000        101       6         717.91
update_index    80000        108       1         717.91

我用測試程式產生了一百萬筆資料的 MyISAM table,各種測試各循環 1000 次,產生如下的測試結果(後面的數字單位是秒):

SELECT BY PK_COL WITH_QUERY_CACHE:              0.058
SELECT BY PK_COL WITHOUT_QUERY_CACHE:           0.062
SELECT BY PK_COL LIMIT WITH_QUERY_CACHE:        0.058
SELECT BY PK_COL LIMIT WITHOUT_QUERY_CACHE:     0.062
SELECT BY UNIQUE_COL WITH_QUERY_CACHE:          0.058
SELECT BY UNIQUE_COL WITHOUT_QUERY_CACHE:       0.062
SELECT BY UNIQUE_COL LIMIT WITH_QUERY_CACHE:    0.058
SELECT BY UNIQUE_COL LIMIT WITHOUT_QUERY_CACHE: 0.062
SELECT BY INDEX_COL WITH_QUERY_CACHE:           0.058
SELECT BY INDEX_COL WITHOUT_QUERY_CACHE:        0.061
SELECT BY INDEX_COL LIMIT WITH_QUERY_CACHE:     0.058
SELECT BY INDEX_COL LIMIT WITHOUT_QUERY_CACHE:  0.063
SELECT BY COL WITH_QUERY_CACHE:                 0.786
SELECT BY COL WITHOUT_QUERY_CACHE:              0.063
SELECT BY COL LIMIT WITH_QUERY_CACHE:           0.059
SELECT BY COL LIMIT WITHOUT_QUERY_CACHE:        0.062
UPDATE BY PK_COL WITH_QUERY_CACHE:              1.139
UPDATE BY PK_COL WITHOUT_QUERY_CACHE:           1.199
UPDATE BY PK_COL LIMIT WITH_QUERY_CACHE:        0.125
UPDATE BY PK_COL LIMIT WITHOUT_QUERY_CACHE:     0.142
UPDATE BY UNIQUE_COL WITH_QUERY_CACHE:          2.734
UPDATE BY UNIQUE_COL WITHOUT_QUERY_CACHE:       1.203
UPDATE BY UNIQUE_COL LIMIT WITH_QUERY_CACHE:    0.147
UPDATE BY UNIQUE_COL LIMIT WITHOUT_QUERY_CACHE: 0.163
UPDATE BY INDEX_COL WITH_QUERY_CACHE:           1.183
UPDATE BY INDEX_COL WITHOUT_QUERY_CACHE:        1.063
UPDATE BY INDEX_COL LIMIT WITH_QUERY_CACHE:     0.138
UPDATE BY INDEX_COL LIMIT WITHOUT_QUERY_CACHE:  0.154
UPDATE BY COL WITH_QUERY_CACHE:                 4704.859
UPDATE BY COL WITHOUT_QUERY_CACHE:              4641.191
UPDATE BY COL LIMIT WITH_QUERY_CACHE:           0.156
UPDATE BY COL LIMIT WITHOUT_QUERY_CACHE:        0.167

根據測試結果,大概可以看到出以下幾個要點:

  1. 根據第 21 行與 22 行的差異看來,MySQL Query cache 還是有點用處,不過效用不大。
  2. 根據第 13 行與第 29 行的結果看來,有沒有設定 Primary Key、UNIQUE、INDEX 的影響不小。
  3. 根據 UPDATE 語法的測試結果看來,有沒有 LIMIT 頗重要。

Technorati Tags: , , , , , , , , ,

(Visited 5151 times)