SiamWebCity.com รับสร้างเว็บไซต์ครบวงจร
เลือกภาษา ภาษาอังกฤษ   
หน้าแรก
web
โปรโมทเว็บ
web
รับทำเว็บไซต์
web
สอนทำเว็บ
web
Domain 299บ.
web
ติดต่อเรา
web
 
รับทำเว็บไซต์ครบวงจร รับพัฒนาแอพพลิเคชั่น สำหรับ Facebook iPad iPhone Android รับอบรมการสร้างเว็บไซต์ โปรโมทเว็บไซต์ ดูแลเว็บไซต์ แก้ไขเว็บไซต์ : เริ่มต้นติดต่อที่เรา ที่เหลือเราเป็นผู้จัดการเพื่อท่าน : เราเป็นมากกว่าเครื่องมือที่ช่วยฝ่าวิกฤตเศรษฐกิจ
รายการ
เกี่ยวกับเรา
ทำไมต้องเลือกเรา
ผลงานที่ผ่านมา
เตรียมตัวก่อนทำเว็บ
รับดูแลเว็บไซต์
แอพ Facebook iPhone
โปรแกรมmlm สำเร็จรูป
เช่าโฮสติง
บริการหลังการขาย
เงื่อนไขการรับบริการ
ร่วมงานกับเรา
คำถามที่พบบ่อย
ติดต่อเรา

ฟรีบทความ
คู่มือการใช้งาน  คู่มือการใช้งาน
VDO สอน Dreamweaver  VDO สอน Dreamweaver
Bitcoin บิทคอยน์  Bitcoin บิทคอยน์
PHP MySQL  VDO  เบื้องต้น  PHP MySQL VDO เบื้องต้น
PHP MySQL  เกร็ดความรู้  PHP MySQL เกร็ดความรู้
jQuery  jQuery
HTML5  HTML5
ASP net   MS SQL  ASP net MS SQL
facebook app  facebook app
JSP  JSP
Oracle  Oracle
CSS  CSS
Google  Google
iphone ipad iphone itune ios  iphone ipad iphone itune ios
SEO  SEO
SQL Server  SQL Server
AJAX  AJAX
รดน้ำอัตโนมัติ  สปริงเกอร์  รดน้ำอัตโนมัติ สปริงเกอร์
คอมพิวเตอร์   อินเตอร์เน็ต  คอมพิวเตอร์ อินเตอร์เน็ต
JavaScripts  JavaScripts
cloud computing  cloud computing
xhtml  xhtml
Photoshop  Photoshop
RSS Feed  RSS Feed
wordpress  wordpress
Computer  Computer
MLM ขายตรง ขยายสายงาน  MLM ขายตรง ขยายสายงาน
NUTT's blog  NUTT's blog
ทีวีดิจิตอล DVB T2  ทีวีดิจิตอล DVB T2
Bootstrap CSS  Bootstrap CSS

รับสอน PHP, MySQL, HTML, CSS, Javascripts, FTP, Dreamweaver,PHPMyAdmin, Appserv, WMSEVER, php-Nuke , Joomla, SMF, Oscommerce, Phpbb, Paypal, Adwordsมาเรียนการสร้างเว็บกัน
บริการสอน แนะนำ Adwords , PHP, MySQL, HTML, FTP, SMF, PHPMyAdmin, Dreamweaver, Oscommerce, Photoshop, Flash...

test speed
Display Pagerank
ดูสถิติเว็บไซต์

รับติดตั้ง PHP ให้ติดต่อ ORACLE ได้ ถึงบ้านคุณ เพียง 2,000 บาท เท่านั้น
ติดต่อ MSN, Google Talk ,E-mail: [email protected]

ความลึกลับของ Trigger ตอนที่ 2



Oracle > ความลึกลับของ Trigger ตอนที่ 2


