ปัญหาการเชื่อมต่อฐานข้อมูล Oracle ไม่ได้ เนื่องจาก Listener

สำหรับผู้ดูแลระบบที่เคยทำงานดูแลฐานข้อมูล Oracle คงเคยเจอกับปัญหาการเชื่อมต่อไปยังฐานข้อมูลไม่ได้ ซึ่งเมื่อไล่เรียงหาสาเหตุแล้ว ก็มีมากมายหลายสาเหตุด้วยกัน เช่น ปัญหาที่ตัวฐานข้อมูลเอง หรือ ปัญหาทางด้านระบบเครือข่าย ฯลฯ ซึ่งในบทความนี้จะเล่าถึงประสบการณ์ที่ได้พบเจอปัญหานี้เช่นกัน โดยสาเหตุนั้นเกี่ยวกับตัว Listener เหตุการณ์ที่เกิดขึ้นช่วงที่พบปัญหา ได้รับแจ้งจากผู้ใช้ว่าไม่สามารถเข้าใช้งานระบบได้  ซึ่งเมื่อได้รับแจ้งจึงทำการตรวจสอบและพบว่าปัญหาเกิดจากการที่ระบบไม่สามารถเชื่อมต่อไปยังฐานข้อมูลที่พัฒนาด้วย Oracle ได้ โดยที่ระบบเครือข่ายยังใช้งานได้ปกติ ดังนั้นสิ่งที่ทำต่อมาคือการตรวจสอบเฉพาะฐานข้อมูลว่าเกิดปัญหาอะไรขึ้น โดยสิ่งที่ทำคือ ทดลองเชื่อมต่อผ่าน SQL Developer ซึ่งเป็นเครื่องมือหนึ่งที่ใช้สำหรับบริหารจัดการฐานข้อมูล Oracle ผลลัพธ์คือ ไม่สามารถเชื่อมต่อได้ โดยมีข้อความแจ้งเตือนว่า socket timeout ทดลองเชื่อมต่อผ่าน Enterprise Manager ซึ่งเป็นเครื่องมือสำหรับบริหารจัดการฐานข้อมูลอีกตัวซึ่งได้ติดตั้งมาพร้อมกับตอนที่สร้างฐานข้อมูล  ซึ่งก็ไม่สามารถเชื่อมต่อได้เช่นกัน และได้ลองสั่ง Startup DB ฐานข้อมูล จากเครื่องมือตัวนี้ อาการผิดปกติก็ยังคงเหมือนเดิม ทดลองเชื่อมต่อผ่าน ผ่าน SQL Plus ซึ่งใช้งานผ่าน command prompt  ปราฏว่าสามารถเชื่อมต่อได้ ใช้คำสั่ง expdp เพื่อ dump ข้อมูลมาสำรองไว้ก่อน  สามารถทำได้เช่นกัน แสดงว่าตัวฐานข้อมูลยังสามารถเข้าถึงได้อยู่ จึงพุ่งประเด็นไปที่ Listener เพราะเป็นตัวกลางที่จัดการให้ระบบหรือเครื่องมือภายนอกสามารถเชื่อมต่อมายังฐานข้อมูลได้ ทดลอง config Listener ใหม่ ด้วยเครื่องมือ Net Configuration Assistant พบว่าใช้เวลาตั้งค่านานมาก แต่ก็สามารถ config ได้ ลอง restart Listener และ Windows แล้ว อาการยังเหมือนเดิม ใช้คำสั่งบน command prompt ที่เกี่ยวกับ Listener ได้แก่ lsnrctl และ tnsping เพื่อตรวจสอบ Listener และ TNS พบว่าใช้เวลานานมาก จึงสันนิษฐานว่า อาจจะเป็นปัญหาที่ Listener แน่นอน เพราะยังเข้าถึงฐานข้อมูลผ่านช่องทางบางช่องทางได้ การแก้ไขปัญหา เมื่อได้ข้อมูลจากการตรวจสอบแล้ว ว่ามีปัญหาจาก Listener จึงได้ค้นข้อมูลใน internet เกี่ยวกับการเชื่อมต่อ Listener ที่ใช้เวลานาน พบว่ามีผู้แนะนำให้ตรวจสอบที่ไฟล์ listener.log ใน \app\Administrator\diag\tnslsnr\Win-User\listener\trace (ตัวอย่างนี้จะเป็น path ที่เป็น oracle 11) ***หมายเหตุ โฟลเดอร์ Win-User เป็นโฟลเดอร์ที่ต้ังตามชื่อ user ใน Windows ถ้าขนาดไฟล์ถึง 4 GB จะมีปัญหาได้ ให้ทำการหยุด service ของ Listener แล้ว rename ชื่อไฟล์ listener.log  ใหม่ เมื่อ start listener แล้ว ไฟล์ listener.log ก็จะถูกสร้างมาใหม่ เมื่อได้ทำการตรวจสอบพบว่าไฟล์มีขนาด 4 GB จริง และได้ทำการแก้ไขตามวิธีที่มีการแนะนำ พบว่าสามารถเชื่อมต่อกับฐานข้อมูล Oracle ได้เป็นปกติ สำหรับกรณีศึกษาที่มีผู้นำเสนอไว้สามารถเข้าดูได้ผ่าน URL https://vjdba.wordpress.com/2013/09/24/93/

