[{"data":1,"prerenderedAt":3564},["ShallowReactive",2],{"navigation_docs":3,"-tu-hoc-database-mysql-cau-hoi-phong-van":420,"-tu-hoc-database-mysql-cau-hoi-phong-van-surround":3559},[4,153],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":26},"Phỏng vấn .NET","i-lucide-briefcase","\u002Fphong-van","1.phong-van",[10,27,66,111,128],{"title":11,"icon":12,"path":13,"stem":14,"children":15,"page":26},"Tổng quan","i-lucide-compass","\u002Fphong-van\u002Ftong-quan","1.phong-van\u002F1.tong-quan",[16,21],{"title":17,"path":18,"stem":19,"icon":20},"Thị trường HCM","\u002Fphong-van\u002Ftong-quan\u002Fthi-truong","1.phong-van\u002F1.tong-quan\u002F1.thi-truong","i-lucide-trending-up",{"title":22,"path":23,"stem":24,"icon":25},"Lộ trình 7 ngày","\u002Fphong-van\u002Ftong-quan\u002Flo-trinh","1.phong-van\u002F1.tong-quan\u002F2.lo-trinh","i-lucide-calendar-days",false,{"title":22,"icon":25,"path":28,"stem":29,"children":30,"page":26},"\u002Fphong-van\u002Flo-trinh","1.phong-van\u002F2.lo-trinh",[31,36,41,46,51,56,61],{"title":32,"path":33,"stem":34,"icon":35},"Ngày 1 — C# cơ bản","\u002Fphong-van\u002Flo-trinh\u002Fngay-1-csharp-co-ban","1.phong-van\u002F2.lo-trinh\u002F1.ngay-1-csharp-co-ban","i-lucide-1",{"title":37,"path":38,"stem":39,"icon":40},"Ngày 2 — OOP và SOLID","\u002Fphong-van\u002Flo-trinh\u002Fngay-2-oop-solid","1.phong-van\u002F2.lo-trinh\u002F2.ngay-2-oop-solid","i-lucide-2",{"title":42,"path":43,"stem":44,"icon":45},"Ngày 3 — C# nâng cao","\u002Fphong-van\u002Flo-trinh\u002Fngay-3-csharp-nang-cao","1.phong-van\u002F2.lo-trinh\u002F3.ngay-3-csharp-nang-cao","i-lucide-3",{"title":47,"path":48,"stem":49,"icon":50},"Ngày 4 — Database và SQL","\u002Fphong-van\u002Flo-trinh\u002Fngay-4-database-sql","1.phong-van\u002F2.lo-trinh\u002F4.ngay-4-database-sql","i-lucide-4",{"title":52,"path":53,"stem":54,"icon":55},"Ngày 5 — ASP.NET Core và EF Core","\u002Fphong-van\u002Flo-trinh\u002Fngay-5-aspnet-efcore","1.phong-van\u002F2.lo-trinh\u002F5.ngay-5-aspnet-efcore","i-lucide-5",{"title":57,"path":58,"stem":59,"icon":60},"Ngày 6 — DSA coding","\u002Fphong-van\u002Flo-trinh\u002Fngay-6-dsa","1.phong-van\u002F2.lo-trinh\u002F6.ngay-6-dsa","i-lucide-6",{"title":62,"path":63,"stem":64,"icon":65},"Ngày 7 — Mock và HR","\u002Fphong-van\u002Flo-trinh\u002Fngay-7-mock-interview","1.phong-van\u002F2.lo-trinh\u002F7.ngay-7-mock-interview","i-lucide-7",{"title":67,"icon":68,"path":69,"stem":70,"children":71,"page":26},"Ngân hàng câu hỏi","i-lucide-database","\u002Fphong-van\u002Fngan-hang-cau-hoi","1.phong-van\u002F3.ngan-hang-cau-hoi",[72,77,82,87,92,97,102,107],{"title":73,"path":74,"stem":75,"icon":76},"C# (60+ câu)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fcsharp","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F1.csharp","i-lucide-hash",{"title":78,"path":79,"stem":80,"icon":81},"OOP và SOLID (40+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Foop","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F2.oop","i-lucide-shapes",{"title":83,"path":84,"stem":85,"icon":86},"SQL (40+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fsql","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F3.sql","i-lucide-database-zap",{"title":88,"path":89,"stem":90,"icon":91},"ASP.NET và EF (50+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Faspnet-ef","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F4.aspnet-ef","i-lucide-server",{"title":93,"path":94,"stem":95,"icon":96},"DSA và Coding (30+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fdsa-coding","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F5.dsa-coding","i-lucide-binary",{"title":98,"path":99,"stem":100,"icon":101},"HR và Soft skill (25+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fhr-behavior","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F6.hr-behavior","i-lucide-users",{"title":103,"path":104,"stem":105,"icon":106},"Design Pattern (55+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fdesign-pattern","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F7.design-pattern","i-lucide-puzzle",{"title":108,"path":109,"stem":110,"icon":91},"ASP.NET MVC và Web API","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Faspnet-mvc-webapi","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F8.aspnet-mvc-webapi",{"title":112,"itle":113,"icon":114,"path":115,"stem":116,"children":117,"page":26},"Tai Lieu","Tài liệu và Cheat sheet","i-lucide-book-marked","\u002Fphong-van\u002Ftai-lieu","1.phong-van\u002F4.tai-lieu",[118,123],{"title":119,"path":120,"stem":121,"icon":122},"Cheat Sheet","\u002Fphong-van\u002Ftai-lieu\u002Fcheatsheet","1.phong-van\u002F4.tai-lieu\u002F1.cheatsheet","i-lucide-clipboard-list",{"title":124,"path":125,"stem":126,"icon":127},"Nguồn tham khảo","\u002Fphong-van\u002Ftai-lieu\u002Fnguon","1.phong-van\u002F4.tai-lieu\u002F2.nguon","i-lucide-link",{"title":129,"icon":130,"path":131,"stem":132,"children":133,"page":26},"Phỏng vấn English","i-lucide-globe","\u002Fphong-van\u002Fenglish-interview","1.phong-van\u002F5.english-interview",[134,138,143,148],{"title":135,"path":136,"stem":137,"icon":130},"Tổng quan English","\u002Fphong-van\u002Fenglish-interview\u002Ftong-quan","1.phong-van\u002F5.english-interview\u002F1.tong-quan",{"title":139,"path":140,"stem":141,"icon":142},"Vocabulary","\u002Fphong-van\u002Fenglish-interview\u002Fvocabulary","1.phong-van\u002F5.english-interview\u002F2.vocabulary","i-lucide-book-a",{"title":144,"path":145,"stem":146,"icon":147},"Technical Q và A (EN)","\u002Fphong-van\u002Fenglish-interview\u002Ftechnical-en","1.phong-van\u002F5.english-interview\u002F3.technical-en","i-lucide-code",{"title":149,"path":150,"stem":151,"icon":152},"Behavioral (EN)","\u002Fphong-van\u002Fenglish-interview\u002Fbehavioral-en","1.phong-van\u002F5.english-interview\u002F4.behavioral-en","i-lucide-message-square-text",{"title":154,"icon":155,"path":156,"stem":157,"children":158},"Tự học","i-lucide-graduation-cap","\u002Ftu-hoc","2.tu-hoc",[159,161,287,310,333,357,384],{"title":154,"path":156,"stem":160,"icon":155},"2.tu-hoc\u002Findex",{"title":162,"icon":68,"path":163,"stem":164,"children":165},"Database","\u002Ftu-hoc\u002Fdatabase","2.tu-hoc\u002F1.database\u002Findex",[166,167,197,222,243,248],{"title":162,"path":163,"stem":164,"icon":68},{"title":168,"icon":91,"path":169,"stem":170,"children":171,"page":26},"SQL Server","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server","2.tu-hoc\u002F1.database\u002F2.sql-server",[172,177,182,187,192],{"title":173,"path":174,"stem":175,"icon":176},"1. Giới thiệu và Cài đặt","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F1.gioi-thieu-cai-dat","i-lucide-play-circle",{"title":178,"path":179,"stem":180,"icon":181},"2. Cú pháp cơ bản","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F2.cu-phap-co-ban","i-lucide-code-2",{"title":183,"path":184,"stem":185,"icon":186},"3. Truy vấn nâng cao","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F3.truy-van-nang-cao","i-lucide-git-merge",{"title":188,"path":189,"stem":190,"icon":191},"4. Đặc thù và Performance","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F4.dac-thu-performance","i-lucide-gauge",{"title":193,"path":194,"stem":195,"icon":196},"5. Q và A phỏng vấn","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F5.cau-hoi-phong-van","i-lucide-message-circle-question",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":26},"PostgreSQL","i-simple-icons-postgresql","\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql","2.tu-hoc\u002F1.database\u002F3.postgresql",[203,206,209,212,215,218],{"title":173,"path":204,"stem":205,"icon":176},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F1.gioi-thieu-cai-dat",{"title":178,"path":207,"stem":208,"icon":181},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F2.cu-phap-co-ban",{"title":183,"path":210,"stem":211,"icon":186},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F3.truy-van-nang-cao",{"title":188,"path":213,"stem":214,"icon":191},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F4.dac-thu-performance",{"title":193,"path":216,"stem":217,"icon":196},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F5.cau-hoi-phong-van",{"title":219,"path":220,"stem":221,"icon":96},"6. Tích hợp C# và Postgres","\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Ftich-hop-csharp","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F6.tich-hop-csharp",{"title":223,"icon":224,"path":225,"stem":226,"children":227,"page":26},"MySQL","i-simple-icons-mysql","\u002Ftu-hoc\u002Fdatabase\u002Fmysql","2.tu-hoc\u002F1.database\u002F4.mysql",[228,231,234,237,240],{"title":173,"path":229,"stem":230,"icon":176},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F4.mysql\u002F1.gioi-thieu-cai-dat",{"title":178,"path":232,"stem":233,"icon":181},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F4.mysql\u002F2.cu-phap-co-ban",{"title":183,"path":235,"stem":236,"icon":186},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F4.mysql\u002F3.truy-van-nang-cao",{"title":188,"path":238,"stem":239,"icon":191},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F4.mysql\u002F4.dac-thu-performance",{"title":193,"path":241,"stem":242,"icon":196},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F4.mysql\u002F5.cau-hoi-phong-van",{"title":244,"path":245,"stem":246,"icon":247},"So sánh 3 RDBMS","\u002Ftu-hoc\u002Fdatabase\u002Fso-sanh","2.tu-hoc\u002F1.database\u002F5.so-sanh","i-lucide-columns-3",{"title":249,"path":250,"stem":251,"children":252,"icon":254},"Supabase (BaaS)","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase","2.tu-hoc\u002F1.database\u002F6.supabase\u002Findex",[253,255,259,264,269,274,278,283],{"title":249,"path":250,"stem":251,"icon":254},"i-simple-icons-supabase",{"title":256,"path":257,"stem":258,"icon":68},"1. Database","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fdatabase","2.tu-hoc\u002F1.database\u002F6.supabase\u002F1.database",{"title":260,"path":261,"stem":262,"icon":263},"2. Authentication","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fauthentication","2.tu-hoc\u002F1.database\u002F6.supabase\u002F2.authentication","i-lucide-key",{"title":265,"path":266,"stem":267,"icon":268},"3. Storage & Realtime","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fstorage-realtime","2.tu-hoc\u002F1.database\u002F6.supabase\u002F3.storage-realtime","i-lucide-zap",{"title":270,"path":271,"stem":272,"icon":273},"4. Edge Functions & AI","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Ffunctions-ai","2.tu-hoc\u002F1.database\u002F6.supabase\u002F4.functions-ai","i-lucide-brain",{"title":275,"path":276,"stem":277,"icon":181},"5. API & SDKs","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fapi-sdk","2.tu-hoc\u002F1.database\u002F6.supabase\u002F5.api-sdk",{"title":279,"path":280,"stem":281,"icon":282},"6. Platform & Deploy","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fplatform-deploy","2.tu-hoc\u002F1.database\u002F6.supabase\u002F6.platform-deploy","i-lucide-cloud",{"title":284,"path":285,"stem":286,"icon":196},"7. Interview & Q&A","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Finterview","2.tu-hoc\u002F1.database\u002F6.supabase\u002F7.interview",{"title":288,"icon":289,"path":290,"stem":291,"children":292},"TypeScript","i-simple-icons-typescript","\u002Ftu-hoc\u002Ftypescript","2.tu-hoc\u002F2.typescript\u002Findex",[293,294,297,301,306],{"title":288,"path":290,"stem":291,"icon":289},{"title":173,"path":295,"stem":296,"icon":176},"\u002Ftu-hoc\u002Ftypescript\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F2.typescript\u002F1.gioi-thieu-cai-dat",{"title":298,"path":299,"stem":300,"icon":81},"2. Type System","\u002Ftu-hoc\u002Ftypescript\u002Ftype-system","2.tu-hoc\u002F2.typescript\u002F2.type-system",{"title":302,"path":303,"stem":304,"icon":305},"3. Advanced types","\u002Ftu-hoc\u002Ftypescript\u002Fadvanced-types","2.tu-hoc\u002F2.typescript\u002F3.advanced-types","i-lucide-braces",{"title":307,"path":308,"stem":309,"icon":196},"4. Q và A phỏng vấn","\u002Ftu-hoc\u002Ftypescript\u002Fcau-hoi-phong-van","2.tu-hoc\u002F2.typescript\u002F4.cau-hoi-phong-van",{"title":311,"icon":81,"path":312,"stem":313,"children":314},"OOP","\u002Ftu-hoc\u002Foop","2.tu-hoc\u002F3.oop\u002Findex",[315,316,321,326,330],{"title":311,"path":312,"stem":313,"icon":81},{"title":317,"path":318,"stem":319,"icon":320},"1. Bốn tính chất","\u002Ftu-hoc\u002Foop\u002F4-tinh-chat","2.tu-hoc\u002F3.oop\u002F1.4-tinh-chat","i-lucide-circle-dot",{"title":322,"path":323,"stem":324,"icon":325},"2. SOLID","\u002Ftu-hoc\u002Foop\u002Fsolid","2.tu-hoc\u002F3.oop\u002F2.solid","i-lucide-shield",{"title":327,"path":328,"stem":329,"icon":106},"3. Design Pattern","\u002Ftu-hoc\u002Foop\u002Fdesign-pattern","2.tu-hoc\u002F3.oop\u002F3.design-pattern",{"title":307,"path":331,"stem":332,"icon":196},"\u002Ftu-hoc\u002Foop\u002Fcau-hoi-phong-van","2.tu-hoc\u002F3.oop\u002F4.cau-hoi-phong-van",{"title":334,"icon":305,"path":335,"stem":336,"children":337},"Generic","\u002Ftu-hoc\u002Fgeneric","2.tu-hoc\u002F4.generic\u002Findex",[338,339,344,349,354],{"title":334,"path":335,"stem":336,"icon":305},{"title":340,"path":341,"stem":342,"icon":343},"1. Khái niệm và cú pháp","\u002Ftu-hoc\u002Fgeneric\u002Fkhai-niem","2.tu-hoc\u002F4.generic\u002F1.khai-niem","i-lucide-book",{"title":345,"path":346,"stem":347,"icon":348},"2. Constraint và Variance","\u002Ftu-hoc\u002Fgeneric\u002Fconstraint-variance","2.tu-hoc\u002F4.generic\u002F2.constraint-variance","i-lucide-filter",{"title":350,"path":351,"stem":352,"icon":353},"3. C# vs TS","\u002Ftu-hoc\u002Fgeneric\u002Fso-sanh","2.tu-hoc\u002F4.generic\u002F3.so-sanh","i-lucide-git-compare",{"title":307,"path":355,"stem":356,"icon":196},"\u002Ftu-hoc\u002Fgeneric\u002Fcau-hoi-phong-van","2.tu-hoc\u002F4.generic\u002F4.cau-hoi-phong-van",{"title":358,"icon":359,"path":360,"stem":361,"children":362},"Nuxt 4","i-simple-icons-nuxt","\u002Ftu-hoc\u002Fnuxt-4","2.tu-hoc\u002F5.nuxt-4\u002Findex",[363,364,367,372,376,379],{"title":358,"path":360,"stem":361,"icon":359},{"title":173,"path":365,"stem":366,"icon":176},"\u002Ftu-hoc\u002Fnuxt-4\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F5.nuxt-4\u002F1.gioi-thieu-cai-dat",{"title":368,"path":369,"stem":370,"icon":371},"2. Routing và Rendering","\u002Ftu-hoc\u002Fnuxt-4\u002Frouting-rendering","2.tu-hoc\u002F5.nuxt-4\u002F2.routing-rendering","i-lucide-route",{"title":373,"path":374,"stem":375,"icon":91},"3. Data và Server","\u002Ftu-hoc\u002Fnuxt-4\u002Fdata-server","2.tu-hoc\u002F5.nuxt-4\u002F3.data-server",{"title":307,"path":377,"stem":378,"icon":196},"\u002Ftu-hoc\u002Fnuxt-4\u002Fcau-hoi-phong-van","2.tu-hoc\u002F5.nuxt-4\u002F4.cau-hoi-phong-van",{"title":380,"path":381,"stem":382,"icon":383},"5. Practical Todo App","\u002Ftu-hoc\u002Fnuxt-4\u002Fpractical-todo-app","2.tu-hoc\u002F5.nuxt-4\u002F5.practical-todo-app","i-lucide-check-square",{"title":385,"path":386,"stem":387,"children":388,"icon":390},"Tailwind CSS","\u002Ftu-hoc\u002Ftailwindcss","2.tu-hoc\u002F6.tailwindcss\u002Findex",[389,391,396,401,406,411,416],{"title":385,"path":386,"stem":387,"icon":390},"i-simple-icons-tailwindcss",{"title":392,"path":393,"stem":394,"icon":395},"1. Layout & Spacing","\u002Ftu-hoc\u002Ftailwindcss\u002Flayout-spacing","2.tu-hoc\u002F6.tailwindcss\u002F1.layout-spacing","i-lucide-layout",{"title":397,"path":398,"stem":399,"icon":400},"2. Typography & Colors","\u002Ftu-hoc\u002Ftailwindcss\u002Ftypography-colors","2.tu-hoc\u002F6.tailwindcss\u002F2.typography-colors","i-lucide-type",{"title":402,"path":403,"stem":404,"icon":405},"3. Interactive & Effects","\u002Ftu-hoc\u002Ftailwindcss\u002Finteractive-effects","2.tu-hoc\u002F6.tailwindcss\u002F3.interactive-effects","i-lucide-sparkles",{"title":407,"path":408,"stem":409,"icon":410},"4. Responsive & Dark Mode","\u002Ftu-hoc\u002Ftailwindcss\u002Fresponsive-darkmode","2.tu-hoc\u002F6.tailwindcss\u002F4.responsive-darkmode","i-lucide-monitor-smartphone",{"title":412,"path":413,"stem":414,"icon":415},"5. Customization & Theme","\u002Ftu-hoc\u002Ftailwindcss\u002Fcustomization","2.tu-hoc\u002F6.tailwindcss\u002F5.customization","i-lucide-settings-2",{"title":417,"path":418,"stem":419,"icon":181},"6. Practical Projects","\u002Ftu-hoc\u002Ftailwindcss\u002Fpractical-projects","2.tu-hoc\u002F6.tailwindcss\u002F6.practical-projects",{"id":421,"title":422,"body":423,"description":3552,"extension":3553,"links":3554,"meta":3555,"navigation":3556,"path":241,"seo":3557,"stem":242,"__hash__":3558},"docs\u002F2.tu-hoc\u002F1.database\u002F4.mysql\u002F5.cau-hoi-phong-van.md","Câu hỏi phỏng vấn MySQL",{"type":424,"value":425,"toc":3450},"minimark",[426,431,436,444,467,472,496,500,566,570,584,587,591,600,604,617,621,625,633,640,644,652,662,666,672,676,679,683,694,698,706,713,717,724,728,744,747,751,759,762,766,769,773,777,791,795,798,802,816,820,836,840,846,850,854,862,866,869,873,882,886,892,896,901,909,919,923,939,945,949,953,964,968,974,978,981,985,991,995,1000,1004,1007,1011,1015,1021,1025,1032,1036,1039,1043,1051,1055,1058,1062,1069,1073,1084,1088,1092,1099,1103,1111,1119,1128,1132,1155,1165,1169,1183,1186,1190,1199,1208,1212,1216,1224,1228,1242,1246,1249,1253,1256,1260,1264,1290,1294,1311,1319,1326,1340,1344,1347,1355,1361,1365,1383,1387,1393,1397,1421,1425,1429,1436,1439,1461,1464,1503,1510,1516,1520,1530,1578,1581,1585,1592,1595,1615,1622,1625,1629,1632,1744,1750,1765,1768,1792,1803,1807,1814,1817,1863,1866,1895,1898,1924,1927,1930,1934,1941,1944,1970,1973,2068,2075,2079,2089,2233,2238,2259,2263,2267,2270,2466,2469,2473,2480,2487,2536,2539,2554,2557,2626,2632,2636,2643,2697,2700,2711,2714,2730,2734,2738,2850,2853,2982,2985,2989,3003,3006,3011,3051,3056,3103,3108,3136,3141,3170,3173,3187,3191,3198,3200,3229,3231,3236,3256,3261,3301,3306,3360,3365,3389,3392,3417,3419,3436,3446],[427,428,430],"h2",{"id":429},"a-tổng-quan","A. Tổng quan",[432,433,435],"h3",{"id":434},"_1-mysql-84-và-97-lts-có-gì-mới","1. MySQL 8.4 và 9.7 LTS có gì mới?",[437,438,439,443],"p",{},[440,441,442],"strong",{},"8.4 LTS (2024)",":",[445,446,447,451,458,464],"ul",{},[448,449,450],"li",{},"Hypergraph Optimizer (DPhyp) — JOIN-heavy nhanh 2-5× (Enterprise only).",[448,452,453,457],{},[454,455,456],"code",{},"mysql_native_password"," disabled mặc định.",[448,459,460,463],{},[454,461,462],{},"SOURCE\u002FREPLICA"," terminology thay MASTER\u002FSLAVE.",[448,465,466],{},"MySQL Operator for Kubernetes production-ready.",[437,468,469,443],{},[440,470,471],{},"9.7 LTS (2025)",[445,473,474,481,484,487,490,493],{},[448,475,476,477,480],{},"Hypergraph Optimizer vào ",[440,478,479],{},"Community Edition",".",[448,482,483],{},"PBKDF2 + SHA-512 authentication, downward replication.",[448,485,486],{},"In-database JavaScript, cpuset cgroup support trong InnoDB.",[448,488,489],{},"DML trên JSON Duality Views trong Community.",[448,491,492],{},"Dynamic Data Masking, OpenID Connect native, MySQL REST Service.",[448,494,495],{},"Nhiều tính năng từ Enterprise chuyển xuống Community (xem câu 2).",[432,497,499],{"id":498},"_2-97-lts-có-thêm-gì-chi-tiết","2. 9.7 LTS có thêm gì chi tiết?",[445,501,502,508,518,524,530,536,542,548,554,560],{},[448,503,504,507],{},[440,505,506],{},"Hypergraph Optimizer vào Community",": optimizer DPhyp — JOIN-heavy query 2-5× nhanh hơn, trước chỉ có trong Enterprise.",[448,509,510,513,514,517],{},[440,511,512],{},"PBKDF2 + SHA-512 authentication",": hashing mạnh hơn ",[454,515,516],{},"caching_sha2_password"," — configurable iteration count, chống brute-force và GPU attack hiệu quả hơn.",[448,519,520,523],{},[440,521,522],{},"Downward replication",": replica từ version cao hơn về version thấp hơn (VD: 9.7 → 8.4) — rolling upgrade an toàn hơn, hỗ trợ topology hỗn hợp.",[448,525,526,529],{},[440,527,528],{},"In-database JavaScript",": viết stored procedure\u002Ffunction bằng JavaScript (GraalVM engine) — business logic phức tạp, JSON manipulation không cần SQL\u002FPSM.",[448,531,532,535],{},[440,533,534],{},"DML trên JSON Duality Views trong Community",": INSERT\u002FUPDATE\u002FDELETE qua JSON document view — trước chỉ có trong Enterprise.",[448,537,538,541],{},[440,539,540],{},"cpuset cgroup support trong InnoDB",": bind thread vào CPU core cụ thể — CPU isolation, NUMA-aware, multi-instance MySQL trên cùng máy.",[448,543,544,547],{},[440,545,546],{},"InnoDB FULLTEXT optimization",": cải thiện performance FULLTEXT search.",[448,549,550,553],{},[440,551,552],{},"Dynamic Data Masking",": ẩn dữ liệu nhạy cảm (PII) theo role — trước chỉ Enterprise.",[448,555,556,559],{},[440,557,558],{},"OpenID Connect (OIDC) native",": login qua Google, Azure AD, Okta không cần plugin ngoài.",[448,561,562,565],{},[440,563,564],{},"MySQL REST Service (MRS)",": expose database qua REST API.",[432,567,569],{"id":568},"_3-lts-vs-innovation-release","3. LTS vs Innovation release?",[445,571,572,578],{},[448,573,574,577],{},[440,575,576],{},"LTS",": hỗ trợ 8 năm, fix bug + security.",[448,579,580,583],{},[440,581,582],{},"Innovation",": quý cập nhật feature mới, support ngắn.",[437,585,586],{},"Production → LTS. Dev\u002Ftest → Innovation OK.",[432,588,590],{"id":589},"_4-storage-engine-chọn-cái-nào","4. Storage engine — chọn cái nào?",[437,592,593,596,597],{},[440,594,595],{},"InnoDB"," mặc định. MyISAM legacy, không transaction, không FK, table-level lock. ",[440,598,599],{},"Luôn dùng InnoDB.",[432,601,603],{"id":602},"_5-utf8-vs-utf8mb4","5. utf8 vs utf8mb4?",[437,605,606,609,610,613,614],{},[454,607,608],{},"utf8"," cũ chỉ 3 byte (không emoji, một số ký tự CJK). ",[454,611,612],{},"utf8mb4"," đủ 4 byte chuẩn UTF-8. ",[440,615,616],{},"Luôn dùng utf8mb4.",[427,618,620],{"id":619},"b-kiểu-dữ-liệu","B. Kiểu dữ liệu",[432,622,624],{"id":623},"_6-datetime-vs-timestamp","6. DATETIME vs TIMESTAMP?",[445,626,627,630],{},[448,628,629],{},"DATETIME: 5-8 byte, range 1000-9999, không convert timezone.",[448,631,632],{},"TIMESTAMP: 4-7 byte, range 1970-2038 (Y2038!), convert UTC ↔ session.",[437,634,635,636,639],{},"DATETIME cho ngày sinh, sự kiện. TIMESTAMP cho ",[454,637,638],{},"created_at"," cần timezone aware.",[432,641,643],{"id":642},"_7-varchar-vs-text-trong-mysql","7. VARCHAR vs TEXT trong MySQL?",[445,645,646,649],{},[448,647,648],{},"VARCHAR(n): lưu inline trong row, index full, fast.",[448,650,651],{},"TEXT: lưu out-of-row (con trỏ), index chỉ prefix.",[437,653,654,657,658,661],{},[454,655,656],{},"VARCHAR(n)"," cho data \u003C 1KB. ",[454,659,660],{},"TEXT"," cho bài viết dài.",[432,663,665],{"id":664},"_8-int11-có-giới-hạn-11-chữ-số-không","8. INT(11) có giới hạn 11 chữ số không?",[437,667,668,671],{},[440,669,670],{},"Không."," Đó là \"display width\", không affect storage hay range. INT luôn 4 byte. Deprecated từ 8.0 — bỏ qua.",[432,673,675],{"id":674},"_9-enum-nên-dùng-không","9. ENUM nên dùng không?",[437,677,678],{},"Hữu ích cho giá trị cố định nhỏ (status, type). Trade-off: thay đổi list cần ALTER TABLE (lock). Alternative: lookup table.",[432,680,682],{"id":681},"_10-json-type-index-như-nào","10. JSON type — index như nào?",[437,684,685,686,689,690,693],{},"Qua ",[440,687,688],{},"generated column"," + index trên nó, hoặc ",[440,691,692],{},"functional index"," (8.0.13+) trên expression.",[427,695,697],{"id":696},"c-ddl","C. DDL",[432,699,701,702,705],{"id":700},"_11-auto_increment-khác-serial-postgres-thế-nào","11. AUTO_INCREMENT khác ",[454,703,704],{},"SERIAL"," Postgres thế nào?",[437,707,708,709,712],{},"Tương đương về mục đích. MySQL ",[454,710,711],{},"AUTO_INCREMENT"," chỉ áp được cho 1 cột\u002Fbảng, và cột phải có index.",[432,714,716],{"id":715},"_12-check-constraint-trước-80","12. CHECK constraint trước 8.0?",[437,718,719,720,723],{},"Trước 8.0 MySQL parse CHECK nhưng ",[440,721,722],{},"không enforce"," (chỉ ignore). Từ 8.0 mới enforce thực sự.",[432,725,727],{"id":726},"_13-on-update-current_timestamp","13. ON UPDATE CURRENT_TIMESTAMP?",[729,730,735],"pre",{"className":731,"code":732,"language":733,"meta":734,"style":734},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n","sql","",[454,736,737],{"__ignoreMap":734},[738,739,742],"span",{"class":740,"line":741},"line",1,[738,743,732],{},[437,745,746],{},"Auto-update timestamp khi row UPDATE. Đặc thù MySQL — Postgres\u002FSQL Server cần trigger.",[432,748,750],{"id":749},"_14-generated-column-virtual-vs-stored","14. Generated column VIRTUAL vs STORED?",[445,752,753,756],{},[448,754,755],{},"VIRTUAL: tính khi đọc, không tốn space.",[448,757,758],{},"STORED: lưu vật lý, index trực tiếp tốt.",[437,760,761],{},"Index trên VIRTUAL được nhưng phải re-evaluate expression mỗi lần — STORED nhanh hơn.",[432,763,765],{"id":764},"_15-invisible-index","15. Invisible index?",[437,767,768],{},"Index tồn tại nhưng optimizer không dùng. Dùng để test trước khi DROP — đỡ overhead drop\u002Frecreate.",[427,770,772],{"id":771},"d-dml","D. DML",[432,774,776],{"id":775},"_16-upsert-trong-mysql","16. UPSERT trong MySQL?",[437,778,779,782,783,786,787,790],{},[454,780,781],{},"INSERT ... ON DUPLICATE KEY UPDATE",". Hoặc ",[454,784,785],{},"REPLACE INTO"," (= DELETE + INSERT, ",[440,788,789],{},"không khuyến nghị"," vì xoá row gốc).",[432,792,794],{"id":793},"_17-insert-ignore-làm-gì","17. INSERT IGNORE làm gì?",[437,796,797],{},"Skip row vi phạm UNIQUE constraint thay vì error. Có thể giấu lỗi khác — dùng cẩn thận.",[432,799,801],{"id":800},"_18-last_insert_id-vs-last_insert_idvalue","18. LAST_INSERT_ID() vs LAST_INSERT_ID(value)?",[445,803,804,810],{},[448,805,806,809],{},[454,807,808],{},"LAST_INSERT_ID()",": return ID vừa insert (per-connection).",[448,811,812,815],{},[454,813,814],{},"LAST_INSERT_ID(value)",": set + return giá trị (trick để return value từ UPDATE).",[432,817,819],{"id":818},"_19-updatedelete-từ-join-cú-pháp","19. UPDATE\u002FDELETE từ JOIN — cú pháp?",[729,821,823],{"className":731,"code":822,"language":733,"meta":734,"style":734},"UPDATE a JOIN b ON ... SET a.col = b.col;\nDELETE a FROM a JOIN b ON ... WHERE ...;\n",[454,824,825,830],{"__ignoreMap":734},[738,826,827],{"class":740,"line":741},[738,828,829],{},"UPDATE a JOIN b ON ... SET a.col = b.col;\n",[738,831,833],{"class":740,"line":832},2,[738,834,835],{},"DELETE a FROM a JOIN b ON ... WHERE ...;\n",[432,837,839],{"id":838},"_20-truncate-có-cascade-không","20. TRUNCATE có CASCADE không?",[437,841,842,845],{},[440,843,844],{},"Không như Postgres."," MySQL TRUNCATE không trigger CASCADE và bị block nếu có FK reference.",[427,847,849],{"id":848},"e-join-query","E. JOIN & query",[432,851,853],{"id":852},"_21-mysql-có-full-outer-join-không","21. MySQL có FULL OUTER JOIN không?",[437,855,856,858,859,480],{},[440,857,670],{}," Phải mô phỏng bằng ",[454,860,861],{},"LEFT JOIN UNION RIGHT JOIN",[432,863,865],{"id":864},"_22-straight_join-dùng-làm-gì","22. STRAIGHT_JOIN dùng làm gì?",[437,867,868],{},"Ép optimizer giữ thứ tự JOIN theo cách viết, không reorder.",[432,870,872],{"id":871},"_23-derived-table-có-cần-alias","23. Derived table có cần alias?",[437,874,875,878,879,480],{},[440,876,877],{},"Có."," MySQL bắt buộc. ",[454,880,881],{},"SELECT * FROM (SELECT ...) AS t",[432,883,885],{"id":884},"_24-cte-từ-version-nào","24. CTE từ version nào?",[437,887,888,891],{},[440,889,890],{},"8.0+",". Trước phải nested subquery (xấu xí).",[432,893,895],{"id":894},"_25-window-function-từ-version-nào","25. Window function từ version nào?",[437,897,898,900],{},[440,899,890],{},". Trước phải user variable trick — bug-prone.",[432,902,904,905,908],{"id":903},"_26-null-safe-equal","26. NULL-safe equal (",[454,906,907],{},"\u003C=>",")?",[437,910,911,914,915,918],{},[454,912,913],{},"a \u003C=> b"," trả TRUE nếu cả 2 NULL. Khác ",[454,916,917],{},"="," (NULL = NULL → NULL\u002FUNKNOWN).",[432,920,922],{"id":921},"_27-regexp-vs-like","27. REGEXP vs LIKE?",[445,924,925,936],{},[448,926,927,928,931,932,935],{},"LIKE: wildcard ",[454,929,930],{},"%",", ",[454,933,934],{},"_",". Đơn giản.",[448,937,938],{},"REGEXP \u002F RLIKE: regex Perl-like.",[437,940,941,942,480],{},"REGEXP chậm hơn, không dùng index trừ khi anchor ",[454,943,944],{},"^",[427,946,948],{"id":947},"f-index","F. Index",[432,950,952],{"id":951},"_28-innodb-secondary-index-chứa-gì-ở-leaf","28. InnoDB secondary index — chứa gì ở leaf?",[437,954,955,956,959,960,963],{},"Chứa ",[440,957,958],{},"secondary key + primary key value"," (chứ không phải row pointer). Hệ quả: query qua secondary → lookup PK → row. Đó là vì sao ",[440,961,962],{},"PK nên nhỏ"," (BIGINT thay vì UUID dài).",[432,965,967],{"id":966},"_29-composite-index-left-most-prefix","29. Composite index left-most prefix?",[437,969,970,973],{},[454,971,972],{},"INDEX(A, B, C)"," dùng cho WHERE A, A+B, A+B+C. Không dùng cho B mình hoặc B+C.",[432,975,977],{"id":976},"_30-covering-index","30. Covering index?",[437,979,980],{},"Index chứa đủ cột query cần — engine không cần lookup PK\u002Frow. Quan trọng đặc biệt với InnoDB vì cấu trúc secondary index.",[432,982,984],{"id":983},"_31-functional-index-từ-version-nào","31. Functional index từ version nào?",[437,986,987,990],{},[440,988,989],{},"8.0.13+",". Cho phép index trên expression. Trước phải tạo generated column.",[432,992,994],{"id":993},"_32-descending-index","32. Descending index?",[437,996,997,999],{},[440,998,890],{}," — index lưu DESC. Query ORDER BY DESC dùng index thẳng, tránh SORT.",[432,1001,1003],{"id":1002},"_33-khi-nào-không-nên-tạo-index","33. Khi nào KHÔNG nên tạo index?",[437,1005,1006],{},"Bảng nhỏ, cột thay đổi nhiều, selectivity thấp, bảng heavy write.",[427,1008,1010],{"id":1009},"g-transaction-locking","G. Transaction & Locking",[432,1012,1014],{"id":1013},"_34-default-isolation-mysql","34. Default isolation MySQL?",[437,1016,1017,1020],{},[440,1018,1019],{},"REPEATABLE READ"," — cao hơn SQL Server \u002F Postgres (cả 2 mặc định READ COMMITTED). Chọn vậy do replication: statement-based binlog cần consistent read.",[432,1022,1024],{"id":1023},"_35-gap-lock-là-gì","35. Gap lock là gì?",[437,1026,1027,1028,1031],{},"InnoDB ở REPEATABLE READ lock cả ",[440,1029,1030],{},"khoảng giữa các index value",", ngăn INSERT phantom. Hiệu ứng phụ: dễ deadlock hơn.",[432,1033,1035],{"id":1034},"_36-next-key-lock","36. Next-key lock?",[437,1037,1038],{},"Combination của record lock + gap lock — lock cả row và gap trước nó.",[432,1040,1042],{"id":1041},"_37-select-for-update-vs-for-share","37. SELECT FOR UPDATE vs FOR SHARE?",[445,1044,1045,1048],{},[448,1046,1047],{},"FOR UPDATE: exclusive lock, chặn UPDATE + FOR UPDATE khác.",[448,1049,1050],{},"FOR SHARE (LOCK IN SHARE MODE cũ): shared lock, cho FOR SHARE khác đọc, chặn UPDATE.",[432,1052,1054],{"id":1053},"_38-deadlock-innodb-xử-lý","38. Deadlock — InnoDB xử lý?",[437,1056,1057],{},"Tự detect, rollback transaction có ít work nhất. App phải retry. Tránh: lock cùng thứ tự, transaction ngắn.",[432,1059,1061],{"id":1060},"_39-auto-commit","39. Auto-commit?",[437,1063,1064,1065,1068],{},"Mặc định ON — mỗi statement = 1 transaction. ",[454,1066,1067],{},"SET AUTOCOMMIT = 0"," để control thủ công.",[432,1070,1072],{"id":1071},"_40-phantom-read-trong-mysql-repeatable-read","40. Phantom read trong MySQL REPEATABLE READ?",[437,1074,1075,1076,1079,1080,1083],{},"Lý thuyết: REPEATABLE READ vẫn cho phantom. Thực tế: InnoDB ",[440,1077,1078],{},"dùng gap lock"," trong RR → ",[440,1081,1082],{},"ngăn phantom",". → MySQL RR ≈ Postgres RR ≈ Serializable phần phantom.",[427,1085,1087],{"id":1086},"h-performance","H. Performance",[432,1089,1091],{"id":1090},"_41-buffer-pool-là-gì","41. Buffer Pool là gì?",[437,1093,1094,1095,1098],{},"Vùng RAM InnoDB cache page (data + index). Tham số ",[454,1096,1097],{},"innodb_buffer_pool_size"," — quan trọng nhất, set 50-70% RAM.",[432,1100,1102],{"id":1101},"_42-redo-log-undo-log","42. Redo log + Undo log?",[445,1104,1105,1108],{},[448,1106,1107],{},"Redo log: ghi mọi thay đổi trước khi flush data → crash recovery.",[448,1109,1110],{},"Undo log: lưu version cũ cho MVCC + ROLLBACK.",[432,1112,1114,1115,1118],{"id":1113},"_43-explain-type-cột-nào-quan-trọng","43. EXPLAIN — ",[454,1116,1117],{},"type"," cột nào quan trọng?",[437,1120,1121,1123,1124,1127],{},[454,1122,1117],{}," cho thấy access pattern. Order tốt → tệ: system > const > eq_ref > ref > range > index > ",[440,1125,1126],{},"ALL"," (full scan, đáng sợ).",[432,1129,1131],{"id":1130},"_44-slow-query-log-cách-bật","44. Slow query log — cách bật?",[729,1133,1137],{"className":1134,"code":1135,"language":1136,"meta":734,"style":734},"language-ini shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","slow_query_log = 1\nlong_query_time = 1\nlog_queries_not_using_indexes = 1\n","ini",[454,1138,1139,1144,1149],{"__ignoreMap":734},[738,1140,1141],{"class":740,"line":741},[738,1142,1143],{},"slow_query_log = 1\n",[738,1145,1146],{"class":740,"line":832},[738,1147,1148],{},"long_query_time = 1\n",[738,1150,1152],{"class":740,"line":1151},3,[738,1153,1154],{},"log_queries_not_using_indexes = 1\n",[437,1156,1157,1158,1161,1162,480],{},"Phân tích bằng ",[454,1159,1160],{},"mysqldumpslow"," hoặc ",[454,1163,1164],{},"pt-query-digest",[432,1166,1168],{"id":1167},"_45-hypergraph-optimizer","45. Hypergraph Optimizer?",[437,1170,1171,1172,1175,1176,1179,1180,480],{},"Optimizer mới dùng DPhyp algorithm — JOIN-heavy analytics 2-5× faster. Từ 8.4 chỉ có ",[440,1173,1174],{},"Enterprise",", từ ",[440,1177,1178],{},"9.7 đã có trong Community",". Bật qua ",[454,1181,1182],{},"optimizer_switch='hypergraph_optimizer=on'",[437,1184,1185],{},"Xem chi tiết tại câu 58.",[432,1187,1189],{"id":1188},"_46-pagination-với-offset-lớn-chậm","46. Pagination với OFFSET lớn chậm?",[437,1191,1192,1195,1196,443],{},[454,1193,1194],{},"LIMIT 1000000, 10"," phải scan + skip 1M row. Fix bằng ",[440,1197,1198],{},"keyset pagination",[729,1200,1202],{"className":731,"code":1201,"language":733,"meta":734,"style":734},"SELECT * FROM orders WHERE id > @last_id ORDER BY id LIMIT 10;\n",[454,1203,1204],{"__ignoreMap":734},[738,1205,1206],{"class":740,"line":741},[738,1207,1201],{},[427,1209,1211],{"id":1210},"i-replication-ha","I. Replication & HA",[432,1213,1215],{"id":1214},"_47-source-replica-replication-async-vs-semi-sync","47. Source-Replica replication async vs semi-sync?",[445,1217,1218,1221],{},[448,1219,1220],{},"Async (default): source commit ngay, không chờ → có thể mất data nếu source chết.",[448,1222,1223],{},"Semi-sync: chờ ít nhất 1 replica ack.",[432,1225,1227],{"id":1226},"_48-binlog-format-row-vs-statement-vs-mixed","48. Binlog format ROW vs STATEMENT vs MIXED?",[445,1229,1230,1236,1239],{},[448,1231,1232,1233],{},"ROW: log từng row thay đổi. Safest, lớn nhất. ",[440,1234,1235],{},"Khuyến nghị.",[448,1237,1238],{},"STATEMENT: log statement. Nhỏ nhưng nondeterministic statement (RAND, NOW) bug.",[448,1240,1241],{},"MIXED: tự chọn.",[432,1243,1245],{"id":1244},"_49-group-replication-innodb-cluster","49. Group Replication \u002F InnoDB Cluster?",[437,1247,1248],{},"Multi-master synchronous, dùng Paxos. Auto-failover. Phức tạp hơn nhưng HA tốt hơn.",[432,1250,1252],{"id":1251},"_50-read-after-write-consistency-với-read-replica","50. Read-after-write consistency với read replica?",[437,1254,1255],{},"Replica có lag → read ngay sau write có thể stale. Fix: route critical read về source, hoặc dùng semi-sync, hoặc proxy như ProxySQL có read consistency hint.",[427,1257,1259],{"id":1258},"j-trick-scenario","J. Trick & scenario",[432,1261,1263],{"id":1262},"_51-bảng-100m-row-query-slow-bước-đầu-tiên","51. Bảng 100M row, query slow. Bước đầu tiên?",[437,1265,1266,1267,1269,1270,1273,1274,1277,1278,1281,1282,1285,1286,1289],{},"EXPLAIN xem type. Tìm ",[454,1268,1126],{}," → thiếu index. Check ",[454,1271,1272],{},"key"," — index nào đang dùng? ",[454,1275,1276],{},"rows"," — estimate. Sau đó check ",[454,1279,1280],{},"Extra",": ",[454,1283,1284],{},"Using filesort"," \u002F ",[454,1287,1288],{},"Using temporary"," đáng ngờ.",[432,1291,1293],{"id":1292},"_52-alter-table-bảng-lớn-không-downtime","52. ALTER TABLE bảng lớn không downtime?",[445,1295,1296,1299,1305],{},[448,1297,1298],{},"Online DDL (ALGORITHM=INPLACE, LOCK=NONE) cho operation support.",[448,1300,1301,1304],{},[454,1302,1303],{},"pt-online-schema-change"," (Percona Toolkit) — tạo bảng mới, copy data, swap.",[448,1306,1307,1310],{},[454,1308,1309],{},"gh-ost"," (GitHub) — không trigger, ít load hơn.",[432,1312,1314,1315,1318],{"id":1313},"_53-bảng-innodb-to-nhưng-select-count-chậm","53. Bảng InnoDB to nhưng ",[454,1316,1317],{},"SELECT COUNT(*)"," chậm?",[437,1320,1321,1322,1325],{},"InnoDB không cache count chính xác (do MVCC). Mỗi ",[454,1323,1324],{},"COUNT(*)"," phải scan. Cách:",[445,1327,1328,1331,1334],{},[448,1329,1330],{},"Cache count trong app\u002FRedis.",[448,1332,1333],{},"Counter table riêng + trigger.",[448,1335,1336,1339],{},[454,1337,1338],{},"information_schema.tables.TABLE_ROWS"," (estimate, không chính xác).",[432,1341,1343],{"id":1342},"_54-pk-là-uuid-có-sao-không","54. PK là UUID — có sao không?",[437,1345,1346],{},"InnoDB tệ cho UUIDv4 random:",[445,1348,1349,1352],{},[448,1350,1351],{},"Insert vào B-tree random → page split nhiều.",[448,1353,1354],{},"Mọi secondary index chứa UUID dài → index phình to.",[437,1356,1357,1360],{},[440,1358,1359],{},"Khuyến nghị:"," UUIDv7 (sortable), hoặc BIGINT AUTO_INCREMENT + UUID là column phụ.",[432,1362,1364],{"id":1363},"_55-replication-lag-tăng-debug","55. Replication lag tăng — debug?",[445,1366,1367,1377,1380],{},[448,1368,1369,1370,1373,1374,480],{},"Check ",[454,1371,1372],{},"SHOW REPLICA STATUS\\G"," — ",[454,1375,1376],{},"Seconds_Behind_Source",[448,1378,1379],{},"Replica single-threaded apply mặc định → cấu hình parallel applier.",[448,1381,1382],{},"Long transaction trên source → tách nhỏ.",[432,1384,1386],{"id":1385},"_56-connection-pool-bao-nhiêu-là-vừa","56. Connection pool — bao nhiêu là vừa?",[437,1388,1389,1392],{},[454,1390,1391],{},"max_connections"," default 151. Mỗi connection ~256KB RAM. App pool size = (cpu_count × 2) + effective_spindle_count thường đủ. Hơn nữa → tốn RAM, contention.",[432,1394,1396],{"id":1395},"_57-bảo-mật-checklist","57. Bảo mật — checklist?",[445,1398,1399,1404,1407,1410,1413,1416],{},[448,1400,1401,480],{},[454,1402,1403],{},"mysql_secure_installation",[448,1405,1406],{},"Không expose port 3306 ra internet.",[448,1408,1409],{},"User ít quyền nhất.",[448,1411,1412],{},"TLS cho connection.",[448,1414,1415],{},"Audit log cho production.",[448,1417,1418,1420],{},[454,1419,516],{}," (8.0+ default) — không revert về native.",[427,1422,1424],{"id":1423},"k-mysql-97-lts-tính-năng-mới","K. MySQL 9.7 LTS — Tính năng mới",[432,1426,1428],{"id":1427},"_58-hypergraph-optimizer-là-gì-làm-sao-bật-khác-optimizer-cũ-ra-sao","58. Hypergraph Optimizer là gì? Làm sao bật? Khác optimizer cũ ra sao?",[437,1430,1431,1432,1435],{},"Hypergraph Optimizer là optimizer mới của MySQL, dùng thuật toán ",[440,1433,1434],{},"DPhyp (Dynamic Programming Hypergraph)"," thay cho thuật toán greedy truyền thống.",[437,1437,1438],{},"Khác biệt chính:",[445,1440,1441,1451],{},[448,1442,1443,1446,1447,1450],{},[440,1444,1445],{},"Optimizer cũ",": tìm kiếm greedy, chỉ sinh ",[440,1448,1449],{},"left-deep join tree",". Nhanh với query đơn giản nhưng dễ bỏ lỡ join order tối ưu cho query phức tạp (>4 bảng).",[448,1452,1453,1456,1457,1460],{},[440,1454,1455],{},"Hypergraph",": exhaustive DP search, hỗ trợ ",[440,1458,1459],{},"bushy join tree",". Tìm được join order tối ưu cho JOIN-heavy query, đặc biệt analytical workload.",[437,1462,1463],{},"Cách bật:",[729,1465,1467],{"className":731,"code":1466,"language":733,"meta":734,"style":734},"-- Per-session\nSET optimizer_switch='hypergraph_optimizer=on';\n\n-- Hint per-query\nSELECT \u002F*+ SET_VAR(optimizer_switch='hypergraph_optimizer=on') *\u002F ...\nFROM a JOIN b JOIN c JOIN d ...;\n",[454,1468,1469,1474,1479,1485,1491,1497],{"__ignoreMap":734},[738,1470,1471],{"class":740,"line":741},[738,1472,1473],{},"-- Per-session\n",[738,1475,1476],{"class":740,"line":832},[738,1477,1478],{},"SET optimizer_switch='hypergraph_optimizer=on';\n",[738,1480,1481],{"class":740,"line":1151},[738,1482,1484],{"emptyLinePlaceholder":1483},true,"\n",[738,1486,1488],{"class":740,"line":1487},4,[738,1489,1490],{},"-- Hint per-query\n",[738,1492,1494],{"class":740,"line":1493},5,[738,1495,1496],{},"SELECT \u002F*+ SET_VAR(optimizer_switch='hypergraph_optimizer=on') *\u002F ...\n",[738,1498,1500],{"class":740,"line":1499},6,[738,1501,1502],{},"FROM a JOIN b JOIN c JOIN d ...;\n",[437,1504,1505,1506,1509],{},"Performance: JOIN-heavy query 2-5x nhanh hơn, nhưng ",[440,1507,1508],{},"compile time dài hơn"," (search space lớn hơn). Query đơn giản không thấy khác biệt — không nên bật global cho OLTP.",[437,1511,1512,1513,480],{},"Lưu ý: Từ 8.4 chỉ có Enterprise, từ ",[440,1514,1515],{},"9.7 đã có trong Community Edition",[432,1517,1519],{"id":1518},"_59-mysql-97-community-được-thêm-những-tính-năng-gì-từ-enterprise","59. MySQL 9.7 Community được thêm những tính năng gì từ Enterprise?",[437,1521,1522,1523,1526,1527,443],{},"Từ 9.7 LTS, Oracle chuyển nhiều tính năng từ ",[440,1524,1525],{},"Enterprise Edition"," sang ",[440,1528,1529],{},"Community Edition miễn phí",[445,1531,1532,1538,1543,1548,1553,1558,1564,1572],{},[448,1533,1534,1537],{},[440,1535,1536],{},"Hypergraph Optimizer",": optimizer mới dùng DPhyp — JOIN-heavy query 2-5x nhanh hơn.",[448,1539,1540,1542],{},[440,1541,552],{},": ẩn dữ liệu nhạy cảm (PII) theo role mà không cần thay đổi application code.",[448,1544,1545,1547],{},[440,1546,564],{},": expose database schema qua REST API tự động.",[448,1549,1550,559],{},[440,1551,1552],{},"OpenID Connect (OIDC) authentication",[448,1554,1555,1557],{},[440,1556,528],{},": viết stored procedure\u002Ffunction bằng JavaScript (GraalVM).",[448,1559,1560,1563],{},[440,1561,1562],{},"DML trên JSON Duality Views",": INSERT\u002FUPDATE\u002FDELETE qua JSON document view — full document-model API.",[448,1565,1566,1569,1570,480],{},[440,1567,1568],{},"PBKDF2 + SHA-512 authentication plugin",": password hashing mạnh hơn ",[454,1571,516],{},[448,1573,1574,1577],{},[440,1575,1576],{},"Downward Replication",": replica từ version cao xuống version thấp.",[437,1579,1580],{},"Đây là chiến lược lớn của Oracle — đưa MySQL Community cạnh tranh trực tiếp với PostgreSQL về mặt tính năng miễn phí.",[432,1582,1584],{"id":1583},"_60-downward-replication-trong-mysql-97-là-gì","60. Downward replication trong MySQL 9.7 là gì?",[437,1586,1587,1588,1591],{},"Downward replication cho phép ",[440,1589,1590],{},"replica từ MySQL version cao hơn về version thấp hơn"," — ví dụ source 9.7 → replica 8.4.",[437,1593,1594],{},"Trước 9.7, replication chỉ hoạt động cùng version hoặc upward (cũ → mới). Downward replication giải quyết các scenario thực tế:",[445,1596,1597,1603,1609],{},[448,1598,1599,1602],{},[440,1600,1601],{},"Rolling upgrade an toàn",": upgrade replica lên version mới trước, nếu có vấn đề vẫn replicating từ source cũ về — không downtime.",[448,1604,1605,1608],{},[440,1606,1607],{},"Topology hỗn hợp",": source chạy Innovation release (feature mới nhất), replica chạy LTS cũ hơn cho ổn định production.",[448,1610,1611,1614],{},[440,1612,1613],{},"Migration dần",": chuyển từng phần hệ thống lên version mới, không cần big-bang upgrade.",[437,1616,1617,1618,1621],{},"Cơ chế: bắt buộc ",[454,1619,1620],{},"binlog_format=ROW",". Replica hiểu các event từ source qua row-based format — statement-based không dùng được vì syntax khác version.",[437,1623,1624],{},"Hạn chế: Không replicate nếu source dùng feature không tồn tại ở version cũ (VD: JavaScript stored procedure từ 9.7 → 8.4 sẽ lỗi).",[432,1626,1628],{"id":1627},"_61-pbkdf2-sha-512-authentication-có-gì-hơn-caching_sha2_password","61. PBKDF2 + SHA-512 authentication có gì hơn caching_sha2_password?",[437,1630,1631],{},"So sánh hai plugin authentication:",[1633,1634,1635,1649],"table",{},[1636,1637,1638],"thead",{},[1639,1640,1641,1644,1646],"tr",{},[1642,1643],"th",{},[1642,1645,516],{},[1642,1647,1648],{},"PBKDF2 + SHA-512",[1650,1651,1652,1666,1679,1692,1705,1718,1731],"tbody",{},[1639,1653,1654,1660,1663],{},[1655,1656,1657],"td",{},[440,1658,1659],{},"Default từ",[1655,1661,1662],{},"MySQL 8.0",[1655,1664,1665],{},"MySQL 9.7",[1639,1667,1668,1673,1676],{},[1655,1669,1670],{},[440,1671,1672],{},"Hash algorithm",[1655,1674,1675],{},"SHA-256 (2 rounds)",[1655,1677,1678],{},"PBKDF2 với SHA-512",[1639,1680,1681,1686,1689],{},[1655,1682,1683],{},[440,1684,1685],{},"Iterations",[1655,1687,1688],{},"5000 rounds cố định",[1655,1690,1691],{},"Configurable (mặc định 10000)",[1639,1693,1694,1699,1702],{},[1655,1695,1696],{},[440,1697,1698],{},"Output length",[1655,1700,1701],{},"256-bit",[1655,1703,1704],{},"512-bit",[1639,1706,1707,1712,1715],{},[1655,1708,1709],{},[440,1710,1711],{},"Chống brute-force",[1655,1713,1714],{},"Tốt",[1655,1716,1717],{},"Tốt hơn (nhiều iteration × SHA-512)",[1639,1719,1720,1725,1728],{},[1655,1721,1722],{},[440,1723,1724],{},"Chống GPU\u002FASIC",[1655,1726,1727],{},"Trung bình",[1655,1729,1730],{},"Tốt (memory-hard hơn)",[1639,1732,1733,1738,1741],{},[1655,1734,1735],{},[440,1736,1737],{},"Caching",[1655,1739,1740],{},"Có cache session",[1655,1742,1743],{},"Không cache (luôn verify)",[437,1745,1746,1749],{},[440,1747,1748],{},"PBKDF2"," (Password-Based Key Derivation Function 2 — chuẩn NIST) tốt hơn vì:",[445,1751,1752,1759,1762],{},[448,1753,1754,1755,1758],{},"Mỗi iteration ",[440,1756,1757],{},"nhân chi phí cho attacker"," — 10000 vòng SHA-512 nghĩa là attacker cần GPU\u002FASIC mạnh gấp nhiều lần để crack.",[448,1760,1761],{},"SHA-512 output dài hơn → collision resistance tốt hơn SHA-256.",[448,1763,1764],{},"Có thể tăng iteration count theo thời gian (Moore's law).",[437,1766,1767],{},"Cấu hình:",[729,1769,1771],{"className":731,"code":1770,"language":733,"meta":734,"style":734},"CREATE USER 'app_user'@'%' IDENTIFIED WITH authentication_pbkdf2 BY 'strong-password';\n\n-- Tăng iteration count cho high-security system\nSET GLOBAL authentication_pbkdf2_iterations = 20000;\n",[454,1772,1773,1778,1782,1787],{"__ignoreMap":734},[738,1774,1775],{"class":740,"line":741},[738,1776,1777],{},"CREATE USER 'app_user'@'%' IDENTIFIED WITH authentication_pbkdf2 BY 'strong-password';\n",[738,1779,1780],{"class":740,"line":832},[738,1781,1484],{"emptyLinePlaceholder":1483},[738,1783,1784],{"class":740,"line":1151},[738,1785,1786],{},"-- Tăng iteration count cho high-security system\n",[738,1788,1789],{"class":740,"line":1487},[738,1790,1791],{},"SET GLOBAL authentication_pbkdf2_iterations = 20000;\n",[437,1793,1794,1795,1797,1798,480],{},"Khuyến nghị: Dùng PBKDF2 cho application user cần high security (admin, finance). ",[454,1796,516],{}," vẫn đủ dùng cho hầu hết web app thông thường — nhưng ",[440,1799,1800,1801],{},"không revert về ",[454,1802,456],{},[432,1804,1806],{"id":1805},"_62-in-database-javascript-trong-mysql-97-dùng-làm-gì","62. In-database JavaScript trong MySQL 9.7 dùng làm gì?",[437,1808,1809,1810,1813],{},"MySQL 9.7 tích hợp ",[440,1811,1812],{},"GraalVM JavaScript engine",", cho phép viết stored program bằng JavaScript thay vì SQL\u002FPSM truyền thống.",[437,1815,1816],{},"Cú pháp:",[729,1818,1820],{"className":731,"code":1819,"language":733,"meta":734,"style":734},"CREATE FUNCTION calculate_discount(price DECIMAL(10,2), tier VARCHAR(20))\nRETURNS DECIMAL(10,2) LANGUAGE JAVASCRIPT AS $$\n  const rates = { bronze: 0.05, silver: 0.10, gold: 0.15 };\n  const rate = rates[tier.toLowerCase()] || 0;\n  return price * (1 - rate);\n$$;\n\nSELECT calculate_discount(100, 'gold'); -- 85.00\n",[454,1821,1822,1827,1832,1837,1842,1847,1852,1857],{"__ignoreMap":734},[738,1823,1824],{"class":740,"line":741},[738,1825,1826],{},"CREATE FUNCTION calculate_discount(price DECIMAL(10,2), tier VARCHAR(20))\n",[738,1828,1829],{"class":740,"line":832},[738,1830,1831],{},"RETURNS DECIMAL(10,2) LANGUAGE JAVASCRIPT AS $$\n",[738,1833,1834],{"class":740,"line":1151},[738,1835,1836],{},"  const rates = { bronze: 0.05, silver: 0.10, gold: 0.15 };\n",[738,1838,1839],{"class":740,"line":1487},[738,1840,1841],{},"  const rate = rates[tier.toLowerCase()] || 0;\n",[738,1843,1844],{"class":740,"line":1493},[738,1845,1846],{},"  return price * (1 - rate);\n",[738,1848,1849],{"class":740,"line":1499},[738,1850,1851],{},"$$;\n",[738,1853,1855],{"class":740,"line":1854},7,[738,1856,1484],{"emptyLinePlaceholder":1483},[738,1858,1860],{"class":740,"line":1859},8,[738,1861,1862],{},"SELECT calculate_discount(100, 'gold'); -- 85.00\n",[437,1864,1865],{},"Stored procedure với JavaScript:",[729,1867,1869],{"className":731,"code":1868,"language":733,"meta":734,"style":734},"CREATE PROCEDURE classify_customers()\nLANGUAGE JAVASCRIPT AS $$\n  \u002F\u002F Logic phân loại khách hàng dựa trên lịch sử mua hàng\n  \u002F\u002F Access SQL data thông qua built-in API\n$$;\n",[454,1870,1871,1876,1881,1886,1891],{"__ignoreMap":734},[738,1872,1873],{"class":740,"line":741},[738,1874,1875],{},"CREATE PROCEDURE classify_customers()\n",[738,1877,1878],{"class":740,"line":832},[738,1879,1880],{},"LANGUAGE JAVASCRIPT AS $$\n",[738,1882,1883],{"class":740,"line":1151},[738,1884,1885],{},"  \u002F\u002F Logic phân loại khách hàng dựa trên lịch sử mua hàng\n",[738,1887,1888],{"class":740,"line":1487},[738,1889,1890],{},"  \u002F\u002F Access SQL data thông qua built-in API\n",[738,1892,1893],{"class":740,"line":1493},[738,1894,1851],{},[437,1896,1897],{},"Use case thực tế:",[445,1899,1900,1906,1912,1918],{},[448,1901,1902,1905],{},[440,1903,1904],{},"Business logic phức tạp",": tính thuế theo vùng, chiết khấu theo bậc, phân hạng khách hàng — logic dạng cây\u002Fđồ thị khó viết bằng SQL.",[448,1907,1908,1911],{},[440,1909,1910],{},"JSON manipulation",": parse, transform, validate JSON document ngay trong DB — tận dụng native JSON của JS.",[448,1913,1914,1917],{},[440,1915,1916],{},"Data validation",": validate format email, số điện thoại, mã số thuế theo regex phức tạp.",[448,1919,1920,1923],{},[440,1921,1922],{},"Custom aggregation",": logic tổng hợp không có sẵn trong SQL (VD: median, percentile phức tạp).",[437,1925,1926],{},"Lợi ích: Developer dùng JS không cần học SQL\u002FPSM. Tận dụng ecosystem JS cho data processing.",[437,1928,1929],{},"Hạn chế: Không hỗ trợ chạy SQL query từ bên trong JS code — chỉ compute logic trên tham số. Overhead khởi tạo GraalVM context (có cache nhưng lần đầu chậm hơn SQL function).",[432,1931,1933],{"id":1932},"_63-cpuset-cgroup-support-trong-innodb-có-ý-nghĩa-gì","63. cpuset cgroup support trong InnoDB có ý nghĩa gì?",[437,1935,1936,1937,1940],{},"cpuset cgroup cho phép ",[440,1938,1939],{},"bind InnoDB thread vào CPU core cụ thể"," — quan trọng trong môi trường container, VM, hoặc multi-tenant.",[437,1942,1943],{},"Ý nghĩa thực tế:",[445,1945,1946,1952,1958,1964],{},[448,1947,1948,1951],{},[440,1949,1950],{},"CPU isolation",": InnoDB thread không bị OS scheduler đẩy sang core khác → giảm cache miss, context switch.",[448,1953,1954,1957],{},[440,1955,1956],{},"NUMA-aware",": trên server multi-socket, bind thread vào core cùng socket với RAM → giảm latency remote memory access đến 40-60%.",[448,1959,1960,1963],{},[440,1961,1962],{},"Predictable performance",": trong container share CPU, đảm bảo MySQL không bị noisy neighbor ảnh hưởng.",[448,1965,1966,1969],{},[440,1967,1968],{},"Multi-instance MySQL",": chạy nhiều instance trên cùng máy, mỗi instance bind vào core riêng → không đụng độ CPU.",[437,1971,1972],{},"Cấu hình (Linux):",[729,1974,1978],{"className":1975,"code":1976,"language":1977,"meta":734,"style":734},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Tạo cgroup với CPU 0-7 cho MySQL\ncgcreate -g cpuset:\u002Fmysql\necho \"0-7\" > \u002Fsys\u002Ffs\u002Fcgroup\u002Fcpuset\u002Fmysql\u002Fcpuset.cpus\necho \"0\" > \u002Fsys\u002Ffs\u002Fcgroup\u002Fcpuset\u002Fmysql\u002Fcpuset.mems\n\n# Gán MySQL process vào cgroup\ncgclassify -g cpuset:\u002Fmysql $(pidof mysqld)\n","bash",[454,1979,1980,1986,1999,2021,2037,2041,2046],{"__ignoreMap":734},[738,1981,1982],{"class":740,"line":741},[738,1983,1985],{"class":1984},"sHwdD","# Tạo cgroup với CPU 0-7 cho MySQL\n",[738,1987,1988,1992,1996],{"class":740,"line":832},[738,1989,1991],{"class":1990},"sBMFI","cgcreate",[738,1993,1995],{"class":1994},"sfazB"," -g",[738,1997,1998],{"class":1994}," cpuset:\u002Fmysql\n",[738,2000,2001,2005,2009,2012,2015,2018],{"class":740,"line":1151},[738,2002,2004],{"class":2003},"s2Zo4","echo",[738,2006,2008],{"class":2007},"sMK4o"," \"",[738,2010,2011],{"class":1994},"0-7",[738,2013,2014],{"class":2007},"\"",[738,2016,2017],{"class":2007}," >",[738,2019,2020],{"class":1994}," \u002Fsys\u002Ffs\u002Fcgroup\u002Fcpuset\u002Fmysql\u002Fcpuset.cpus\n",[738,2022,2023,2025,2027,2030,2032,2034],{"class":740,"line":1487},[738,2024,2004],{"class":2003},[738,2026,2008],{"class":2007},[738,2028,2029],{"class":1994},"0",[738,2031,2014],{"class":2007},[738,2033,2017],{"class":2007},[738,2035,2036],{"class":1994}," \u002Fsys\u002Ffs\u002Fcgroup\u002Fcpuset\u002Fmysql\u002Fcpuset.mems\n",[738,2038,2039],{"class":740,"line":1493},[738,2040,1484],{"emptyLinePlaceholder":1483},[738,2042,2043],{"class":740,"line":1499},[738,2044,2045],{"class":1984},"# Gán MySQL process vào cgroup\n",[738,2047,2048,2051,2053,2056,2059,2062,2065],{"class":740,"line":1854},[738,2049,2050],{"class":1990},"cgclassify",[738,2052,1995],{"class":1994},[738,2054,2055],{"class":1994}," cpuset:\u002Fmysql",[738,2057,2058],{"class":2007}," $(",[738,2060,2061],{"class":1990},"pidof",[738,2063,2064],{"class":1994}," mysqld",[738,2066,2067],{"class":2007},")\n",[437,2069,2070,2071,2074],{},"Trong MySQL 9.7, InnoDB tự detect và tối ưu buffer pool allocation theo cgroup assignment. Không cần cấu hình thủ công ",[454,2072,2073],{},"innodb_numa_interleave"," như trước đây.",[432,2076,2078],{"id":2077},"_64-json-duality-views-là-gì-dml-support-trong-community-có-ý-nghĩa-gì","64. JSON Duality Views là gì? DML support trong Community có ý nghĩa gì?",[437,2080,2081,2084,2085,2088],{},[440,2082,2083],{},"JSON Duality Views"," cho phép truy cập cùng một bộ dữ liệu dưới ",[440,2086,2087],{},"hai dạng",": relational (SQL table) và document (JSON) — không cần duplication.",[729,2090,2092],{"className":731,"code":2091,"language":733,"meta":734,"style":734},"-- Tạo Duality View từ bảng quan hệ\nCREATE JSON DUALITY VIEW customer_dv AS\n  customer {\n    _id: id,\n    name: name,\n    orders: orders {\n      _id: id,\n      total: amount,\n      date: created_at\n    }\n  };\n\n-- Đọc như JSON document\nSELECT json_doc FROM customer_dv WHERE json_doc.name = 'An';\n\n-- INSERT qua JSON view (MỚI trong Community 9.7)\nINSERT INTO customer_dv VALUES ('{\n  \"_id\": 101,\n  \"name\": \"Vinh\",\n  \"orders\": [{\"_id\": 1, \"total\": 500, \"date\": \"2026-01-01\"}]\n}');\n\n-- UPDATE qua JSON view\nUPDATE customer_dv d SET d.json_doc = JSON_SET(d.json_doc, '$.name', 'Vinh Updated')\nWHERE d.json_doc._id = 101;\n",[454,2093,2094,2099,2104,2109,2114,2119,2124,2129,2134,2140,2146,2152,2157,2163,2169,2174,2180,2186,2192,2198,2204,2210,2215,2221,2227],{"__ignoreMap":734},[738,2095,2096],{"class":740,"line":741},[738,2097,2098],{},"-- Tạo Duality View từ bảng quan hệ\n",[738,2100,2101],{"class":740,"line":832},[738,2102,2103],{},"CREATE JSON DUALITY VIEW customer_dv AS\n",[738,2105,2106],{"class":740,"line":1151},[738,2107,2108],{},"  customer {\n",[738,2110,2111],{"class":740,"line":1487},[738,2112,2113],{},"    _id: id,\n",[738,2115,2116],{"class":740,"line":1493},[738,2117,2118],{},"    name: name,\n",[738,2120,2121],{"class":740,"line":1499},[738,2122,2123],{},"    orders: orders {\n",[738,2125,2126],{"class":740,"line":1854},[738,2127,2128],{},"      _id: id,\n",[738,2130,2131],{"class":740,"line":1859},[738,2132,2133],{},"      total: amount,\n",[738,2135,2137],{"class":740,"line":2136},9,[738,2138,2139],{},"      date: created_at\n",[738,2141,2143],{"class":740,"line":2142},10,[738,2144,2145],{},"    }\n",[738,2147,2149],{"class":740,"line":2148},11,[738,2150,2151],{},"  };\n",[738,2153,2155],{"class":740,"line":2154},12,[738,2156,1484],{"emptyLinePlaceholder":1483},[738,2158,2160],{"class":740,"line":2159},13,[738,2161,2162],{},"-- Đọc như JSON document\n",[738,2164,2166],{"class":740,"line":2165},14,[738,2167,2168],{},"SELECT json_doc FROM customer_dv WHERE json_doc.name = 'An';\n",[738,2170,2172],{"class":740,"line":2171},15,[738,2173,1484],{"emptyLinePlaceholder":1483},[738,2175,2177],{"class":740,"line":2176},16,[738,2178,2179],{},"-- INSERT qua JSON view (MỚI trong Community 9.7)\n",[738,2181,2183],{"class":740,"line":2182},17,[738,2184,2185],{},"INSERT INTO customer_dv VALUES ('{\n",[738,2187,2189],{"class":740,"line":2188},18,[738,2190,2191],{},"  \"_id\": 101,\n",[738,2193,2195],{"class":740,"line":2194},19,[738,2196,2197],{},"  \"name\": \"Vinh\",\n",[738,2199,2201],{"class":740,"line":2200},20,[738,2202,2203],{},"  \"orders\": [{\"_id\": 1, \"total\": 500, \"date\": \"2026-01-01\"}]\n",[738,2205,2207],{"class":740,"line":2206},21,[738,2208,2209],{},"}');\n",[738,2211,2213],{"class":740,"line":2212},22,[738,2214,1484],{"emptyLinePlaceholder":1483},[738,2216,2218],{"class":740,"line":2217},23,[738,2219,2220],{},"-- UPDATE qua JSON view\n",[738,2222,2224],{"class":740,"line":2223},24,[738,2225,2226],{},"UPDATE customer_dv d SET d.json_doc = JSON_SET(d.json_doc, '$.name', 'Vinh Updated')\n",[738,2228,2230],{"class":740,"line":2229},25,[738,2231,2232],{},"WHERE d.json_doc._id = 101;\n",[437,2234,2235,443],{},[440,2236,2237],{},"DML support trong Community có ý nghĩa lớn",[445,2239,2240,2246,2253,2256],{},[448,2241,2242,2243,2245],{},"Trước 9.7, DML trên JSON Duality View chỉ có trong ",[440,2244,1525],{}," (tính năng thương mại, phải trả phí).",[448,2247,2248,2249,2252],{},"Từ 9.7, INSERT\u002FUPDATE\u002FDELETE qua Duality View có trong ",[440,2250,2251],{},"Community miễn phí"," — full document-model API không tốn tiền.",[448,2254,2255],{},"Cạnh tranh trực tiếp với MongoDB (document model) và PostgreSQL JSONB — MySQL giờ có cả SQL và NoSQL trong cùng một engine, không cần add-on.",[448,2257,2258],{},"App có thể: CRUD nhanh qua document API cho frontend + SQL query phức tạp cho report\u002Fanalytics — cùng một data.",[427,2260,2262],{"id":2261},"l-mysql-index-performance-nâng-cao","L. MySQL Index & Performance nâng cao",[432,2264,2266],{"id":2265},"_65-các-loại-index-trong-mysql","65. Các loại index trong MySQL?",[437,2268,2269],{},"MySQL hỗ trợ nhiều loại index, mỗi loại cho mục đích khác nhau:",[1633,2271,2272,2285],{},[1636,2273,2274],{},[1639,2275,2276,2279,2282],{},[1642,2277,2278],{},"Loại index",[1642,2280,2281],{},"Engine",[1642,2283,2284],{},"Use case chính",[1650,2286,2287,2316,2332,2345,2363,2379,2392,2404,2416,2429,2441,2453],{},[1639,2288,2289,2294,2297],{},[1655,2290,2291],{},[440,2292,2293],{},"B-tree",[1655,2295,2296],{},"InnoDB (mặc định)",[1655,2298,2299,931,2301,931,2304,931,2307,931,2310,931,2313],{},[454,2300,917],{},[454,2302,2303],{},">",[454,2305,2306],{},"\u003C",[454,2308,2309],{},"BETWEEN",[454,2311,2312],{},"LIKE 'abc%'",[454,2314,2315],{},"ORDER BY",[1639,2317,2318,2323,2326],{},[1655,2319,2320],{},[440,2321,2322],{},"FULLTEXT",[1655,2324,2325],{},"InnoDB (5.6+)",[1655,2327,2328,2329],{},"Tìm kiếm văn bản ",[454,2330,2331],{},"MATCH(...) AGAINST(...)",[1639,2333,2334,2339,2342],{},[1655,2335,2336],{},[440,2337,2338],{},"SPATIAL (R-tree)",[1655,2340,2341],{},"InnoDB (5.7+)",[1655,2343,2344],{},"Dữ liệu địa lý (GIS, POINT, POLYGON)",[1639,2346,2347,2352,2355],{},[1655,2348,2349],{},[440,2350,2351],{},"Hash",[1655,2353,2354],{},"MEMORY, NDB",[1655,2356,2357,2358,931,2360,2362],{},"Chỉ ",[454,2359,917],{},[454,2361,907],{}," (không range scan)",[1639,2364,2365,2370,2373],{},[1655,2366,2367],{},[440,2368,2369],{},"Descending",[1655,2371,2372],{},"InnoDB (8.0+)",[1655,2374,2375,2378],{},[454,2376,2377],{},"ORDER BY col DESC"," dùng index thẳng",[1639,2380,2381,2386,2389],{},[1655,2382,2383],{},[440,2384,2385],{},"Functional",[1655,2387,2388],{},"InnoDB (8.0.13+)",[1655,2390,2391],{},"Index trên expression\u002Ffunction",[1639,2393,2394,2399,2401],{},[1655,2395,2396],{},[440,2397,2398],{},"Invisible",[1655,2400,2372],{},[1655,2402,2403],{},"Test trước khi DROP index an toàn",[1639,2405,2406,2411,2413],{},[1655,2407,2408],{},[440,2409,2410],{},"Prefix",[1655,2412,595],{},[1655,2414,2415],{},"Index N ký tự đầu của cột dài (VARCHAR\u002FTEXT)",[1639,2417,2418,2423,2426],{},[1655,2419,2420],{},[440,2421,2422],{},"Composite",[1655,2424,2425],{},"Tất cả",[1655,2427,2428],{},"Index nhiều cột — left-most prefix rule",[1639,2430,2431,2436,2438],{},[1655,2432,2433],{},[440,2434,2435],{},"Unique",[1655,2437,2425],{},[1655,2439,2440],{},"Enforce uniqueness + index",[1639,2442,2443,2448,2450],{},[1655,2444,2445],{},[440,2446,2447],{},"Primary Key",[1655,2449,595],{},[1655,2451,2452],{},"Clustered index — data lưu vật lý theo PK",[1639,2454,2455,2460,2463],{},[1655,2456,2457],{},[440,2458,2459],{},"Adaptive Hash",[1655,2461,2462],{},"InnoDB (tự động)",[1655,2464,2465],{},"Tự sinh hash index cho hot page trong Buffer Pool",[437,2467,2468],{},"Thực tế: 95% trường hợp cần B-tree composite index là đủ. FULLTEXT cho search engine trong app. SPATIAL cho map\u002Flocation app.",[432,2470,2472],{"id":2471},"_66-fulltext-index-với-ngram-parser-dùng-cho-tiếng-việt-thế-nào","66. FULLTEXT index với ngram parser — dùng cho tiếng Việt thế nào?",[437,2474,2475,2476,2479],{},"FULLTEXT index mặc định dùng whitespace để tách từ — chỉ hoạt động tốt với ngôn ngữ Latin có khoảng trắng giữa các từ (Anh, Pháp). ",[440,2477,2478],{},"Không hoạt động đúng với tiếng Việt, Trung, Nhật, Hàn"," vì parser không hiểu cách tách từ.",[437,2481,2482,2483,2486],{},"Giải pháp: ",[440,2484,2485],{},"ngram parser"," — tokenizer theo n-gram (cặp ký tự liên tiếp), không phụ thuộc vào whitespace.",[729,2488,2490],{"className":731,"code":2489,"language":733,"meta":734,"style":734},"-- Tạo FULLTEXT index với ngram parser\nALTER TABLE articles\n  ADD FULLTEXT INDEX ft_title_content (title, content) WITH PARSER ngram;\n\n-- Tìm kiếm tiếng Việt\nSELECT *, MATCH(title, content) AGAINST('lập trình viên' IN BOOLEAN MODE) AS score\nFROM articles\nWHERE MATCH(title, content) AGAINST('lập trình viên' IN BOOLEAN MODE)\nORDER BY score DESC;\n",[454,2491,2492,2497,2502,2507,2511,2516,2521,2526,2531],{"__ignoreMap":734},[738,2493,2494],{"class":740,"line":741},[738,2495,2496],{},"-- Tạo FULLTEXT index với ngram parser\n",[738,2498,2499],{"class":740,"line":832},[738,2500,2501],{},"ALTER TABLE articles\n",[738,2503,2504],{"class":740,"line":1151},[738,2505,2506],{},"  ADD FULLTEXT INDEX ft_title_content (title, content) WITH PARSER ngram;\n",[738,2508,2509],{"class":740,"line":1487},[738,2510,1484],{"emptyLinePlaceholder":1483},[738,2512,2513],{"class":740,"line":1493},[738,2514,2515],{},"-- Tìm kiếm tiếng Việt\n",[738,2517,2518],{"class":740,"line":1499},[738,2519,2520],{},"SELECT *, MATCH(title, content) AGAINST('lập trình viên' IN BOOLEAN MODE) AS score\n",[738,2522,2523],{"class":740,"line":1854},[738,2524,2525],{},"FROM articles\n",[738,2527,2528],{"class":740,"line":1859},[738,2529,2530],{},"WHERE MATCH(title, content) AGAINST('lập trình viên' IN BOOLEAN MODE)\n",[738,2532,2533],{"class":740,"line":2136},[738,2534,2535],{},"ORDER BY score DESC;\n",[437,2537,2538],{},"Cấu hình ngram_token_size:",[729,2540,2542],{"className":1134,"code":2541,"language":1136,"meta":734,"style":734},"# my.cnf\nngram_token_size = 2  # mặc định. 2 = bigram. Giá trị nhỏ → index to hơn, tìm chi tiết hơn.\n",[454,2543,2544,2549],{"__ignoreMap":734},[738,2545,2546],{"class":740,"line":741},[738,2547,2548],{},"# my.cnf\n",[738,2550,2551],{"class":740,"line":832},[738,2552,2553],{},"ngram_token_size = 2  # mặc định. 2 = bigram. Giá trị nhỏ → index to hơn, tìm chi tiết hơn.\n",[437,2555,2556],{},"So với LIKE:",[1633,2558,2559,2571],{},[1636,2560,2561],{},[1639,2562,2563,2565,2568],{},[1642,2564],{},[1642,2566,2567],{},"LIKE '%keyword%'",[1642,2569,2570],{},"FULLTEXT + ngram",[1650,2572,2573,2586,2599,2612],{},[1639,2574,2575,2580,2583],{},[1655,2576,2577],{},[440,2578,2579],{},"Index",[1655,2581,2582],{},"Không dùng",[1655,2584,2585],{},"Dùng index",[1639,2587,2588,2593,2596],{},[1655,2589,2590],{},[440,2591,2592],{},"Tốc độ",[1655,2594,2595],{},"Full scan — chậm",[1655,2597,2598],{},"Nhanh",[1639,2600,2601,2606,2609],{},[1655,2602,2603],{},[440,2604,2605],{},"Relevance",[1655,2607,2608],{},"Không",[1655,2610,2611],{},"Score ranking",[1639,2613,2614,2619,2621],{},[1655,2615,2616],{},[440,2617,2618],{},"Boolean",[1655,2620,2608],{},[1655,2622,2623],{},[454,2624,2625],{},"+required -excluded",[437,2627,2628,2629,480],{},"Hạn chế: Index lớn hơn B-tree (lưu tất cả bigram). Boolean mode có thể không chính xác bằng dedicated search engine (Elasticsearch). Stopword vẫn áp dụng — tắt bằng ",[454,2630,2631],{},"innodb_ft_enable_stopword = OFF",[432,2633,2635],{"id":2634},"_67-prefix-index-khi-nào-dùng","67. Prefix index — khi nào dùng?",[437,2637,2638,2639,2642],{},"Prefix index chỉ index ",[440,2640,2641],{},"N ký tự đầu"," của cột, thay vì toàn bộ giá trị. Dùng cho cột dài (VARCHAR > 255, TEXT, BLOB) để tiết kiệm không gian.",[729,2644,2646],{"className":731,"code":2645,"language":733,"meta":734,"style":734},"-- Index 20 ký tự đầu của title\nCREATE INDEX idx_title_prefix ON articles(title(20));\n\n-- Tìm độ dài prefix tối ưu (trade-off size vs selectivity)\nSELECT\n  COUNT(DISTINCT LEFT(title, 10)) \u002F COUNT(*) AS sel_10,\n  COUNT(DISTINCT LEFT(title, 20)) \u002F COUNT(*) AS sel_20,\n  COUNT(DISTINCT LEFT(title, 30)) \u002F COUNT(*) AS sel_30\nFROM articles;\n-- Chọn N nhỏ nhất mà selectivity ≈ 1\n",[454,2647,2648,2653,2658,2662,2667,2672,2677,2682,2687,2692],{"__ignoreMap":734},[738,2649,2650],{"class":740,"line":741},[738,2651,2652],{},"-- Index 20 ký tự đầu của title\n",[738,2654,2655],{"class":740,"line":832},[738,2656,2657],{},"CREATE INDEX idx_title_prefix ON articles(title(20));\n",[738,2659,2660],{"class":740,"line":1151},[738,2661,1484],{"emptyLinePlaceholder":1483},[738,2663,2664],{"class":740,"line":1487},[738,2665,2666],{},"-- Tìm độ dài prefix tối ưu (trade-off size vs selectivity)\n",[738,2668,2669],{"class":740,"line":1493},[738,2670,2671],{},"SELECT\n",[738,2673,2674],{"class":740,"line":1499},[738,2675,2676],{},"  COUNT(DISTINCT LEFT(title, 10)) \u002F COUNT(*) AS sel_10,\n",[738,2678,2679],{"class":740,"line":1854},[738,2680,2681],{},"  COUNT(DISTINCT LEFT(title, 20)) \u002F COUNT(*) AS sel_20,\n",[738,2683,2684],{"class":740,"line":1859},[738,2685,2686],{},"  COUNT(DISTINCT LEFT(title, 30)) \u002F COUNT(*) AS sel_30\n",[738,2688,2689],{"class":740,"line":2136},[738,2690,2691],{},"FROM articles;\n",[738,2693,2694],{"class":740,"line":2142},[738,2695,2696],{},"-- Chọn N nhỏ nhất mà selectivity ≈ 1\n",[437,2698,2699],{},"Khi nào dùng:",[445,2701,2702,2705,2708],{},[448,2703,2704],{},"Cột VARCHAR\u002FTEXT dài (> 255 ký tự) nhưng query thường chỉ tìm prefix (VD: tìm theo đầu email, URL).",[448,2706,2707],{},"Cần index nhưng không muốn index phình to (index lớn → RAM, disk, write performance).",[448,2709,2710],{},"Cột BLOB — bắt buộc phải dùng prefix (BLOB không index full được).",[437,2712,2713],{},"Hạn chế:",[445,2715,2716,2724,2727],{},[448,2717,2718,2719,931,2721,480],{},"Không dùng cho ",[454,2720,2315],{},[454,2722,2723],{},"GROUP BY",[448,2725,2726],{},"Không dùng làm covering index.",[448,2728,2729],{},"Phải chọn độ dài prefix đủ selectivity — prefix quá ngắn → nhiều row match → index ít hiệu quả.",[427,2731,2733],{"id":2732},"m-mysql-stored-programs","M. MySQL Stored Programs",[432,2735,2737],{"id":2736},"_68-stored-procedure-vs-function-trong-mysql-khác-nhau-thế-nào","68. Stored procedure vs function trong MySQL — khác nhau thế nào?",[1633,2739,2740,2753],{},[1636,2741,2742],{},[1639,2743,2744,2747,2750],{},[1642,2745,2746],{},"Đặc điểm",[1642,2748,2749],{},"Procedure",[1642,2751,2752],{},"Function",[1650,2754,2755,2772,2785,2798,2811,2824,2837],{},[1639,2756,2757,2762,2767],{},[1655,2758,2759],{},[440,2760,2761],{},"Cách gọi",[1655,2763,2764],{},[454,2765,2766],{},"CALL sp_name(params)",[1655,2768,2769],{},[454,2770,2771],{},"SELECT fn_name(params)",[1639,2773,2774,2779,2782],{},[1655,2775,2776],{},[440,2777,2778],{},"Giá trị trả về",[1655,2780,2781],{},"Không bắt buộc (qua OUT param)",[1655,2783,2784],{},"Bắt buộc RETURN 1 giá trị",[1639,2786,2787,2792,2795],{},[1655,2788,2789],{},[440,2790,2791],{},"Tham số",[1655,2793,2794],{},"IN \u002F OUT \u002F INOUT",[1655,2796,2797],{},"Chỉ IN",[1639,2799,2800,2805,2808],{},[1655,2801,2802],{},[440,2803,2804],{},"Transaction",[1655,2806,2807],{},"COMMIT, ROLLBACK được",[1655,2809,2810],{},"Không được",[1639,2812,2813,2818,2821],{},[1655,2814,2815],{},[440,2816,2817],{},"Dùng trong SQL",[1655,2819,2820],{},"Không (chỉ CALL)",[1655,2822,2823],{},"Được (SELECT, WHERE, JOIN...)",[1639,2825,2826,2831,2834],{},[1655,2827,2828],{},[440,2829,2830],{},"Side effect",[1655,2832,2833],{},"Được phép (INSERT, UPDATE...)",[1655,2835,2836],{},"Khuyến nghị hạn chế",[1639,2838,2839,2844,2847],{},[1655,2840,2841],{},[440,2842,2843],{},"Use case",[1655,2845,2846],{},"Batch process, business transaction",[1655,2848,2849],{},"Tính toán, computed column",[437,2851,2852],{},"Ví dụ thực tế:",[729,2854,2856],{"className":731,"code":2855,"language":733,"meta":734,"style":734},"-- Procedure: xử lý đơn hàng (nhiều bước, có transaction)\nDELIMITER $$\nCREATE PROCEDURE process_order(IN p_user_id INT, IN p_amount DECIMAL(10,2))\nBEGIN\n  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;\n  START TRANSACTION;\n    INSERT INTO orders(user_id, amount) VALUES(p_user_id, p_amount);\n    UPDATE users SET balance = balance - p_amount WHERE id = p_user_id;\n  COMMIT;\nEND$$\nDELIMITER ;\n\nCALL process_order(1, 500.00);\n\n-- Function: tính tổng đơn hàng (compute, dùng trong SELECT)\nDELIMITER $$\nCREATE FUNCTION order_total(p_user_id INT) RETURNS DECIMAL(10,2)\nDETERMINISTIC READS SQL DATA\nBEGIN\n  DECLARE total DECIMAL(10,2);\n  SELECT COALESCE(SUM(amount), 0) INTO total FROM orders WHERE user_id = p_user_id;\n  RETURN total;\nEND$$\nDELIMITER ;\n\nSELECT name, order_total(id) AS total_spent FROM users;\n",[454,2857,2858,2863,2868,2873,2878,2883,2888,2893,2898,2903,2908,2913,2917,2922,2926,2931,2935,2940,2945,2949,2954,2959,2964,2968,2972,2976],{"__ignoreMap":734},[738,2859,2860],{"class":740,"line":741},[738,2861,2862],{},"-- Procedure: xử lý đơn hàng (nhiều bước, có transaction)\n",[738,2864,2865],{"class":740,"line":832},[738,2866,2867],{},"DELIMITER $$\n",[738,2869,2870],{"class":740,"line":1151},[738,2871,2872],{},"CREATE PROCEDURE process_order(IN p_user_id INT, IN p_amount DECIMAL(10,2))\n",[738,2874,2875],{"class":740,"line":1487},[738,2876,2877],{},"BEGIN\n",[738,2879,2880],{"class":740,"line":1493},[738,2881,2882],{},"  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;\n",[738,2884,2885],{"class":740,"line":1499},[738,2886,2887],{},"  START TRANSACTION;\n",[738,2889,2890],{"class":740,"line":1854},[738,2891,2892],{},"    INSERT INTO orders(user_id, amount) VALUES(p_user_id, p_amount);\n",[738,2894,2895],{"class":740,"line":1859},[738,2896,2897],{},"    UPDATE users SET balance = balance - p_amount WHERE id = p_user_id;\n",[738,2899,2900],{"class":740,"line":2136},[738,2901,2902],{},"  COMMIT;\n",[738,2904,2905],{"class":740,"line":2142},[738,2906,2907],{},"END$$\n",[738,2909,2910],{"class":740,"line":2148},[738,2911,2912],{},"DELIMITER ;\n",[738,2914,2915],{"class":740,"line":2154},[738,2916,1484],{"emptyLinePlaceholder":1483},[738,2918,2919],{"class":740,"line":2159},[738,2920,2921],{},"CALL process_order(1, 500.00);\n",[738,2923,2924],{"class":740,"line":2165},[738,2925,1484],{"emptyLinePlaceholder":1483},[738,2927,2928],{"class":740,"line":2171},[738,2929,2930],{},"-- Function: tính tổng đơn hàng (compute, dùng trong SELECT)\n",[738,2932,2933],{"class":740,"line":2176},[738,2934,2867],{},[738,2936,2937],{"class":740,"line":2182},[738,2938,2939],{},"CREATE FUNCTION order_total(p_user_id INT) RETURNS DECIMAL(10,2)\n",[738,2941,2942],{"class":740,"line":2188},[738,2943,2944],{},"DETERMINISTIC READS SQL DATA\n",[738,2946,2947],{"class":740,"line":2194},[738,2948,2877],{},[738,2950,2951],{"class":740,"line":2200},[738,2952,2953],{},"  DECLARE total DECIMAL(10,2);\n",[738,2955,2956],{"class":740,"line":2206},[738,2957,2958],{},"  SELECT COALESCE(SUM(amount), 0) INTO total FROM orders WHERE user_id = p_user_id;\n",[738,2960,2961],{"class":740,"line":2212},[738,2962,2963],{},"  RETURN total;\n",[738,2965,2966],{"class":740,"line":2217},[738,2967,2907],{},[738,2969,2970],{"class":740,"line":2223},[738,2971,2912],{},[738,2973,2974],{"class":740,"line":2229},[738,2975,1484],{"emptyLinePlaceholder":1483},[738,2977,2979],{"class":740,"line":2978},26,[738,2980,2981],{},"SELECT name, order_total(id) AS total_spent FROM users;\n",[437,2983,2984],{},"Nguyên tắc chọn: Cần thay đổi data + transaction → procedure. Cần compute 1 giá trị + dùng trong query → function.",[432,2986,2988],{"id":2987},"_69-trigger-use-case-thực-tế","69. Trigger — use case thực tế?",[437,2990,2991,2992,2995,2996,2999,3000,480],{},"Trigger là code tự động chạy ",[440,2993,2994],{},"trước hoặc sau"," INSERT\u002FUPDATE\u002FDELETE. Có 2 loại: ",[454,2997,2998],{},"FOR EACH ROW"," (per-row) và ",[454,3001,3002],{},"FOR EACH STATEMENT",[437,3004,3005],{},"Các use case thực tế:",[437,3007,3008],{},[440,3009,3010],{},"1. Audit log — ghi lại mọi thay đổi:",[729,3012,3014],{"className":731,"code":3013,"language":733,"meta":734,"style":734},"CREATE TRIGGER trg_audit_users AFTER UPDATE ON users\nFOR EACH ROW\n  INSERT INTO audit_log(table_name, row_id, changed_by, old_val, new_val, changed_at)\n  VALUES('users', OLD.id, USER(),\n    JSON_OBJECT('email', OLD.email, 'role', OLD.role),\n    JSON_OBJECT('email', NEW.email, 'role', NEW.role),\n    NOW());\n",[454,3015,3016,3021,3026,3031,3036,3041,3046],{"__ignoreMap":734},[738,3017,3018],{"class":740,"line":741},[738,3019,3020],{},"CREATE TRIGGER trg_audit_users AFTER UPDATE ON users\n",[738,3022,3023],{"class":740,"line":832},[738,3024,3025],{},"FOR EACH ROW\n",[738,3027,3028],{"class":740,"line":1151},[738,3029,3030],{},"  INSERT INTO audit_log(table_name, row_id, changed_by, old_val, new_val, changed_at)\n",[738,3032,3033],{"class":740,"line":1487},[738,3034,3035],{},"  VALUES('users', OLD.id, USER(),\n",[738,3037,3038],{"class":740,"line":1493},[738,3039,3040],{},"    JSON_OBJECT('email', OLD.email, 'role', OLD.role),\n",[738,3042,3043],{"class":740,"line":1499},[738,3044,3045],{},"    JSON_OBJECT('email', NEW.email, 'role', NEW.role),\n",[738,3047,3048],{"class":740,"line":1854},[738,3049,3050],{},"    NOW());\n",[437,3052,3053],{},[440,3054,3055],{},"2. Validate business rule phức tạp:",[729,3057,3059],{"className":731,"code":3058,"language":733,"meta":734,"style":734},"CREATE TRIGGER trg_check_balance BEFORE INSERT ON withdrawals\nFOR EACH ROW\nBEGIN\n  DECLARE current_balance DECIMAL(10,2);\n  SELECT balance INTO current_balance FROM users WHERE id = NEW.user_id;\n  IF current_balance \u003C NEW.amount THEN\n    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Số dư không đủ';\n  END IF;\nEND$$\n",[454,3060,3061,3066,3070,3074,3079,3084,3089,3094,3099],{"__ignoreMap":734},[738,3062,3063],{"class":740,"line":741},[738,3064,3065],{},"CREATE TRIGGER trg_check_balance BEFORE INSERT ON withdrawals\n",[738,3067,3068],{"class":740,"line":832},[738,3069,3025],{},[738,3071,3072],{"class":740,"line":1151},[738,3073,2877],{},[738,3075,3076],{"class":740,"line":1487},[738,3077,3078],{},"  DECLARE current_balance DECIMAL(10,2);\n",[738,3080,3081],{"class":740,"line":1493},[738,3082,3083],{},"  SELECT balance INTO current_balance FROM users WHERE id = NEW.user_id;\n",[738,3085,3086],{"class":740,"line":1499},[738,3087,3088],{},"  IF current_balance \u003C NEW.amount THEN\n",[738,3090,3091],{"class":740,"line":1854},[738,3092,3093],{},"    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Số dư không đủ';\n",[738,3095,3096],{"class":740,"line":1859},[738,3097,3098],{},"  END IF;\n",[738,3100,3101],{"class":740,"line":2136},[738,3102,2907],{},[437,3104,3105],{},[440,3106,3107],{},"3. Soft-delete cascade:",[729,3109,3111],{"className":731,"code":3110,"language":733,"meta":734,"style":734},"CREATE TRIGGER trg_soft_delete_posts AFTER UPDATE ON users\nFOR EACH ROW\n  IF NEW.deleted_at IS NOT NULL AND OLD.deleted_at IS NULL THEN\n    UPDATE posts SET deleted_at = NOW() WHERE user_id = NEW.id;\n  END IF;\n",[454,3112,3113,3118,3122,3127,3132],{"__ignoreMap":734},[738,3114,3115],{"class":740,"line":741},[738,3116,3117],{},"CREATE TRIGGER trg_soft_delete_posts AFTER UPDATE ON users\n",[738,3119,3120],{"class":740,"line":832},[738,3121,3025],{},[738,3123,3124],{"class":740,"line":1151},[738,3125,3126],{},"  IF NEW.deleted_at IS NOT NULL AND OLD.deleted_at IS NULL THEN\n",[738,3128,3129],{"class":740,"line":1487},[738,3130,3131],{},"    UPDATE posts SET deleted_at = NOW() WHERE user_id = NEW.id;\n",[738,3133,3134],{"class":740,"line":1493},[738,3135,3098],{},[437,3137,3138],{},[440,3139,3140],{},"4. Tự động cập nhật cột derived:",[729,3142,3144],{"className":731,"code":3143,"language":733,"meta":734,"style":734},"CREATE TRIGGER trg_update_order_total AFTER INSERT ON order_items\nFOR EACH ROW\n  UPDATE orders\n  SET total = total + (NEW.price * NEW.quantity)\n  WHERE id = NEW.order_id;\n",[454,3145,3146,3151,3155,3160,3165],{"__ignoreMap":734},[738,3147,3148],{"class":740,"line":741},[738,3149,3150],{},"CREATE TRIGGER trg_update_order_total AFTER INSERT ON order_items\n",[738,3152,3153],{"class":740,"line":832},[738,3154,3025],{},[738,3156,3157],{"class":740,"line":1151},[738,3158,3159],{},"  UPDATE orders\n",[738,3161,3162],{"class":740,"line":1487},[738,3163,3164],{},"  SET total = total + (NEW.price * NEW.quantity)\n",[738,3166,3167],{"class":740,"line":1493},[738,3168,3169],{},"  WHERE id = NEW.order_id;\n",[437,3171,3172],{},"Lưu ý quan trọng:",[445,3174,3175,3178,3181,3184],{},[448,3176,3177],{},"Trigger chạy trong cùng transaction với DML gốc → rollback được.",[448,3179,3180],{},"Không nên dùng trigger cho heavy logic — ảnh hưởng performance mọi DML.",[448,3182,3183],{},"Recursive trigger: MySQL giới hạn 1 level, không cho phép trigger tự gọi chính nó.",[448,3185,3186],{},"Debug khó — logic nằm ẩn trong DB, không visible trong application code. Cân nhắc dùng application-level hook thay cho trigger nếu logic phức tạp.",[432,3188,3190],{"id":3189},"_70-event-scheduler-dùng-khi-nào","70. Event scheduler — dùng khi nào?",[437,3192,3193,3194,3197],{},"Event Scheduler là ",[440,3195,3196],{},"cron job trong MySQL"," — chạy SQL định kỳ không cần cron\u002Fsystemd bên ngoài, không phụ thuộc OS.",[437,3199,1767],{},[729,3201,3203],{"className":731,"code":3202,"language":733,"meta":734,"style":734},"-- Bật event scheduler (cần SUPER privilege)\nSET GLOBAL event_scheduler = ON;\n\n-- my.cnf để auto-start sau restart\n-- event_scheduler = ON\n",[454,3204,3205,3210,3215,3219,3224],{"__ignoreMap":734},[738,3206,3207],{"class":740,"line":741},[738,3208,3209],{},"-- Bật event scheduler (cần SUPER privilege)\n",[738,3211,3212],{"class":740,"line":832},[738,3213,3214],{},"SET GLOBAL event_scheduler = ON;\n",[738,3216,3217],{"class":740,"line":1151},[738,3218,1484],{"emptyLinePlaceholder":1483},[738,3220,3221],{"class":740,"line":1487},[738,3222,3223],{},"-- my.cnf để auto-start sau restart\n",[738,3225,3226],{"class":740,"line":1493},[738,3227,3228],{},"-- event_scheduler = ON\n",[437,3230,1897],{},[437,3232,3233],{},[440,3234,3235],{},"1. Dọn dữ liệu cũ:",[729,3237,3239],{"className":731,"code":3238,"language":733,"meta":734,"style":734},"CREATE EVENT clean_expired_sessions\n  ON SCHEDULE EVERY 1 HOUR\n  DO DELETE FROM sessions WHERE expired_at \u003C NOW();\n",[454,3240,3241,3246,3251],{"__ignoreMap":734},[738,3242,3243],{"class":740,"line":741},[738,3244,3245],{},"CREATE EVENT clean_expired_sessions\n",[738,3247,3248],{"class":740,"line":832},[738,3249,3250],{},"  ON SCHEDULE EVERY 1 HOUR\n",[738,3252,3253],{"class":740,"line":1151},[738,3254,3255],{},"  DO DELETE FROM sessions WHERE expired_at \u003C NOW();\n",[437,3257,3258],{},[440,3259,3260],{},"2. Aggregation định kỳ:",[729,3262,3264],{"className":731,"code":3263,"language":733,"meta":734,"style":734},"CREATE EVENT daily_sales_report\n  ON SCHEDULE EVERY 1 DAY\n  STARTS '2026-07-09 02:00:00'\n  DO\n    INSERT INTO daily_sales_summary (report_date, total_amount, order_count)\n    SELECT CURDATE(), SUM(amount), COUNT(*) FROM orders\n    WHERE created_at >= CURDATE();\n",[454,3265,3266,3271,3276,3281,3286,3291,3296],{"__ignoreMap":734},[738,3267,3268],{"class":740,"line":741},[738,3269,3270],{},"CREATE EVENT daily_sales_report\n",[738,3272,3273],{"class":740,"line":832},[738,3274,3275],{},"  ON SCHEDULE EVERY 1 DAY\n",[738,3277,3278],{"class":740,"line":1151},[738,3279,3280],{},"  STARTS '2026-07-09 02:00:00'\n",[738,3282,3283],{"class":740,"line":1487},[738,3284,3285],{},"  DO\n",[738,3287,3288],{"class":740,"line":1493},[738,3289,3290],{},"    INSERT INTO daily_sales_summary (report_date, total_amount, order_count)\n",[738,3292,3293],{"class":740,"line":1499},[738,3294,3295],{},"    SELECT CURDATE(), SUM(amount), COUNT(*) FROM orders\n",[738,3297,3298],{"class":740,"line":1854},[738,3299,3300],{},"    WHERE created_at >= CURDATE();\n",[437,3302,3303],{},[440,3304,3305],{},"3. Rotate partition:",[729,3307,3309],{"className":731,"code":3308,"language":733,"meta":734,"style":734},"CREATE EVENT monthly_partition_maintenance\n  ON SCHEDULE EVERY 1 MONTH\n  DO\n  BEGIN\n    -- Tạo partition cho tháng sau\n    SET @sql = CONCAT('ALTER TABLE logs ADD PARTITION ...');\n    PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;\n    -- Xóa partition cũ (> 6 tháng)\n    ...\n  END;\n",[454,3310,3311,3316,3321,3325,3330,3335,3340,3345,3350,3355],{"__ignoreMap":734},[738,3312,3313],{"class":740,"line":741},[738,3314,3315],{},"CREATE EVENT monthly_partition_maintenance\n",[738,3317,3318],{"class":740,"line":832},[738,3319,3320],{},"  ON SCHEDULE EVERY 1 MONTH\n",[738,3322,3323],{"class":740,"line":1151},[738,3324,3285],{},[738,3326,3327],{"class":740,"line":1487},[738,3328,3329],{},"  BEGIN\n",[738,3331,3332],{"class":740,"line":1493},[738,3333,3334],{},"    -- Tạo partition cho tháng sau\n",[738,3336,3337],{"class":740,"line":1499},[738,3338,3339],{},"    SET @sql = CONCAT('ALTER TABLE logs ADD PARTITION ...');\n",[738,3341,3342],{"class":740,"line":1854},[738,3343,3344],{},"    PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;\n",[738,3346,3347],{"class":740,"line":1859},[738,3348,3349],{},"    -- Xóa partition cũ (> 6 tháng)\n",[738,3351,3352],{"class":740,"line":2136},[738,3353,3354],{},"    ...\n",[738,3356,3357],{"class":740,"line":2142},[738,3358,3359],{},"  END;\n",[437,3361,3362],{},[440,3363,3364],{},"4. Event chạy một lần:",[729,3366,3368],{"className":731,"code":3367,"language":733,"meta":734,"style":734},"CREATE EVENT one_time_data_migration\n  ON SCHEDULE AT '2026-07-15 03:00:00'\n  DO\n    INSERT INTO archive_orders SELECT * FROM orders WHERE created_at \u003C '2025-01-01';\n",[454,3369,3370,3375,3380,3384],{"__ignoreMap":734},[738,3371,3372],{"class":740,"line":741},[738,3373,3374],{},"CREATE EVENT one_time_data_migration\n",[738,3376,3377],{"class":740,"line":832},[738,3378,3379],{},"  ON SCHEDULE AT '2026-07-15 03:00:00'\n",[738,3381,3382],{"class":740,"line":1151},[738,3383,3285],{},[738,3385,3386],{"class":740,"line":1487},[738,3387,3388],{},"    INSERT INTO archive_orders SELECT * FROM orders WHERE created_at \u003C '2025-01-01';\n",[437,3390,3391],{},"Giám sát và quản lý:",[729,3393,3395],{"className":731,"code":3394,"language":733,"meta":734,"style":734},"SHOW EVENTS;                              -- Liệt kê tất cả event\nSELECT * FROM information_schema.EVENTS;  -- Chi tiết hơn\nALTER EVENT clean_expired_sessions DISABLE; -- Tạm dừng\nDROP EVENT IF EXISTS clean_expired_sessions; -- Xóa\n",[454,3396,3397,3402,3407,3412],{"__ignoreMap":734},[738,3398,3399],{"class":740,"line":741},[738,3400,3401],{},"SHOW EVENTS;                              -- Liệt kê tất cả event\n",[738,3403,3404],{"class":740,"line":832},[738,3405,3406],{},"SELECT * FROM information_schema.EVENTS;  -- Chi tiết hơn\n",[738,3408,3409],{"class":740,"line":1151},[738,3410,3411],{},"ALTER EVENT clean_expired_sessions DISABLE; -- Tạm dừng\n",[738,3413,3414],{"class":740,"line":1487},[738,3415,3416],{},"DROP EVENT IF EXISTS clean_expired_sessions; -- Xóa\n",[437,3418,3172],{},[445,3420,3421,3427,3430],{},[448,3422,3423,3424,480],{},"Khi replication: event chạy trên source, statement replicate xuống replica. Trên replica set ",[454,3425,3426],{},"event_scheduler = OFF",[448,3428,3429],{},"Nếu event chạy quá lâu → event sau bị skip (không queue). Cần giám sát thời gian chạy.",[448,3431,3432,3433,3435],{},"Sau MySQL restart mà ",[454,3434,3426],{}," trong my.cnf → event không chạy → nhớ set ON.",[3437,3438,3441,3442],"callout",{"color":3439,"icon":3440},"primary","i-lucide-arrow-right","Tiếp theo: ",[3443,3444,3445],"a",{"href":245},"So sánh chi tiết 3 RDBMS",[3447,3448,3449],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}",{"title":734,"searchDepth":832,"depth":832,"links":3451},[3452,3459,3466,3474,3481,3491,3499,3508,3517,3523,3533,3542,3547],{"id":429,"depth":832,"text":430,"children":3453},[3454,3455,3456,3457,3458],{"id":434,"depth":1151,"text":435},{"id":498,"depth":1151,"text":499},{"id":568,"depth":1151,"text":569},{"id":589,"depth":1151,"text":590},{"id":602,"depth":1151,"text":603},{"id":619,"depth":832,"text":620,"children":3460},[3461,3462,3463,3464,3465],{"id":623,"depth":1151,"text":624},{"id":642,"depth":1151,"text":643},{"id":664,"depth":1151,"text":665},{"id":674,"depth":1151,"text":675},{"id":681,"depth":1151,"text":682},{"id":696,"depth":832,"text":697,"children":3467},[3468,3470,3471,3472,3473],{"id":700,"depth":1151,"text":3469},"11. AUTO_INCREMENT khác SERIAL Postgres thế nào?",{"id":715,"depth":1151,"text":716},{"id":726,"depth":1151,"text":727},{"id":749,"depth":1151,"text":750},{"id":764,"depth":1151,"text":765},{"id":771,"depth":832,"text":772,"children":3475},[3476,3477,3478,3479,3480],{"id":775,"depth":1151,"text":776},{"id":793,"depth":1151,"text":794},{"id":800,"depth":1151,"text":801},{"id":818,"depth":1151,"text":819},{"id":838,"depth":1151,"text":839},{"id":848,"depth":832,"text":849,"children":3482},[3483,3484,3485,3486,3487,3488,3490],{"id":852,"depth":1151,"text":853},{"id":864,"depth":1151,"text":865},{"id":871,"depth":1151,"text":872},{"id":884,"depth":1151,"text":885},{"id":894,"depth":1151,"text":895},{"id":903,"depth":1151,"text":3489},"26. NULL-safe equal (\u003C=>)?",{"id":921,"depth":1151,"text":922},{"id":947,"depth":832,"text":948,"children":3492},[3493,3494,3495,3496,3497,3498],{"id":951,"depth":1151,"text":952},{"id":966,"depth":1151,"text":967},{"id":976,"depth":1151,"text":977},{"id":983,"depth":1151,"text":984},{"id":993,"depth":1151,"text":994},{"id":1002,"depth":1151,"text":1003},{"id":1009,"depth":832,"text":1010,"children":3500},[3501,3502,3503,3504,3505,3506,3507],{"id":1013,"depth":1151,"text":1014},{"id":1023,"depth":1151,"text":1024},{"id":1034,"depth":1151,"text":1035},{"id":1041,"depth":1151,"text":1042},{"id":1053,"depth":1151,"text":1054},{"id":1060,"depth":1151,"text":1061},{"id":1071,"depth":1151,"text":1072},{"id":1086,"depth":832,"text":1087,"children":3509},[3510,3511,3512,3514,3515,3516],{"id":1090,"depth":1151,"text":1091},{"id":1101,"depth":1151,"text":1102},{"id":1113,"depth":1151,"text":3513},"43. EXPLAIN — type cột nào quan trọng?",{"id":1130,"depth":1151,"text":1131},{"id":1167,"depth":1151,"text":1168},{"id":1188,"depth":1151,"text":1189},{"id":1210,"depth":832,"text":1211,"children":3518},[3519,3520,3521,3522],{"id":1214,"depth":1151,"text":1215},{"id":1226,"depth":1151,"text":1227},{"id":1244,"depth":1151,"text":1245},{"id":1251,"depth":1151,"text":1252},{"id":1258,"depth":832,"text":1259,"children":3524},[3525,3526,3527,3529,3530,3531,3532],{"id":1262,"depth":1151,"text":1263},{"id":1292,"depth":1151,"text":1293},{"id":1313,"depth":1151,"text":3528},"53. Bảng InnoDB to nhưng SELECT COUNT(*) chậm?",{"id":1342,"depth":1151,"text":1343},{"id":1363,"depth":1151,"text":1364},{"id":1385,"depth":1151,"text":1386},{"id":1395,"depth":1151,"text":1396},{"id":1423,"depth":832,"text":1424,"children":3534},[3535,3536,3537,3538,3539,3540,3541],{"id":1427,"depth":1151,"text":1428},{"id":1518,"depth":1151,"text":1519},{"id":1583,"depth":1151,"text":1584},{"id":1627,"depth":1151,"text":1628},{"id":1805,"depth":1151,"text":1806},{"id":1932,"depth":1151,"text":1933},{"id":2077,"depth":1151,"text":2078},{"id":2261,"depth":832,"text":2262,"children":3543},[3544,3545,3546],{"id":2265,"depth":1151,"text":2266},{"id":2471,"depth":1151,"text":2472},{"id":2634,"depth":1151,"text":2635},{"id":2732,"depth":832,"text":2733,"children":3548},[3549,3550,3551],{"id":2736,"depth":1151,"text":2737},{"id":2987,"depth":1151,"text":2988},{"id":3189,"depth":1151,"text":3190},"65+ câu hỏi phỏng vấn MySQL cho dev backend \u002F fullstack — InnoDB, gap lock, replication, optimizer, MySQL 8.4 & 9.7 LTS.","md",null,{},{"title":193,"icon":196},{"title":422,"description":3552},"6Nh9uiWVO2LJS0Pl6ug4-tPO0RInV1xwavjBFmB3HC0",[3560,3562],{"title":188,"path":238,"stem":239,"description":3561,"icon":191,"children":-1},"InnoDB internals, buffer pool, replication source\u002Freplica, partitioning, performance tuning cho MySQL 8.4\u002F9.x.",{"title":244,"path":245,"stem":246,"description":3563,"icon":247,"children":-1},"So sánh chi tiết 3 RDBMS phổ biến — feature, performance, use case, syntax difference. Bảng tham chiếu cuối khi đã học cả 3.",1783490367284]