ปัญหาการนำทริกเกอร์ไปใช้คือผู้พัฒนามักจะไม่รู้ผลข้างเคียงในแง่ของการ ควบคุมการใช้งานพร้อมกัน (Concurrency) และระดับความเป็นส่วนตัว (Isolation Level) ของแต่ละ Session บนฐานข้อมูล จุดแข็งที่สุดอันหนึ่งของ Oracle เหนือฐานข้อมูลค่ายอื่น ๆ คือ การอ่านข้อมูล (ใน Session หนึ่ง)ไม่ขัดขวางการเขียนข้อมูล (ในอีก Session หนึ่ง) และในทางกลับกันการเขียนข้อมูลก็ไม่ขัดขวางการอ่านข้อมูลเช่นกัน แต่คุณสมบัติอันนี้ถ้าผู้พัฒนาโปรแกรมไม่เข้าใจ อาจจะทำให้เกิดความผิดพลาดได้เมื่อมีการใช้ทริกเกอร์ โดยเฉพาะเมื่อพยายามนำทริกเกอร์มาเพื่อบังคับใช้กฎบางอย่าง ลองดูตัวอย่าง


สมมติว่าเรามีตารางสกุลเงิน ซึ่งมีสกุลเงินหลักเพียงสกุลเดียวของแต่ละประเทศดังนี้
Country Currency Primary_Currency
US USD Y
US USN N
US USS N

เรา ต้องการจะบังคับใช้กฎว่ามีเพียงหนึ่งสกุลเงินเท่านั้นที่จะสามารถเป็น สกุลเงินหลักได้ในแต่ละประเทศ (Primary_Currency = 'Y') เราสร้างทริกเกอร์ BEFORE UPDATE แบบทำงาน "ทีละบรรทัด" (For Each Row) ในตารางข้างบนไว้ และใช้ Autonomous Transaction เพื่อหลีกเลี่ยงปัญหา Mutating Error (จะกล่าวถึงในภายหลัง) เพื่อที่จะเช็คว่าประเทศนั้น ๆ มี Primary_currency='Y') แล้วหรือยัง โดยที่ทริกเกอร์มีหน้าตาแบบนี้

SQL> create or replace
2 trigger currencies_trigger
3 before update on currencies
4 for each row
5 declare
6 PRAGMA AUTONOMOUS_TRANSACTION;
7 l_cnt number;
8 begin
9 select count(*)
10 into l_cnt
11 from currencies
12 where primary_currency='Y'
13 and country=:new.country;
14 if (l_cnt>1)
15 then
16 raise_application_error
17 (-20000,'only on allowed');
18 end if;
19 end;
20 /
Trigger created.


มี หลายสิ่งผิดปกติกับทริกเกอร์อันนี้ สิ่งที่เห็นได้ชัดคือความจำเป็นที่มันจะต้องใช้ Autonomous Transaction ซึ่งถ้าไม่ใช้จะเกิดข้อผิดพลาด
ORA-04091: table SCOTT.CURRENCIES is mutating, trigger/function may not see it และ
ORA-06512: at "SCOTT.CURRENCIES_TRIGGER", line 4
ORA-04088: error during execution of trigger 'SCOTT.CURRENCIES_TRIGGER'
ซึ่ง หมายถึง "คุณกำลังทำบางสิ่งบางอย่างที่ผิดกฎเบื้องต้น ซึ่งระบบฐานข้อมูล Oracle ไม่ยอมให้ทำแบบนั้น" ซึ่งถ้าระบบฯ ยอมให้ทริกเกอร์อ่านข้อมูลในตารางขณะที่ทำการอัพเดทไปทีละเรคคอร์ด ตัวทริกเกอร์ก็จะเห็นตารางที่ถูกอัพเดทไปทีละแถว ๆ เช่นถ้าเราอัพเดทข้อมูล 5 แถว (โดยคำสั่งอัพเดทคำสั่งเดียว) ทริกเกอร์ (แบบ For Each Row) ก็จะเห็นข้อมูลเปลี่ยนไปเมื่ออัพเดทแถวแรกเป็นจำนวนหนึ่งแถว ครั้งที่สองเปลี่ยนไปสองแถว ฯลฯ ซึ่งมันผิดปกติวิสัยของการมองเห็นตารางในแง่ของระบบฐานข้อมูล