Read More »

Oracle / PLSQL: LISTAGG Function

LISTAGG เป็นฟังก์ชันการรวมสตริงของ Oracle ที่นำค่าข้อมูลในคอลัมภ์ที่ระบุมาเรียงต่อกัน และดำเนินการจัดเรียงลำดับของข้อมูลที่นำมาต่อกันตามคอลัมภ์ใน order_by_clause ซึ่งฟังก์ชัน LISTAGG สามารถแสดงผลได้หลายรูปแบบดังนี้ Single-set aggregate function : LISTAGG เป็นฟังก์ชันที่ดำเนินการกับข้อมูลแล้วคืนค่ากลับมาเพียงเร็คคอร์ดเดียว Group-set aggregate function : LISTAGG เป็นฟังก์ชันที่ดำเนินการกับข้อมูลและคืนค่ากลับมาหลายเร็คคอร์ดตามกลุ่มที่กำหนดในเงื่อนไข GROUP BY  Analytic function : LISTAGG เป็นฟังก์ชันที่ดำเนินการจัดแยกผลการค้นหาออกเป็นกลุ่มตามเงื่อนไขที่กำหนดใน query_partition_clause Syntax LISTAGG (measure_column [, ‘delimiter’]) WITHIN GROUP (order_by_clause) [OVER (query_partition_clause)] โดยที่  measure_column คือ คอลัมภ์ที่ต้องการนำค่าข้อมูลมาเรียงต่อกัน โดยจะดำเนินเฉพาะค่าที่ไม่เป็น null เท่านั้น delimiter คือ ตัวเลือกที่ให้สามารถระบุตัวคั่นระหว่างค่าข้อมูลที่จะนำมาเรียงต่อกัน order_by_clause คือ ค่าที่นำมาเรียงต่อกันจะเรียงตามค่าในคอลัมภ์ที่กำหนดใน order_by_clause   ตัวอย่างการใช้งาน  สมมติเรามีข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่ซึ่งประกอบด้วย 6 ฟิลด์ข้อมูลแสดงดังตัวอย่างด้านล่าง ข้อมูล: ตาราง TEST_NEW_STUDENT เป็นตัวอย่างข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่จำนวน 16 รายการ Single-set aggregate function ตัวอย่างในส่วนนี้จะแสดงชื่อ-นามสกุลนักศึกษาทุกคนที่อยู่ในคณะ ’06’ โดยจัดเรียงลำดับข้อมูลตามชื่อนักศึกษา(stud_name_thai) SELECT LISTAGG (stud_name_thai || ‘ ‘ || stud_sname_thai, ‘,’) WITHIN GROUP (ORDER BY stud_name_thai) “NAME LIST” FROM test_new_student WHERE fac_id = ’06’; ผลลัพธ์ที่ได้ : จะคืนค่ากลับมาเพียงเร็คคอร์ดเดียวตามเงือนไขที่ระบุ Group-set aggregate function  ตัวอย่างในส่วนนี้จะแสดงชื่อ-นามสกุลนักศึกษาทุกคนแยกตามคณะที่สังกัด โดยจัดเรียงลำดับข้อมูลตามชื่อนักศึกษา(stud_name_thai) SELECT fac_id,LISTAGG (stud_name_thai || ‘ ‘ || stud_sname_thai, ‘,’) WITHIN GROUP (ORDER BY stud_name_thai) “NAME LIST” FROM test_new_student GROUP BY fac_id ORDER BY fac_id; ผลลัพธ์ที่ได้ : จะคืนค่ากลับมาหลายเร็คคอร์ดตามเงื่อนไข GROUP BY Analytic function ตัวอย่างในส่วนนี้จะแสดงข้อมูลเฉพาะคนที่ได้คะแนนมากกว่า 60 และจัดแยกผลการค้นหาตามคณะที่สังกัด SELECT fac_id,stud_name_thai||’ ‘||stud_sname_thai student_name,eng_score, LISTAGG (stud_name_thai||’ ‘||stud_sname_thai, ‘,’) WITHIN GROUP (ORDER BY eng_score, stud_name_thai) OVER (PARTITION BY fac_id) AS “NAME_LIST” FROM test_new_student WHERE eng_score > 60 ORDER BY fac_id, eng_score ผลลัพธ์ที่ได้ : ดำเนินการจัดแยกผลการค้นหาออกเป็นกลุ่มตามเงื่อนไขที่กำหนดใน PARTITION BY 

