ต่อ MCP Server เข้าฐานข้อมูล Production ต้องล็อก Permission และ Read Only ก่อนเปิดให้ Agent ใช้

สรุปสั้น ๆ
MCP server ที่ต่อเข้าฐานข้อมูล production ต้องผ่านชั้น Permission ของตัวเอง ไม่ใช่พึ่งพา credential เดิมของแอปหลัก ต้องบังคับโหมดอ่านอย่างเดียวเป็นค่าเริ่มต้น เปิดโหมดเขียนเฉพาะ table และ operation ที่จำเป็นจริง พร้อมมี query timeout, row limit และ audit log ทุกครั้งที่ Agent เรียกใช้
มีทีมหนึ่งที่อยากให้ Agent ตอบคำถามธุรกิจได้ตรงจากฐานข้อมูลจริง เช่น 'เดือนนี้ยอดขายรวมเท่าไร' หรือ 'ลูกค้ารายไหนค้างชำระเกิน 30 วัน' วิธีที่เร็วที่สุดในสายตาทีมคือต่อ MCP server เข้ากับฐานข้อมูล production ตัวเดียวกับที่แอปหลักใช้งานอยู่ แล้วให้ Agent ยิง SQL ได้อิสระตามที่มันคิดว่าจำเป็น
สิ่งที่เกิดขึ้นในสัปดาห์แรกคือ Agent ตอบคำถามได้ดีจริงในหลายกรณี แต่ก็มีอยู่ครั้งหนึ่งที่มันพยายามช่วยผู้ใช้ 'อัปเดตสถานะลูกค้าที่ซ้ำกันให้เป็นสถานะเดียว' ด้วยการรัน UPDATE แบบไม่มี WHERE ที่แคบพอ ผลคือข้อมูลลูกค้าหลายพันแถวถูกเปลี่ยนสถานะผิดพลาดในไม่กี่วินาที ทั้งที่ไม่มีใครสั่งให้มันทำแบบนั้นตรง ๆ
เหตุการณ์แบบนี้ไม่ใช่เรื่องแปลกสำหรับทีมที่รีบต่อ MCP เข้าฐานข้อมูลโดยไม่วางชั้น Permission ก่อน บทความนี้จะพาวางกรอบที่ใช้ได้จริง ตั้งแต่การแยก credential ของ MCP ออกจากแอปหลัก การบังคับ read only เป็นค่าเริ่มต้น ไปจนถึงการจำกัด table, row limit และการเก็บ audit log ทุกครั้งที่มีการเรียกใช้
ทำไมการใช้ credential เดียวกับแอปหลักถึงเป็นความเสี่ยงที่มองไม่เห็นทันที
แอปหลักของธุรกิจส่วนใหญ่ถูกออกแบบมาให้ทำงานผ่านชั้น business logic ที่มี validation อยู่ก่อนแล้ว เช่น ก่อนจะลบลูกค้าได้ต้องผ่านการตรวจสอบสิทธิ์ ตรวจสอบว่ามี Order ค้างอยู่หรือไม่ และมี confirmation step ให้ผู้ใช้กดยืนยัน แต่พอ MCP server ใช้ credential ระดับฐานข้อมูลตรง ๆ มันจะข้ามชั้น business logic เหล่านั้นไปหมด กลายเป็นการคุยกับฐานข้อมูลแบบดิบที่ไม่มี validation คั่นกลางเลย
อีกความเสี่ยงที่มองไม่เห็นในตอนแรกคือขอบเขตของ credential เดิมมักกว้างกว่าที่ Agent ควรมีสิทธิ์เยอะมาก เพราะแอปหลักมักต้องเข้าถึงแทบทุก table เพื่อทำงานได้ครบ แต่ Agent ที่ตอบคำถามธุรกิจส่วนใหญ่ต้องการแค่ table รายงานไม่กี่ตัว การใช้ credential เดียวกันจึงเท่ากับเปิดประตูกว้างกว่าที่จำเป็นให้กับระบบที่ยังคาดเดาพฤติกรรมได้ไม่แน่นอนเท่าโค้ดที่เขียนไว้ตายตัว
หลักที่ควรยึดคือสร้าง database user ใหม่แยกต่างหากสำหรับ MCP server โดยเฉพาะ ไม่ใช้ user เดียวกับแอปหลักหรือ user ระดับ admin เด็ดขาด แล้วกำหนดสิทธิ์ของ user นี้ตั้งแต่ระดับฐานข้อมูลเลย ไม่ใช่พึ่งพาแค่ logic ฝั่ง MCP server อย่างเดียว เพราะถ้าชั้น logic มีช่องโหว่ สิทธิ์ระดับฐานข้อมูลจะเป็นแนวป้องกันสุดท้ายที่ยังกันความเสียหายไว้ได้
บังคับโหมดอ่านอย่างเดียวเป็นค่าเริ่มต้น แล้วเปิดโหมดเขียนเฉพาะที่จำเป็นจริง
แนวทางที่ปลอดภัยที่สุดคือเริ่มจากให้ MCP server เข้าถึงฐานข้อมูลได้แค่โหมดอ่านอย่างเดียว (read only) เสมอ ไม่ว่างานที่ Agent ต้องทำจะดูเหมือนต้องเขียนข้อมูลด้วยหรือไม่ก็ตาม เพราะงานส่วนใหญ่ที่ธุรกิจต้องการจาก Agent คือการตอบคำถามและสรุปข้อมูล ซึ่งไม่จำเป็นต้องเขียนอะไรเข้าฐานข้อมูลเลย
ถ้ามีความจำเป็นจริง ๆ ที่ต้องให้ Agent เขียนข้อมูลได้ เช่น อัปเดตสถานะ Order หรือบันทึกบันทึกการติดต่อลูกค้า ควรเปิดสิทธิ์เขียนเฉพาะ table และ column ที่จำเป็นเท่านั้น ไม่ใช่เปิด write ให้ทั้งฐานข้อมูล และควรทำผ่าน stored procedure หรือ tool เฉพาะที่ควบคุม logic ไว้แล้ว แทนที่จะให้ Agent ยิง UPDATE หรือ DELETE แบบอิสระ
หลักการสำคัญคือแยก tool ที่อ่านออกจาก tool ที่เขียนให้ชัดเจนแบบเดียวกับที่ใช้ในการออกแบบ MCP tool ทั่วไป ห้ามมี tool เดียวที่รับพารามิเตอร์บอกว่าจะอ่านหรือเขียน เพราะยิ่งเพิ่มความเสี่ยงที่ Agent เลือกโหมดผิดโดยไม่ตั้งใจ ยิ่งงานที่กระทบข้อมูลจริงมากเท่าไร ยิ่งต้องแยก tool ให้ชัดเจนมากขึ้นเท่านั้น
วาง Permission Matrix ก่อนเขียน tool แม้แต่ตัวแรก
ก่อนเขียนโค้ด MCP tool ตัวแรก ควรนั่งวางตารางว่า table ไหนที่ Agent ควรอ่านได้ table ไหนที่ห้ามแตะเลย และ table ไหนที่อ่านได้แต่ต้องกรอง column ที่มีข้อมูลอ่อนไหวออกก่อน เช่น table ลูกค้าที่มี column เลขบัตรประชาชนหรือรหัสผ่านที่ hash ไว้ ต่อให้เป็นโหมดอ่านอย่างเดียวก็ไม่ควรให้ Agent เห็น column เหล่านี้
| Table | สิทธิ์ที่ Agent ควรมี | เหตุผล |
|---|---|---|
| orders | อ่านได้ทุก column ยกเว้น internal_note | ใช้ตอบคำถามยอดขาย แต่ note ภายในอาจมีข้อมูลอ่อนไหวของทีมขาย |
| customers | อ่านได้เฉพาะ column ที่ไม่ใช่ PII ดิบ | ป้องกันข้อมูลส่วนบุคคลรั่วผ่านบทสนทนา |
| payment_logs | ห้ามเข้าถึงเลย | ข้อมูลการเงินละเอียดอ่อนเกินกว่าจะให้ Agent อ่านโดยตรง |
| order_status_history | อ่านและเขียนได้ผ่าน tool เฉพาะ | งานอัปเดตสถานะที่ธุรกิจต้องการให้ Agent ช่วยจริง ควบคุมผ่าน stored procedure |
วาง Guardrail ระดับ query เพื่อกันเหตุการณ์ที่ Permission อย่างเดียวกันไม่ได้
Permission ระดับ table ป้องกันได้แค่ว่า Agent แตะ table ไหนได้บ้าง แต่ป้องกันไม่ได้ว่า query ที่มันสร้างจะกวาดข้อมูลทั้ง table โดยไม่มี WHERE ที่แคบพอ หรือ query ที่ join หลาย table จนใช้เวลานานจนกระทบ performance ของฐานข้อมูล production จึงต้องมี guardrail เพิ่มอีกชั้นที่ระดับ query เอง
guardrail ที่ควรมีอย่างน้อยคือ row limit บังคับในทุก query แม้ Agent จะไม่ได้ใส่ LIMIT มาเอง เช่น บังคับสูงสุด 500 แถวต่อการเรียกหนึ่งครั้ง เพื่อกันทั้งการกวาดข้อมูลเกินจำเป็นและกัน context ของ Agent บวมจนล้น อีกอย่างคือ query timeout ที่ตัดการทำงานถ้า query ใช้เวลานานเกินกำหนด เพื่อกันไม่ให้ query หนักไปกระทบผู้ใช้งานจริงของแอปหลักที่ใช้ฐานข้อมูลเดียวกันอยู่
สำหรับทีมที่ให้ Agent สร้าง SQL เองแบบ dynamic ควรมีขั้นตอน parse และตรวจสอบ query ก่อนรันจริงเสมอ เช่น ปฏิเสธ query ที่มีคำสั่ง DROP, TRUNCATE หรือ DELETE โดยไม่มี WHERE ปฏิเสธ query ที่พยายามเข้าถึง table นอกรายการที่อนุญาต และ log ทุก query ที่ถูกปฏิเสธไว้เพื่อดูภายหลังว่า Agent พยายามทำอะไรที่ไม่ควรทำบ้าง
พิจารณาต่อเข้า Read Replica แทน Production หลักเมื่อทำได้
ถ้าระบบมี read replica อยู่แล้ว การให้ MCP server ต่อเข้า replica แทนฐานข้อมูล production หลักเป็นทางเลือกที่ปลอดภัยกว่ามาก เพราะต่อให้ guardrail ทุกชั้นพลาดไปหมด ความเสียหายที่เกิดขึ้นก็จะจำกัดอยู่ที่ replica ไม่กระทบข้อมูล production จริง และ query ที่หนักของ Agent ก็ไม่ไปแย่ง resource จากผู้ใช้งานจริงของแอปหลัก
ข้อควรระวังของการใช้ replica คือข้อมูลอาจ delay จาก production หลักไม่กี่วินาทีถึงไม่กี่นาทีขึ้นกับการตั้งค่า replication ถ้าธุรกิจต้องการคำตอบแบบ real-time เป๊ะ ๆ เช่น ยืนยันว่า Order เพิ่งเกิดขึ้นเมื่อครู่นี้แล้วหรือยัง ต้องแจ้ง Agent ให้บอกผู้ใช้ตรง ๆ ว่าข้อมูลอาจมี delay เล็กน้อย แทนที่จะพูดเหมือนข้อมูลเป็น real-time เสมอไป
เก็บ Audit Log ทุกครั้งที่ Agent เรียกใช้ฐานข้อมูล ไม่ใช่แค่ตอนมีปัญหา
ทีมจำนวนมากเพิ่งเริ่มคิดเรื่อง audit log หลังจากมีเหตุการณ์ผิดพลาดเกิดขึ้นแล้ว ทั้งที่ควรวางไว้ตั้งแต่วันแรกที่เปิดให้ Agent เข้าถึงฐานข้อมูล เพราะเมื่อเกิดปัญหาขึ้นจริง สิ่งแรกที่ต้องรู้คือ query อะไรถูกรันไปบ้าง ใครหรือ Agent session ไหนเป็นคนสั่ง และผลลัพธ์ที่ได้กระทบข้อมูลกี่แถว
audit log ที่ดีควรบันทึกอย่างน้อย timestamp, session หรือ conversation id ที่เรียกใช้, query หรือ tool call ที่เกิดขึ้นพร้อมพารามิเตอร์, จำนวนแถวที่ได้รับผลกระทบ และผลลัพธ์ว่าสำเร็จหรือถูกปฏิเสธโดย guardrail ข้อมูลชุดนี้ไม่ได้มีประโยชน์แค่ตอนสืบสวนปัญหา แต่ยังใช้เป็นข้อมูลตั้งต้นสำหรับปรับ Permission Matrix และ guardrail ให้แม่นขึ้นเรื่อย ๆ ตามพฤติกรรมจริงที่เกิดขึ้น
ควบคุมว่า Agent เห็น Schema มากแค่ไหน ไม่ใช่เปิดให้เห็นทั้งฐานข้อมูล
อีกจุดที่มักถูกมองข้ามคือการเปิดให้ Agent เรียกดู schema ของฐานข้อมูลทั้งหมดเพื่อ 'ช่วยให้มันเขียน query ได้ฉลาดขึ้น' ซึ่งฟังดูมีเหตุผลในแง่ความสะดวก แต่ก็หมายความว่า Agent จะรู้จักชื่อ table และ column ทุกตัวในระบบ รวมถึง table ที่ไม่ควรเกี่ยวข้องกับงานที่มันต้องทำเลย เพิ่มพื้นผิวความเสี่ยงโดยไม่จำเป็น
แนวทางที่ดีกว่าคือสร้าง view หรือ schema ย่อยที่มีเฉพาะ table และ column ที่เกี่ยวข้องกับงานของ Agent จริง ๆ แล้วให้ MCP server รู้จักแค่ schema ย่อยนี้เท่านั้น วิธีนี้นอกจากจะลดความเสี่ยงแล้ว ยังช่วยให้ Agent สร้าง query ได้แม่นขึ้นด้วย เพราะไม่ต้องเลือกจาก table ที่ไม่เกี่ยวข้องปะปนอยู่จำนวนมาก
ทำแบบนี้แล้วพัง เพราะ… ข้อผิดพลาดที่เจอบ่อยตอนต่อ MCP เข้าฐานข้อมูล
- ใช้ connection string เดียวกับแอปหลักเพื่อความเร็วในการเริ่มโปรเจกต์ — ทำแบบนี้แล้วพัง เพราะ Agent จะมีสิทธิ์เท่ากับแอปหลักทั้งหมด รวมถึงสิทธิ์เขียนและลบที่ไม่ควรมีตั้งแต่แรก
- ปล่อยให้ Agent สร้าง SQL แบบอิสระโดยไม่มีการตรวจสอบก่อนรัน — ทำแบบนี้แล้วพัง เพราะไม่มีอะไรกันคำสั่งที่กว้างเกินไปอย่าง UPDATE หรือ DELETE ที่ขาด WHERE ที่แคบพอ
- ไม่ตั้ง row limit หรือ query timeout ไว้ — ทำแบบนี้แล้วพัง เพราะ query หนักที่ Agent สร้างขึ้นเองอาจไปแย่ง resource จนกระทบผู้ใช้งานจริงของระบบหลักโดยไม่มีใครรู้ตัวจนกว่าจะช้าลงชัดเจน
- เปิด schema เต็มให้ Agent เห็นทุก table เพื่อ 'ให้มันฉลาดขึ้น' — ทำแบบนี้แล้วพัง เพราะเพิ่มพื้นผิวความเสี่ยงโดยไม่จำเป็น และ Agent อาจเผลอไปยุ่งกับ table ที่ไม่เกี่ยวข้องกับงานจริง
- ไม่เก็บ audit log เพราะคิดว่ายังไม่จำเป็นในช่วงทดลอง — ทำแบบนี้แล้วพัง เพราะพอเกิดปัญหาขึ้นจริงจะไม่มีข้อมูลย้อนกลับไปสืบว่าเกิดอะไรขึ้น และไม่มีข้อมูลไว้ปรับปรุง Permission ให้แม่นขึ้น
สรุป
การต่อ MCP server เข้าฐานข้อมูล production ให้ปลอดภัย ไม่ใช่แค่เรื่องเทคนิคการเชื่อมต่อ แต่เป็นเรื่องของการออกแบบชั้น Permission ตั้งแต่ database user, table ที่เข้าถึงได้, guardrail ระดับ query ไปจนถึง audit log ที่ครบถ้วน ทุกชั้นต้องทำงานร่วมกัน ไม่ใช่พึ่งพาชั้นใดชั้นหนึ่งเพียงอย่างเดียว
หลักที่ง่ายที่สุดและควรเริ่มต้นด้วยเสมอคือบังคับโหมดอ่านอย่างเดียวเป็นค่าเริ่มต้น แล้วค่อยเปิดสิทธิ์เขียนเฉพาะจุดที่จำเป็นจริงและควบคุมได้ผ่าน tool เฉพาะ ไม่ใช่เปิดกว้างตั้งแต่แรกแล้วค่อยมาไล่ปิดทีหลังเมื่อเกิดปัญหาแล้ว
- แยก database user ของ MCP ออกจากแอปหลักเสมอ อย่าใช้ credential เดียวกัน
- บังคับ read only เป็นค่าเริ่มต้น เปิดเขียนเฉพาะ table และ operation ที่จำเป็นจริง
- วาง guardrail ระดับ query คือ row limit, query timeout และการตรวจคำสั่งอันตราย
- เก็บ audit log ทุกครั้งที่เรียกใช้ ไม่ใช่แค่ตอนมีปัญหาแล้ว
คำถามที่พบบ่อย
ต่อ MCP server เข้าฐานข้อมูลจำเป็นต้องใช้ read replica เสมอไหม
ไม่จำเป็นเสมอไป แต่แนะนำอย่างยิ่งถ้ามีอยู่แล้วในระบบ เพราะเพิ่มชั้นความปลอดภัยโดยไม่ต้องเขียน guardrail เพิ่มเติม ถ้าไม่มี replica ต้องพึ่งพา Permission ระดับฐานข้อมูล guardrail ระดับ query และ audit log ให้ครบแทน
จำเป็นต้องแยก database user สำหรับ MCP จริงหรือ ใช้ user เดิมแต่จำกัดสิทธิ์เพิ่มไม่ได้เหรอ
ทำได้ในทางเทคนิค แต่ไม่แนะนำ เพราะการแก้สิทธิ์ของ user เดิมเสี่ยงกระทบแอปหลักที่ใช้ user เดียวกันอยู่ การแยก user ใหม่ทำให้ควบคุมและตรวจสอบสิทธิ์ของ MCP ได้อิสระโดยไม่กระทบระบบเดิม
ควรให้ Agent เขียน SQL เองหรือควรมี tool สำเร็จรูปสำหรับแต่ละคำถาม
สำหรับงานที่ทำซ้ำบ่อยและกำหนดรูปแบบได้ล่วงหน้า เช่น สรุปยอดขายรายเดือน ควรทำเป็น tool สำเร็จรูปที่ควบคุม query ไว้แน่นอน ปลอดภัยกว่าและคาดเดาผลลัพธ์ได้ ส่วนคำถามที่หลากหลายเกินจะเขียน tool ครบทุกแบบ อาจต้องให้สร้าง SQL แบบ dynamic แต่ต้องผ่านการตรวจสอบและ guardrail อย่างเข้มงวดก่อนรันเสมอ
row limit ควรตั้งไว้เท่าไรถึงจะเหมาะสม
ขึ้นกับลักษณะงานและขนาด context ของ Agent ที่ใช้ แต่ค่าเริ่มต้นที่ใช้ได้ในหลายกรณีคือ 200-500 แถวต่อการเรียกหนึ่งครั้ง เพียงพอสำหรับการสรุปข้อมูลส่วนใหญ่และไม่ทำให้ context บวมจนล้น ถ้างานใดต้องการมากกว่านี้ควรออกแบบ tool ให้สรุปข้อมูลฝั่ง backend ก่อนส่งกลับ แทนที่จะส่งข้อมูลดิบจำนวนมากให้ Agent ประมวลผลเอง
audit log ควรเก็บไว้นานแค่ไหน
ควรกำหนดตาม policy การเก็บข้อมูลของธุรกิจและข้อกำหนดด้านกฎหมายที่เกี่ยวข้อง ไม่มีตัวเลขตายตัวที่ใช้ได้กับทุกกรณี แต่อย่างน้อยควรเก็บนานพอที่จะสืบสวนปัญหาย้อนหลังได้ในทางปฏิบัติ เช่น หลายเดือน แล้วพิจารณา archive ข้อมูลเก่าแทนการลบทิ้งทันที
ถ้าจำเป็นต้องให้ Agent เขียนข้อมูลจริง ควรมีขั้นตอนยืนยันจากคนก่อนไหม
สำหรับ operation ที่มีผลกระทบสูง เช่น ลบข้อมูลหรือเปลี่ยนสถานะการเงิน ควรมีขั้นตอนให้คนยืนยันก่อนเสมอ ไม่ควรให้ Agent ตัดสินใจรันเองโดยอัตโนมัติทั้งหมด การมีจุดอนุมัติจากคนเป็นแนวป้องกันสุดท้ายที่ลดความเสียหายเมื่อ guardrail อื่นพลาดไป
อ่านต่อแบบเจาะลึก
วัด Conversion LINE ทุกแบรนด์ รวมศูนย์ที่เดียว
องค์กรที่มีหลายแบรนด์ หลายสาขา หลาย LINE OA — linli รวม Tracking และส่ง Conversion กลับทุกแพลตฟอร์ม พร้อม Custom Limit เริ่มฟรี 14 วัน
ติดต่อทีม Salesบทความที่เกี่ยวข้อง

MCP Server ใช้ต่างจาก Webhook ตรงไหน เมื่อต้องต่อ Agent เข้าระบบที่ยิง Event เอง

เขียน MCP Tool ไป 12 ตัวให้ Agent ใช้ แต่มันเลือกผิดทุกครั้ง ทำไม