สมมติ ว่าตาราง CURRENCIES ข้างบนมีทริกเกอร์ดังตัวอย่าง (CURRENCIES_TRIGGER) ซึ่งยอมให้อ่านข้อมูลจากตารางขณะที่ทำการอัพเดท ลองรันคำสั่งนี้ดู

SQL> update currencies
2 set primary_currency =
3 decode (currency,'USD','N','USN','Y')
4 where country = 'US'
5 and currency in ('USD','USN');


คำ สั่งนี้น่าจะโอเค เมื่อรันเสร็จควรจะมี Primary Currency เพียงหนึ่งแถวในแต่ละประเทศ ปกติระบบฯที่ไม่มีทริกเกอร์จะถือว่านี่เป็นหนึ่งคำสั่ง และรันมันตามปกติ แต่เนื่องจาก Autonomous Transaction ทริกเกอร์จะสามารถอัพเดทไปในขณะที่เช็คแถวที่มี Primary Currency เป็น 'Y' ไปทีละแถวได้ เราจะพบว่าถ้าระบบรันโดยอัพเดทแถวที่มี Currency เป็น 'USD' ก่อนเป็นแถวแรกก็จะทำให้แถวนี้มี Primary Currency เป็น 'N' เมื่อรันแถวต่อไปซึ่ง Currency เป็น 'USN' ก็จะอัพเดทให้ Primary Currency ของ 'USN' เป็น 'Y' แต่ถ้าลำดับของการรันเริ่มจากแถวที่มี Currency เป็น 'USN' ก่อน (ปกติลำดับการปรากฎอยู่ของแถวของฐานข้อมูลตามแนวคิดของระบบฐานข้อมูลเชิง สัมพันธ์ จะไม่มีนัยสำคัญแต่อย่างใด คือข้อมูลที่เรา Insert เข้าไปอาจจะอยู่ที่ลำดับแถวใด ๆ ในตารางก็ได้) ผลที่ได้คือเมื่อทริกเกอร์รันครั้งแรกมันจะเห็นว่า 'USN' มี PRIMARY_CURRENCY='Y' (ของใหม่) ในขณะเดียวกัน 'USD' ก็มี PRIMARY_CURRENCY='Y' (ของเก่า) ซึ่งก็จะเกิด Error ซึ่งไม่ใช่เพราะคำสั่งนี้จริง ๆ แล้วต้องทำได้และสำเร็จ ดังนั้นทริกเกอร์ตัวนี้จะใช้ได้ (สำเร็จ) กับข้อมูลบางส่วน และบางส่วนจะใช้ไม่ได้ ถ้าสองฐานข้อมูลมีข้อมูลเหมือนกันแต่แถวอยู่ต่างลำดับกัน ซึ่งทำให้ลำดับการรันต่างกัน ก็จะให้ผลที่ต่างกัน และยอมรับไม่ได้ และนั่นเป็นเหตุผลว่าทำไมจะต้องมีการกำหนดข้อบังคับเกี่ยวกับการ Mutating Table เพื่อป้องกันความผิดพลาดของเราเอง แต่อาจจะโชคดีหรือไม่ดีที่ผู้พัฒนาโปรแกรมสามารถที่จะเลือกที่จะใช้ Autonomouse Transaction เพื่อหลีกเลี่ยงปัญหาดังกล่าวและเปิดช่องให้มีการคิวรีข้อมูลจากตารางในขณะ ที่ทริกเกอร์ที่อยู่บนตารางนั้นกำลังทำงานดังกับว่ามันอยู่คนละ Session กัน ทริกเกอร์จะไม่สามารถจะเห็นความเปลี่ยนแปลงที่เกิดขึ้นกับตารางจากคำสั่งอัพ เดทได้ (ดังเช่นที่ทริกเกอร์ไม่สามารถเห็นว่าในที่สุดแล้ว 'USD' จะถูกเซ็ท Primary Currencyเป็น 'N' ในท้ายที่สุด หากระบบฯ รันเอาตัว 'USN' ขึ้นก่อน) จริง ๆ แล้วหน้าที่ของทริกเกอร์คือการตรวจสอบการเปลี่ยนแปลงที่จะเกิดขึ้นกับข้อมูล (ว่าถูกต้องหรือไม่) กลับไปอ่านข้อมูลก่อนที่การเปลี่ยนแปลงจะเกิดขึ้น ซึ่งทำให้ไม่สามารถยอมรับได้