Read More »

Oracle : ROLLUP Extension to GROUP BY

การจัดกลุ่มข้อมูลด้วย GROUP BY เมื่อต้องการจัดกลุ่มข้อมูล เราสามารถใช้ประโยค GROUP BY เพื่อทำการแบ่งออกเป็นรายการย่อย ๆ การคิวรีที่รวมประโยค GROUP BY จะเรียกว่าการคิวรีแบบกลุ่ม เพราะว่ามันจะรวมกลุ่มข้อมูลจากคำสั่ง SELECT แล้วสร้างเป็นเร็คคอร์ดสรุปเพียงเร็คคอร์ดเดียวให้กับแต่ละกลุ่ม  ส่วนขยาย ROLLUP  ในการคิวรีข้อมูลเราสามารถค้นหาแถวข้อมูลผลรวมของแต่ละกลุ่ม รวมถึงสรุปผลรวมที่มาจากผลลัพธ์ทั้งหมดในตอนท้ายของการคิวรีอีกทีได้ โดยใช้ส่วนขยายที่เรียกว่า ROLLUP ซึ่งมีรูปแบบการใช้งานดังนี้ ROLLUP Syntax SELECT…GROUP BY ROLLUP(grouping_column_reference_list) ตัวอย่างการใช้งาน สมมติเรามีข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่ซึ่งประกอบด้วย 6 ฟิลด์ข้อมูลแสดงดังตัวอย่างด้านล่าง ข้อมูล: ตาราง TEST_NEW_STUDENT เป็นตัวอย่างข้อมูลคะแนนภาษาอังกฤษของนักศึกษาใหม่จำนวน 16 รายการ โจทย์ เราต้องการนับจำนวนนักศึกษาใหม่แยกตามคณะที่นักศึกษาสังกัด และรหัส สน.ที่สอบได้ เราสามารถใช้ประโยค GROUP BY เพื่อแก้ปัญหาข้อนี้ ดังตัวอย่างคิวรีต่อไปนี้ SELECT fac_id, sn_code, COUNT (*) NUM_STUDENT FROM test_new_student GROUP BY fac_id, sn_code ORDER BY fac_id, sn_code; ผลลัพธ์ที่ได้ : แสดงจำนวนนักศึกษาแยกตามคณะที่สังกัด และรหัส สน.ที่สอบได้ แสดงเรียงตามรหัสคณะ และรหัส สน.ที่สอบได้ โจทย์ หากเราต้องการนับจำนวนนักศึกษาใหม่แยกตามคณะที่นักศึกษาสังกัด และรหัส สน.ที่สอบได้ พร้อมทั้งแสดงผลรวมของนักศึกษาแต่ละคณะ และหาผลรวมของนักศึกษาทั้งหมดด้วย เราสามารถใช้ส่วนขยายที่เรียกว่า ROLLUP เพื่อแก้ปัญหาข้อนี้ ดังตัวอย่างคิวรีต่อไปนี้ SELECT fac_id, sn_code, COUNT (*) NUM_STUDENT FROM test_new_student GROUP BY ROLLUP (fac_id, sn_code) ORDER BY fac_id, sn_code; ผลลัพธ์ที่ได้ : แสดงจำนวนนักศึกษาแยกตามคณะที่สังกัด และรหัส สน.ที่สอบได้ แสดงเรียงตามรหัสคณะ และผลรวมของนักศึกษาแต่ละคณะ และผลรวมนักศึกษาทั้งหมด ลองใช้งานกันดูนะคะ  สำหรับส่วนขยาย ROLLUP เพื่อหาสรุปผลรวมที่มาจากผลลัพธ์ทั้งหมดในตอนท้ายของการคิวรี

