Friday, June 22, 2007 - 文章

KB-Transaction Error When Query Oracle Database Links

同事遇到一個狀況,使用OleDbCommand查詢ORACLE上的Database Link時,系統回報以下錯誤:
ORA-02041: client database did not begin a transaction

Goggle了一下,發現問問題的人挺多的,但回答很分歧,沒法一下子得到正解。反覆測試後,我得到的結論如後。

當使用Oracle Database Link時,因涉及兩台以上的Oracle Server,自動啟用Distributed Transaction可以被理解(SQL Server亦是如此)。但網路上的討論似乎都集中火力在避免啟用Distributed Transaction上,而不是研究怎麼順利啟用它。Anyway,我試出兩種成功的做法。第一種是用ORACLE提供的OLEDB,關鍵是要將Registry中的HKLM\SOFTWARE\ORACLE\OLEDB\DistribTX由1改為0,表示停用分散式交易(我懷疑這會導致所有的Oracle OLEDB操作都失去分散式交易的能力,值得留意)。程式碼如下:

   1:  static void testOraOle()
   2:  {
   3:      OleDbConnection cn =
   4:          new OleDbConnection(
   5:          "Provider=OraOLEDB.Oracle; Data Source=Ora1; " +
   6:          "User Id=blah; Password=blahblah;");
   7:      cn.Open();
   8:      OleDbCommand cmd = 
   9:          new OleDbCommand("select * from myTable@Ora2", cn);
  10:      OleDbDataReader dr = cmd.ExecuteReader();
  11:      while (dr.Read())
  12:          Console.WriteLine(dr[0].ToString());
  13:      dr.Close();
  14:      cn.Close();
  15:  }

使用ODP.NET時,關鍵則在Connection String中要加上Enlist=false停用分散式交易,如下:

   1:  static void testOraODP()
   2:  {
   3:      //程式碼要宣告using ODP = Oracle.DataAccess.Client;
   4:      ODP.OracleConnection cn = 
   5:          new ODP.OracleConnection(
   6:          "Data Source=Ora1; User Id=blah; Password=blahblah; " +
   7:          "Enlist=false;");
   8:      cn.Open();
   9:      ODP.OracleCommand cmd = 
  10:          new ODP.OracleCommand("select * from myTable@Ora2", cn);
  11:      ODP.OracleDataReader dr = cmd.ExecuteReader();
  12:      while (dr.Read())
  13:          Console.WriteLine(dr[0].ToString());
  14:      dr.Close();
  15:      cn.Close();
  16:  }

至於System.Data.OracleClient,在我的測試中,即使加上Enlist=false仍會傳回相同錯誤,是否註定無法支援或仍有其他的解法,暫時不得而知,若有人有成功案例再反應給我吧!

Posted 22 June 2007 02:12 PMJeffrey | 1 comment(s)
Filed under: ,
Microsoft SMTP Service Mini FAQ

Microsoft SMTP Service是從NT時代就有的實用服務,陽春歸陽春,拿來當作網站系統派送通知的服務綽綽有餘。這幾年下來,陸續有些處理SMTP Service的經驗,在此以FAQ的方式做個分享。

1.為什麼我的信寄不出去?
A: 寄信Client多半會要求輸入SMTP Server IP、Port Number等資料。有些人會抱怨明明就設好127.0.0.1的25 Port,使用Telent 127.0.0.1 25的方式也可以連線成功,但信就是寄不出去。
最常見的理由是SMTP Service的Mail Relay(郵件轉寄)功能被關閉了! 由於垃圾信發送者常常會在網路上尋找支援Relay功能的SMTP主機當作發送垃圾信的跳板。近年來,基於安全理由,各家SMTP Server的預設值都會停用Mail Relay功能,所以請記得到IIS管理員中將127.0.0.1加入允許Relay的IP清單。
有個非常實用的SMTP偵測技巧是利用Telnet檢視SMTP交談中的訊息,如下所示,就可以清楚看出問題出在Relay Denied。關於Telnet 25 Port的技巧可以參考MS的這篇KB,至於如何Config SMTP Service,則可以看另一篇KB

C:\>telnet 127.0.0.1 25

220 blah.com.tw Microsoft ESMTP MAIL Service, Version: 5.0.2195.6713 ready at
 Thu, 21 Jun 2007 22:14:42 +0800