ผู้พัฒนาอาจจะหาหนทางจัดการกับปัญหานี้ โดยการใช้ Package และทริกเกอร์ 3 ตัว ดูเรื่องนี้ใน http://asktom.oracle.com/tkyte/Mutate ใน Oracle11g มีความสามารถใหม่เรียกว่า "Compound Trigger" ซึ่งสามารถใช้แทนแนวคิด Package และทริกเกอร์ 3 ตัวนี้ได้ ซึ่งผลลัพท์ที่ได้จะเหมือนกันดังต่อไปนี้

เทคนิค นี้ Package จะมี Global Variable เป็นประเภท PLSQL table (ตัวอย่างเช่น Array), Global Variable ตัวนี้จะถูกตั้งให้เป็นค่าว่าง โดยทริกเกอร์ BEFORE Statement หลังจากนั้น Global Variable จะถูกใส่ค่า Primary Keys โดยทริกเกอร์อีกตัว (FOR EACH ROW) ซึ่งเก็บทุกคีย์ของแถวที่ถูกอัพเดท หรือเก็บ rowid ของทุกแถวก็ได้ และในที่สุดทริกเกอร์ AFTER Statement จะตรวจสอบค่าใน Global Variable (Array) ซึ่งได้ผ่านการเปลี่ยนแปลงตามคำสั่งทั้งหมดทุกแถวแล้ว ซึ่งฟังดูน่าจะใช้ได้ แต่วิธีการ Package และทริกเกอร์ 3 ตัวก็ได้ผลกับเฉพาะถ้าคุณเป็นคนเดียวที่ใช้ระบบฯ อยู่และจะต้องไม่มีธุรกรรมมากกว่าหนึ่งธุรกรรม ณ ขณะใดขณะหนึ่ง ทริกเกอร์จำนวนมากที่มีลักษณะที่ทำงานได้ดีถ้าใช้งานโดยผู้ใช้เพียงคนเดียว แต่จะมีปัญหาถ้ามีผู้ใช้มากกว่าหนึ่งคนทำงานร่วมกัน ตัวอย่างเช่น ถ้าข้อมูลในตาราง Currencies เริ่มต้นด้วย primary_currency เป็น 'N' ทั้งหมด

Country Currency Primary_Currency
US USD N
US USN N
US USS N

ใน Session แรก เรารันคำสั่งนี้

SQL> update currencies
2 set primary_currency = 'Y'
4 where country = 'US'
5 and currency = 'USD';


โดย การใช้วิธีการทริกเกอร์ 3 ตัว ทริกเกอร์ BEFORE จะเซ็ทค่า Globa Variable ให้เป็นค่าว่าง ต่อมาทริกเกอร์ FOR EACH ROW จะทำงานและจะจำประเทศที่ถูกแก้ไขเอาไว้ใน Global Variable หลังจากนั้นทริกเกอร์ AFTER จะทำงานโดยการตรวจสอบว่าใน Country ที่ระบุไว้ใน Global Variable มีกี่ตัวที่มีค่า Primary Currency เป็น 'Y' ถ้ามีตัวเดียวก็ถือว่าใช้ได้ ซึ่งแนวคิดทริกเกอร์ 3 ตัวนี้น่าจะใช้ได้ แต่ถ้าเกิดมี Session อื่น หลังจากที่ Session แรกทำการอัพเดทแล้วแต่ยังไม่ได้ Commit รันคำสั่ง

SQL> update currencies
2 set primary_currency = 'Y'
4 where country = 'US'
5 and currency = 'USN';


ทริกเกอร์ ก็จะทำงานของมัน ทริกเกอร์ AFTER จะทำการนับจำนวน Primary Currency ที่เป็น 'Y' เหมือน ๆ กันและจะไม่เห็นว่ามี Primary Currency ที่เป็น 'Y' ในอีกหนึ่ง Session ที่ยังไม่ได้ Commit ผลที่ได้คือทริกเกอร์ AFTER ก็จะพบว่าคำสั่งนี้ไม่ทำให้มีแถวที่มี Primary Currency เป็น 'Y' มากกว่าหนึ่งแถว แต่เมื่อทั้งสองแถวทำการ Commit จะพบว่าทั้ง Currency 'USD' และ 'USN' ต่างก็มี Primary Currency เป็น 'Y' นั่นหมายความว่ากฎที่เราพยายามที่จะบังคับไม่สามารถทำงานได้ถูกต้อง การจะทำให้กฎนี้ทำงานได้จะต้องทำการ "Serialized" (ยอมให้การกระทำใด ๆ ต่อตารางต้องทำทีละหนึ่ง การกระทำที่ตามมาจะต้องรอให้การกระทำก่อนหน้าเสร็จก่อน) หรือทำการล๊อคเรคคอร์ดที่เราต้องการอัพเดทนั้นไว้ แต่กฎนี้จะต้องสามารถใช้ได้กับคำสั่ง Insert ด้วยซึ่งทำให้เราจะต้องล๊อคกันในระดับตารางเลยทีเดียวเพื่อป้องกันไม่ให้ผู้ อื่นเข้ามา Insert ลงในตารางเดียวกันในขณะที่เราทำการ Insert ได้

อาจ จะกล่าวได้ว่าถ้ามีการใช้ทริกเกอร์ที่ทำการบังคับใช้กฎข้ามแถว (เช่นกฎที่ระบุว่าในทุก ๆ แถวของคอลัมน์หนึ่งจะมีค่าที่ระบุเกิดขึ้นในคอลัมน์นั้นได้เพียงครั้งเดียว ดังตัวอย่าง Primary Currency ที่กล่าวมาแล้ว) แล้วไม่มีการใช้คำสั่ง LOCK TABLE เพื่อทำการ Serialized การเข้าถึงตารางแล้ว ผลที่ได้น่าจะมีความผิดพลาดอยู่อย่างค่อนข้างแน่ชัด ซึ่งส่งผลกับความถูกต้องของข้อมูลอย่างหลีกเลี่ยงไม่ได้ การจะบังคับใช้กฎกับตารางโดยใช้ทริกเกอร์นั้นจึงเป็นเรื่องซับซ้อน และมักจะมีความจำเป็นต้องมีการล๊อคในระดับตารางดังได้กล่าวมาแล้ว

(ยังไม่จบนะครับ ยังมีตอนต่อไป...ขอขอบคุณที่ให้ความสนใจและโปรดติดตามตอนต่อไปนะครับ)

แปลจาก "The Trouble with Triggers"
โดย Tom Kyte, Oracle Magazine Volume XXII / Number 5 September/October2008, ASK TOM



http://tanakornt.blogspot.com/2011/04/trigger-2.html


Short URL click! Facebook Share
<< Back : เข้าชม 6,416 ครั้ง : ขึ้นไปด้านบน
รับโพสเว็บ รับจ้างโพสเว็บบอร์ด รับโพสเว็บไซด์ webboard Seeding รับจ้างโพสต์ โปรโมทเว็บไซต์ webUB.com



รับทำเว็บไซต์, ทำเว็บ, สร้างเว็บไซต์, รับทำเว็บ, รับออกแบบเว็บ, รับเขียนเว็บ, ออกแบบเว็บ, เว็บดีไซน์, รับสร้างเว็บ, เขียนเว็บไซต์, เว็บ, บริษัท ทำเว็บ, บริษัท สร้างเว็บ, บริษัท ออกแบบเว็บ, บริษัท เขียนเว็บ, ผลงานเว็บ, โฮสติ้ง,Design,Web,เว็บ,เว็บ โฮสติ้ง,เว็ป,โฮสติ้ง ราคาถูก,เว็บไซต์,จดโดเมน,เว็บโฮสติ้ง,Web Download,Web PHP,Flash MX,Graphic Design,Search Engine, Web, Design, Web Host,Web Hosting,Web Page,เขียนเว็บ,เขียนเว็บไซต์,จัดทำเว็บ,จัดทำเว็บไซต์,ทำเว็บ,ทำเว็บไซต์, โปรโมทเว็บ,ฟรี เว็บ,รับเขียนเว็บ,รับทำเว็บ,รับทำเว็บไซต์,รับออกแบบเว็บ,รับออกแบบเว็บไซ ต์,เว็บ สำเร็จรูป,เว็บดีไซน์,เว็ปไซต์, สร้างเว็บ,สร้างเว็บไซต์,ออกแบบ เว็บไซต์,ออกแบบเว็บ,ออกแบบเว็บไซต์,เขียนโปรแกรม,บริการเว็บโฮสติ้ง,ประชา สัมพันธ์เว็บ,รับจัดทำเว็บไซต์,รับสร้างเว็บ,เว็บโปรแกรม,เว็บสวย, บริการจัดทำเว็บไซต์,บริษัทรับจัดทำเว็บไซต์,ให้บริการจัดทำเว็บไซต์, มีประสบการณ์การจัดทำเว็บไซต์, งานบริการเว็บไซต์,ผลงานการเว็บไซต์,ผลงานเว็บไซต์,เว็บไซต์,เว็บไซต์ ปรัชญา "พอเพียง",เว็บไซต์ราคาที่ยุติธรรม,เว็บไซต์ระบบมาตรฐาน,เว็บไซต์ทุกงาน, เว็บไซต์ธุรกิจ, โปรโมทเว็บ,ประชาสัมพันธ์เว็บ,เว็บ,ออกแบบเว็บ,เขียนโปรแกรม,สร้างเว็บ,ออก แบบเว็บไซต์,ทำเว็บ,เว็บสวย,เขียนเว็บไซต์,ทำเว็บไซต์,รับทำเว็บ,รับออกแบบ เว็บ,เขียนเว็บ,รับเขียนเว็บ,รับทำเว็บไซต์,รับจัดทำเว็บไซต์,เว็บโฮสติ้ง, จัดทำเว็บ,เว็บโปรแกรม,เว็บไซต์,เว็บดีไซน์,รับออกแบบเว็บไซต์,สร้างเว็บไซ ต์,เว็บ,จดโดเมน,บริการเว็บโฮสติ้ง,จัดทำเว็บไซต์,โปรแกรมคอมพิวเตอร์

รับทำเว็บไซต์ : โปรโมทเว็บไซต์ : รับเขียนโปรแกรม : สอนสร้างเว็บ : จด Domain name 299บ. : เช่า Hosting : บริการดูแลเว็บไซต์ : รับซื้อ ขาย Rolex : Sitemap.xml
สปริงเกอร์

ข้อสอบ คลังข้อสอบ ระบบข้อสอบ โปรแกรมข้อสอบ ฟรี Exam.in.th
เว็บไซต์ในเครือข่าย: SiamWebCity.com webUB.com EXAM.in.th ข้อสอบ.ไทย ไอเดียแต่งบ้าน homeEST.com
Copyright © 2009-2019 SiamWebCity.COM. ® All rights reserved. หมายเลขทะเบียนประกอบพานิชย์อิเลคทรอนิกส์ : 0447314800321
E-mail, Google Talk : admin [at] siamwebcity.com, Skype: SiamWebCity.com
ขึ้นไปด้านบน