Read More »

Uploading Files into Database with ASP.NET MVC

การ    upload  file มีหลายรูปแบบ ไม่ว่าจะเป็นการ upload file  แบบ copy ไว้บน server หรือจะเป็นการบันทึกลงในฐานข้อมูลเลยโดยตรง วันนี้จะขอนำเสนอในส่วนของการ upload   file  และบันทึกลงฐานข้อมูล     โดยใช้ ASP.NET MVC  ดังนี้   กำหนดไฟล์ที่ต้องการ upload ให้มีรูปแบบดังนี้       public class UploadModel { [Required] public HttpPostedFileBase File { get; set; } }   ในส่วนของ    View   <form id=”uploader” enctype=”multipart/form-data” method=”POST”> <a type=”submit” href=”#” onclick=”uploadConfirm();” class=”btn btn-info”><span class=”glyphicon glyphicon-save”></span>&nbsp;Upload</a> </form> ในส่วนของ java script (สำหรับเรียก Controller)   function uploadConfirm() { $.ajax({ type: ‘POST’, contentType: ‘application/json; charset=utf-8’, url: ‘@Url.Action(“CheckDataBeforeUpload”, “NoteUpload”)’, data: “{ ‘periodID’:’” + $(‘#selectedlistPeriods’).val() + “‘ ,’financeID’:’” + $(‘#selectedlistFinance’).val() + “‘ }”, success: function (resultSave) {   }, error: function (data) { alert(data); } }); }   ในส่วนของ Controller public async Task<ActionResult> UploadFile(UploadModel model, FormCollection form) {   string fileName = Path.GetFileName(model.File.FileName); //แสดงชื่อไฟล์ string strFileName = Path.GetFileNameWithoutExtension(fileName); //แสดงชื่อไฟล์ string contentType = model.File.ContentType;  //แสดงนามสกุลไฟล์   string FileExtension = fileName.Substring(fileName.LastIndexOf(‘.’) + 1).ToLower(); using (Stream fs = model.File.InputStream) // { using (BinaryReader br = new BinaryReader(fs)) { byte[] bytes = br.ReadBytes((Int32)fs.Length);   //TO DO:  Code ในส่วนที่ต้องการ insert ข้อมูลลง Database } }   return RedirectToAction(“Index”); }   จากตัวอย่างข้างต้น จะเป็นการ upload file ลงฐานข้อมูลโดยตรงในส่วนของรูปแบบการพัฒนาแบบ MVC ผู้เขียนหวังว่าอาจจะเป็นอีกทางเลือกหนึ่งของผู้พัฒนา ในการนำไปพัฒนาโปรแกรมต่อไปนะคะ ^_^ แหล่งอ้างอิง https://stackoverflow.com/questions/15106190/uploading-files-into-database-with-asp-net-mvc https://stackoverflow.com/questions/21677038/mvc-upload-file-with-model-second-parameter-posted-file-is-null/21677156

Read More »

Configuration of TCP/IP with SSL and TLS for Database Connections