helo darkthread
250 blah.com.tw Hello [10.220.1.91]
mail from: jeffrey@utopia.com
250 2.1.0 jeffrey@utopia.com....Sender OK
rcpt to: jeffrey@darkthread.net
550 5.7.1 Unable to relay for jeffrey@darkthread.net
quit
221 2.0.0 blah.com.tw Service closing transmission channel

Connection to host lost.

C:\>

 2.我沒開放Relay,為什麼某些程式的信還是寄得出去?
A.前面強調過SMTP Svc必須要開放Mail Relay限制才能寄Mail出去,但有人抗議,他的SMTP Svc Mail Relay一直以來都是關閉的,信件照樣寄得嗄嗄叫!
inetpub/wwwroot相信大家都耳熟能詳,但inetpub下還有個名不見經傳的mailroot目錄。mailroot下有幾個好玩的目錄: Badmail用來放SMTP Svc寄不出的退信、Drop是被丟棄的信、Mailbox則用來存放寄給本機使用者的信(MS SMTP Svc其實有收信功能的,只要Domain Name設對了,user@yourSmtpDomain.com的信就會被放到這裡),Queue、Route、SortTemp都是傳送過程中暫存信件用的。[2008-07-14更新: Will保哥提供了一些Windows 2003上觀察到的不同,請參見留言] 如果信件卡住沒送出去,則可以在Queue中看到大排長龍。最後的重頭戲來了,有個Pickup目錄,你只要把信組成.eml的格式寫進去,MS SMTP Svc就會幫你寄出去,效果與使用TCP 25連上127.0.0.1完全相同,但這種做法不受Relay的限制。(大概是SMTP將有權限在本機寫入檔案的Client視為合法使用者的緣故)
例如MS的CDONTS.DLL,不需要指定SMTP Svc IP & Port就可以寄信,關鍵也在於它是用Pickup目錄來交寄郵件。

3.要怎麼Trouble-Shooting SMTP Svc?
A.前面已經提示過一些技巧了,在此再做個整理:
1) 用Telnet 127.0.0.1 25的方法Debug
2) 檢查Badmail, Pickup, Queue等Mailroot下的目錄
3) SMTP Svc跟IIS一樣可以記Log,但預設是關閉的,打開後可以在windows\system32\logfiles裡找到類似IISLog的記錄檔

4.SMTP Svc使用上有沒有什麼限制?
A.先談談效能,在我的經驗中,網站整合SMTP Svc,對寄寄通知函、定期送報表等工作向來都勝任愉快。只有當年.COM泡沬化的前夕曾打算用它來發數萬封網路行銷電子報,一次硬塞數百封Mail會讓SMTP Svc不支倒地了... 不過,一般而言,專業電子報派發應該就近Colocation在ISP,更常見的作法是使用專門的軟體、平台派發,這種土法鍊鋼惡搞法對SMTP Svc而言本來就不太公平。
至於其他限制方面,由於SMTP Svc會查DNS,自行用25 Port連上對方的Mail Server交寄郵件,許多公司的防火牆根本不允許一般的PC連線Internet上的25 Port,要用得另外申請;另一方面,收信Mail Server也常會透過反查發信主機的DNS來過濾來路不明的SMTP Server,若SMTP Svc沒有設好DNS,也會吃閉門羮。對於這方面的困擾,我常用的一招是設定Smart Host! 設定Smart Host後,SMTP Svc就不必再抛頭露臉,所有的信都會轉交Smart Host主機,由它負責寄出。由於近來各公司都啟動了相關的垃圾信機制,因此透過公司統一的對外管道寄信問題較少。關於Smart Host的設定可以參考剛才提過的一篇KB

5.SMTP Svc有沒有什麼資安防護機制?
A.SMTP Svc可以限定接受連線的對象IP、允許Mail Relay的IP、加上SSL、TLS加密功能,還可要求使用者必須登入AD帳號後才可使用(跟IIS一樣可以選Basic、NT整合式認證等),透過這些設定,可以減少被當成垃圾信跳板的可能。另外,先前提到的Log功能則可以作為事後追查之用,也算是資安機制的一部分吧!

Posted 22 June 2007 08:10 AMJeffrey | 1 comment(s)
Filed under: ,

搜尋

Go

<June 2007>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication