ด้วยการใช้ชุดอักขระแบบหลายไบต์อย่างแพร่หลาย โปรแกรมเมอร์ที่พูดภาษาอังกฤษจำนวนมากในการพัฒนาซอฟต์แวร์จึงไม่ค่อยมีความรู้เกี่ยวกับอักขระแบบหลายไบต์มากนัก นี่คือสาเหตุว่าทำไมช่องโหว่จำนวนมากในช่วงไม่กี่ปีที่ผ่านมาจึงเป็นสาเหตุ ผู้เขียนบทความนี้พูดถึงมุมมองของเขาเองเกี่ยวกับบทบาทของสถาปัตยกรรมชุดอักขระของ MySQL ในช่วงไม่กี่เดือนที่ผ่านมา ทุกครั้งที่ฉันใช้ MySQL ฉันมักจะคิดเสมอว่า สถาปัตยกรรมชุดอักขระแบบลำดับชั้นในปัจจุบันของ MySQL มีประโยชน์จริงหรือไม่
การประมวลผลชุดอักขระ MySQL
ส่งคำขอ
ลูกค้า ( character_set_client ) = 》การเชื่อมต่อฐานข้อมูล ( character_set_connection ) = 》ที่เก็บข้อมูล (ตาราง คอลัมน์)
คำขอส่งคืน
ที่เก็บข้อมูล (ตาราง คอลัมน์)= 》การเชื่อมต่อฐานข้อมูล (Character_set_connection)= 》ไคลเอนต์ (Character_set_results)
ที่แต่ละโหนดที่ไม่ใช่ค่าเริ่มต้น การดำเนินการแปลงชุดอักขระจะดำเนินการจากโหนดก่อนหน้าไปยังโหนดปัจจุบัน ตัวอย่างเช่น พิจารณาสภาพแวดล้อมต่อไปนี้:
◆ character_set_connection utf-8
◆ character_set_results gbk
◆ character_set_client gb2312
◆ มีตาราง A และชุดอักขระฟิลด์ล้วนเป็น BIG5
เมื่อส่งคำขอ ข้อมูลจะถูกแปลงจาก gbk เป็น utf-8 ก่อน จากนั้นเป็น BIG5 จากนั้นจึงจัดเก็บ
เมื่อส่งคืนคำขอ ข้อมูลจะถูกแปลงจาก BIG5 เป็น utf-8 ก่อน จากนั้นเป็น gb2312 จากนั้นจึงส่งไปยังไคลเอนต์
บทบาทของสถาปัตยกรรม
1. อนุญาตให้ไคลเอนต์ที่แตกต่างกันมีชุดอักขระที่แตกต่างกัน ตัวอย่างทั่วไปคือ ฉันมีไซต์ UTF-8 ซึ่งเป็นไคลเอนต์ที่มีไคลเอนต์ชุดอักขระ UTF-8 ในเวลาเดียวกัน ฉันอาจจำเป็นต้องอ่านและเขียนฐานข้อมูลบนเทอร์มินัล gbk ซึ่งเป็นไคลเอนต์อื่น แต่ชุดอักขระของมันคือ gbk
2. เมื่อใช้งานระบบไฟล์ผ่านฐานข้อมูล คุณจะต้องแปลงพาธของไฟล์เป็นชุดอักขระของระบบไฟล์ ตัวอย่างเช่น ไคลเอนต์ของฉันคือ gbk และระบบไฟล์เซิร์ฟเวอร์เป็น utf-8 การดำเนินการ "/A Slice/Rina.rmvb" ในข้อมูลที่ส่ง ข้อมูลของ "slice" จะแตกต่างจากเซิร์ฟเวอร์ ในขณะนี้ จำเป็นต้องมีวิธีแปลง "สไลซ์" ของ GBK เป็น utf-8 ที่นี่ MySQL แนะนำสิ่งที่เรียกว่า character_filesystem เพื่อทำสิ่งนี้ให้สำเร็จ
นอกเหนือจากนั้น ฉันไม่สามารถนึกถึงการใช้งานอื่นใดได้ในขณะนี้ แต่ลองคิดดูให้ดีว่าเราต้องการการรักษาแบบนี้จริงหรือ? เว็บไซต์หลายแห่งเพียงหวังว่าข้อมูลของพวกเขาจะสามารถออกมาได้ตามต้องการ มีอีกสองสถานการณ์ที่นี่
1. ฉันหวังว่าฉันสามารถจัดเรียงหรือดำเนินการเหมือนกับการดำเนินการตามข้อมูลได้ เรามาพูดถึงการเรียงลำดับกันก่อน สำหรับฟิลด์ที่มีภาษาจีน แนวคิดของการเรียงลำดับตามชุดอักขระนั้นไม่มีประโยชน์ เมื่อเรียงลำดับภาษาจีนตัวย่อ โดยทั่วไปคุณต้องการจัดเรียงตามพินอิน ฉันไม่เข้าใจการยืนยันใน MySQL จริงๆ แต่เมื่อพิจารณาจากโปรแกรมที่ฉันสัมผัส หากจำเป็นต้องมีการเรียงลำดับประเภทนี้ ฟิลด์จะถูกสร้างขึ้นเป็นพิเศษเพื่อจัดเก็บพินอินสำหรับการเรียงลำดับ นอกจากนี้ยังมีอักขระโพลีโฟนิกในพินอินอีกด้วย หากเป็น UTF-8 ก็อาจมีสถานการณ์ที่จีน ญี่ปุ่น และเกาหลีใต้ใช้ภาษาจีนร่วมกันบางส่วนในเวลาเดียวกัน การติดตั้งใช้งานไม่ใช่เรื่องง่าย ดังนั้นทั้งชุดตรวจสอบ GBK และ UTF-8 ของ MySQL จึงไม่ควรใช้พินอิน ฉันกล้าพูดได้เลยว่าเว็บไซต์ส่วนใหญ่ในจีนที่ใช้ MySQL ตอนนี้ใช้ชุดตรวจสอบที่เป็นเพียงการเรียงลำดับไบต์ ด้วยการเรียงลำดับไบต์ ไม่จำเป็นต้องใช้ชุดอักขระใดๆ เลย ดังนั้น สำหรับไซต์ภาษาจีน การตรวจสอบอักขระ MySQL จึงไม่มีความหมายในการเรียงลำดับ
แต่ในแง่ของการดำเนินการ มันมีความหมายเพียงเล็กน้อย ตัวอย่างเช่น ถ้าฉันชอบ '%a%' ก็เป็นไปได้ที่จะจับคู่ตัวอักษรจีนที่มี a ในส่วนใดส่วนหนึ่ง แน่นอนว่าสถานการณ์นี้จะไม่พบใน UTF-8 เนื่องจากรูปแบบการจัดเก็บข้อมูลของ UTF-8 หมายความว่า a สามารถเป็นได้เท่านั้น และไม่สามารถเป็นส่วนหนึ่งของอักขระแบบหลายไบต์ได้ แต่ปัญหานี้อาจเกิดขึ้นในชุดอักขระอื่น สุดท้ายแล้วไลค์ก็เหมือนกับคำสั่ง ทำให้การตรวจสอบไม่มีความหมาย เป็นลม.
2. หากไม่จำเป็นต้องจัดเรียงข้อมูล เช่น หรือค้นหาข้อความแบบเต็ม โปรดหยุดใช้อักขระ varchar ข้อความและสิ่งที่คล้ายกัน binary, varbinary, BLOB เป็นตัวเลือกที่ถูกต้อง ไบนารี่และสิ่งที่คล้ายกันจะไม่ทำการแปลงชุดอักขระเมื่อจัดเก็บและเรียกค้น แต่เมื่อเรียงลำดับ จะถูกจัดเรียงตามเนื้อหาไบนารีเท่านั้น ดังนั้นประสิทธิภาพจึงสูงกว่าของถ่าน varchar และข้อความมาก
ในกรณีนี้ไม่จำเป็นต้องมีชุดอักขระ อย่างไรก็ตาม ตามสถาปัตยกรรม MySQL ในปัจจุบัน การดำเนินการชุดอักขระระหว่างไคลเอ็นต์และการเชื่อมต่อจะละเว้นประเภทฟิลด์ การแปลงชุดอักขระจะยังคงดำเนินการระหว่างสองโหนดนี้
กล่าวถึงการตั้งค่าชุดอักขระใน PHP ด้วย โปรดหยุดใช้คำสั่งเช่น mysql_query("set name utf8") mysql_set_charset() เป็นวิธีการตั้งค่าชุดอักขระที่สมบูรณ์ที่สุด อย่างหลังมีการตั้งค่าที่มากกว่าแบบแรก นั่นคือการตั้งค่าสมาชิกชุดอักขระของ struct MySQL ตัวแปรสมาชิกนี้มีบทบาทสำคัญในการหลีกเลี่ยง โดยเฉพาะอย่างยิ่งสำหรับรูปแบบการเข้ารหัส เช่น GBK ที่ใช้ "" เป็นส่วนหนึ่งของอักขระ หากคุณใช้เฉพาะ mysql_query("set name XXX") ในชุดอักขระบางชุด ก็จะมีช่องโหว่ด้านความปลอดภัยที่สำคัญ ส่งผลให้ mysql_real_escape_string ไม่ปลอดภัยเท่ากับเครื่องหมาย addslashes
-