สิ่งที่ต้องเตรียม Oracle Database Server ในตัวอย่างนี้ใช้ Oracle database บน Oracle Enterprise Linux 7 Oracle Database Client  ในตัวอย่างใช้ Windows Server 2008 R2 เริ่ม ฝั่ง Server เข้าระบบด้วยบัญชีผู้ใช้ oracle หรือบัญชีที่เป็นเจ้าของ Oracle Database เปิด terminal สร้าง Oracle Wallet ด้วยคำสั่ง mkdir -p /u01/app/oracle/wallet ต่อด้วย orapki wallet create -wallet “/u01/app/oracle/wallet” -pwd WalletPasswd123 -auto_login_local โดย -pwd WalletPasswd123 ตัว WalletPasswd123 คือรหัสผ่านที่ใช้ป้องกันการเข้าถึงข้อมูลต่างๆ ใน wallet กฎการตั้งมีอยู่คือ ยาวอย่างน้อย 8 ตัวอักษร ไม่จำกัดความยาว จำเป็นต้องตั้งให้ตัวเลขผสมตัวอักษร สร้าง Certificate และใส่เข้าไปใน wallet ด้วยคำสั่ง orapki wallet add -wallet “/u01/app/oracle/wallet” -pwd WalletPasswd123 \ -dn “CN=`hostname`” -keysize 1024 -self_signed -validity 3650 ตรวจสอบด้วยคำสั่ง orapki wallet display -wallet “/u01/app/oracle/wallet” -pwd WalletPasswd123 ได้ผลลัพธ์ประมาณ Oracle PKI Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Requested Certificates: User Certificates: Subject: CN=reis.psu.ac.th Trusted Certificates: Subject: CN=reis.psu.ac.th Export Certificate เพื่อนำไปใช้กับเครื่อง Oracle Client ด้วยคำสั่ง orapki wallet export -wallet “/u01/app/oracle/wallet” -pwd WalletPasswd123 \ -dn “CN=`hostname`” -cert /tmp/server-certificate.crt ตรวจสอบแฟ้มที่ export ไปด้วยคำสั่ง cat /tmp/server-certificate.crt ได้ผลลัพธ์ประมาณว่า —–BEGIN CERTIFICATE—– MIIBoTCCAQoCAQAwDQYJKoZIhvcNAQEEBQAwGTEXMBUGA1UEAxMOcmVpcy5wc3UuYWMudGgwHhcN MTgwMTA5MDcyNTA2WhcNMjgwMTA3MDcyNTA2WjAZMRcwFQYDVQQDEw5yZWlzLnBzdS5hYy50aDCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAj4x2/NviDaTlXuEJt0kZARY5fHiT2SiVX+a18hai I0stoUhKKefjOCgB85iuqjIk0rvcGXI0KXkbenTy2t40A+qGxB04mBhCLKaKeIe67BZKR6Zyw1dd oaesoaWChC01b+IW1X5WWtC53UxpIZQ4Zktj41sLGUnarIr9+9HFwncCAwEAATANBgkqhkiG9w0B AQQFAAOBgQAqSCF2Y8uyM4rSQHUC8MKEl3Ia3NJKnigMOUzDc2fP7grSaoeuQ4NvIntTD+s+IT5Y EpLVND4kSHFTwGRq0Py/ig8ybXZCXfHtvNZh7ZGziL/sYt5/8xYi/tOBKwVanBTUaseKIMovtmd7 UyoOKrX8YBoFsB3UPRLudmFsksXRXw== —–END CERTIFICATE—– ฝั่ง Client เข้าระบบด้วยบัญชีผู้ใช้ administrator เปิด cmd แล้วสร้าง wallet ด้วยคำสั่ง mkdir c:\app\oracle\wallet สร้าง Certificate ด้วยคำสั่ง orapki wallet add -wallet “c:\app\oracle\wallet” -pwd WalletPasswd123 -dn “CN=%computername%” -keysize 1024 -self_signed -validity 3650 โดย WalletPasswd123 คือพาสเวิร์ดที่ใช้ล็อค wallet ไม่จำเป็นต้องเหมือนกับของ Server ตรวจสอบด้วยคำสั่ง orapki wallet display -wallet “c:\app\oracle\wallet” -pwd WalletPasswd123 ได้ผลลัพธ์ประมาณว่า Oracle PKI Tool : Version

Read More »