星期日, 6月 30, 2013

最佳化Ajax的執行速度


  1. 最佳化 for 迴圈
  2. 把DOM節點附加至文件
  3. 減少點 (dot) 標記


Reference
Ajax in Action

MD5被破解了,要改用SHA

過去很常用MD5做訊息摘要,近來發現某些地方會用SHA做摘要
google了一下,發現MD5因hash不夠強而被破解了,能夠偽造相同的訊息摘要
大致問題如下
  1. MD5的hash值,google就會找到了,
    本來沒在意這點,不過有時會用在儲存密碼上
    這就容易被反推,記得幾年前也有朋友用google MD5去找密碼...
  2. 相同的訊息摘要
    MD5本來就不以安全為出發點,只是做摘要用,因此hash不夠強,會發生兩個不同的message,但產生相同的hash碼
  3. 利用MD5做檔案特徵碼也有相同的問題
    SHA的訊息摘要的長度更長,因此較不會發生碰撞,也更為安全
    不過相對MD5,運算也相對較慢,所以適合用在摘要小段訊息
    檔案還是用MD5比較快

PHP寫法
$data = "魚乾的筆記本";
$key = "fishjerk";

$sig = md5($data, true);  // = hash('md5', $data);
//Output 32個字元特徵碼: 9fc745260dedf115ec7b62fa811f0698

$sig = hash_hmac('sha256', $data, $key ); //跟hash('sha256')的差別是多了$salt改變特徵碼
//Output 64個字元特徵碼: 7b8ddbde1cc031945d23d82af786a83048e40efff7c1194ed9ea6c6f0fae39b2

$sig = hash_hmac('sha512', $data, $key );
//Output 128個字元特徵碼: 8cb44d44e52b443fa3095a06668dd6e31b8ce973f3b4f353d40ca35b47605dc41ff3ab003f375aee5ed1a14456e2b783d1f98543cc111822ea63d26d1427ea61


SHA有5種演算法,SHA-0 ~ SHA-5
目前 SHA-0 及 SHA-1 也都被破了
SHA-2 以上還沒出現有效的攻擊,SHA256 及 SHA512 即為 SHA-2

過去上密碼學時,都沒注意到原來SHA是Secure Hash Algorithm 縮寫
都說是Secure了,還在用MD5玩~ (羞)
難怪之前用 facebook 金流時,人家也用sha256

References

星期三, 6月 26, 2013

Select For Update

前陣子發生商品的庫存欄位發生負值~ 也就是超賣~
因此很有經驗「會向中對齊」的長官就說一定沒用select for update~

啥系 Select For Update
就是把某欄位select 出來做 update
//例如..
SELECT quantity FROM products WHERE id=1
...拉出來減掉購買數... 再更新回DB
Update products Set quantity = $quantity WHERE id =1 

看起來沒問題,但如果在select後,update前,這商品先其他人更新了,這quantity就會有問題了~
所以Oracle可以下
SELECT quantity FROM products WHERE id=1 FOR UPDATE
這樣會把此筆先lock,其他人就select此商品就待等待Update剛成


說這麼多~~ 但公司是用MS SQL....
只好再研究一下怎麼用...
  • MS SQL
    網上查到可加HOLDLOCK or UPDLOCK
    研究了一下,由於是用select for update,如果搭HOLDLOCK,可能發生互相等待而造成deadlock,因此應使用UPDLOCK,SQL Server會選擇由一完成update後釋放資源
    所以SQL應該如下,以避免 deadlock
    SELECT quantity FROM products WHERE id = 1 WITH (UPDLOCK)
    ...
    UPDATE FROM products SET quantity = $quantity WHERE id =1 
  • MySQL refer to [MySQL] 使用 SELECT ... FOR UPDATE 做交易寫入前的確認
    SET AUTOCOMMIT=0;
    BEGIN WORK;
    SELECT quantity FROM products WHERE id=3 FOR UPDATE;
    ===========================================
    此時 products 資料中 id=3 的資料被鎖住(註3),其它交易必須等待此次交易
    送交後才能執行 SELECT * FROM products WHERE id=3 FOR UPDATE (註2)
    如此可以確保 quantity 在別的交易讀到的數字是正確的。
    ===========================================
    UPDATE products SET quantity = '1' WHERE id=3 ;
    COMMIT WORK;
    ===========================================
    送交(Commit)寫入資料庫,products 解鎖。
    註1: BEGIN/COMMIT 為交易的起始及結束點,可使用二個以上的 MySQL Command 視窗來交互觀察鎖定的狀況。


其他問題
"select for update"會造成其他Query等待,如何才能讓其他Query不等待呢?
  • Oracle
    SELECT * quantity FROM products WHERE id=1 FOR UPDATE NOWAIT;               //不等,回報錯誤
    SELECT * quantity FROM products WHERE id=1 FOR UPDATE NOWAIT skip Locked;   //不等,給目前的值 也就是dirty read 
  • MS SQL
    SELECT * quantity FROM products WHERE id=1 WITH (NOWAIT);  //不等,回報錯誤
    SELECT * quantity FROM products WHERE id=1 WITH (NOLOCK);  //不等,給目前的值 也就是dirty read 
  • MySQL
    等有用到再補....

Reference