Real-World MySQL Problems & Solutions

থিওরি শেখা সহজ, কিন্তু প্রোডাকশন এনভায়রনমেন্টে যখন রাত ৩টার সময় সার্ভার ডাউন হয়, তখন থিওরি মনে থাকে না। তখন দরকার হয় প্র্যাকটিক্যাল সলিউশন

এই অধ্যায়ে আমরা ১৮টি ভয়ংকর সমস্যা এবং তাদের সমাধান নিয়ে আলোচনা করব, যা আপনাকে একজন সাধারণ ডেভেলপার থেকে "Database Savior" বানিয়ে দেবে।

১৯.১ Slow Query Issues (সবচেয়ে সাধারণ সমস্যা)

সমস্যা: কুয়েরি রান করতে ৫-১০ সেকেন্ড বা তার বেশি সময় নিচ্ছে। সাইট লোড হচ্ছে না।

🔍 কারণ:

  • ইনডেক্স মিসিং বা ভুল ইনডেক্স ব্যবহার
  • SELECT * ব্যবহার করা (অপ্রয়োজনীয় ডেটা লোড)
  • WHERE ক্লজে ফাংশন ব্যবহার (যেমন: WHERE YEAR(date) = 2023) যা ইনডেক্স নষ্ট করে
  • বিশাল অফসেট পেজিনেশন (LIMIT 1000000, 20)

✅ সমাধান:

  • EXPLAIN: কুয়েরির আগে EXPLAIN বসিয়ে দেখুন type=ALL আছে কি না। থাকলে ইনডেক্স দিন
  • Covering Index: প্রয়োজনীয় কলামগুলো ইনডেক্সে যুক্ত করুন
  • Keyset Pagination: OFFSET বাদ দিয়ে WHERE id < last_id ব্যবহার করুন
  • No Functions: কলামের ওপর ফাংশন চালাবেন না

১৯.২ Deadlock Problem (সাইলেন্ট কিলার)

সমস্যা: Error 1213: Deadlock found when trying to get lock...

🔍 কেন হয়?

দুটি ট্রানজেকশন একে অপরের লকের জন্য অপেক্ষা করছে।

  • User A: Table 1 লক করল → Table 2 চায়
  • User B: Table 2 লক করল → Table 1 চায়

✅ সমাধান:

  • Fixed Order: সবসময় একই অর্ডারে টেবিল আপডেট করুন (Table 1 → Table 2)
  • Small Transaction: ট্রানজেকশন যত ছোট হবে, ডেডলক চান্স তত কম
  • Retry Logic: অ্যাপ্লিকেশনে try-catch ব্লকে কোড লিখুন। ডেডলক এরর পেলে ৫০ms পর আবার ট্রাই করুন
// Pseudocode - Retry Logic
try {
  // Execute transaction
} catch (DeadlockException) {
  sleep(50);
  retry();
}

১৯.৩ Table Lock / Metadata Lock

সমস্যা: একটা সাধারণ ALTER TABLE বা INSERT কুয়েরি অনন্তকাল ধরে আটকে আছে।

🔍 কারণ:

অন্য কোনো সেশনে একটি লম্বা কুয়েরি চলছে যা টেবিলটি লক করে রেখেছে। অথবা একটি ট্রানজেকশন ওপেন হয়ে আছে কিন্তু ক্লোজ হয়নি।

✅ সমাধান:

  • Process List: SHOW PROCESSLIST; দিয়ে দেখুন কে লক ধরে আছে
  • Kill Process: KILL [Process_ID]; দিয়ে সেশনটি বন্ধ করুন
  • Online Schema Change: লাইভ টেবিলে স্কিমা চেঞ্জ করতে pt-online-schema-change টুল ব্যবহার করুন

১৯.৪ Connection Errors (Too many connections)

এরর: ERROR 1040: Too many connections

🔍 কারণ:

  • ট্রাফিক স্পাইক হয়েছে
  • অ্যাপ্লিকেশনে কানেকশন পুল (Connection Pool) ঠিকমতো রিলিজ করছে না
  • স্লো কুয়েরির কারণে সব কানেকশন বিজি হয়ে আছে

✅ সমাধান:

  • Increase Limit: my.cnf ফাইলে max_connections বাড়ান (যেমন: ৫০০ বা ১০০০)
  • Connection Pooling: ব্যাকএন্ডে (Node/Java) অবশ্যই কানেকশন পুল ব্যবহার করুন এবং আইডল কানেকশন টাইমআউট সেট করুন
  • Read Replica: রিড ট্রাফিক স্লেভ সার্ভারে পাঠিয়ে দিন

১৯.৫ Charset / Collation Issues (Emoji সমস্যা)

সমস্যা: ডেটাবেসে বাংলা লেখা বা ইমোজি (😊) সেভ করলে ??? বা গার্বেজ দেখায়। অথবা Incorrect string value এরর দেয়।

🔍 কারণ:

আপনি utf8 ব্যবহার করছেন, যা ৩ বাইট। ইমোজির জন্য ৪ বাইট দরকার।

✅ সমাধান:

সবসময় utf8mb4 ব্যবহার করুন।

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

টেবিল কনভার্ট করতে:

ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

১৯.৬ Disk Full Error (বিপজ্জনক)

সমস্যা: সার্ভার ক্র্যাশ করছে, লগে বলছে No space left on device

🔍 কারণ:

  • Binlogs: বাইনারি লগ ফাইল জমে শত শত জিবি হয়ে গেছে
  • Temp Tables: কোনো খারাপ কুয়েরি বিশাল টেম্প ফাইল বানিয়েছে

✅ সমাধান:

-- Clean Binlogs
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;
  • Auto Expiry: কনফিগারেশনে binlog_expire_logs_seconds সেট করুন
  • Move Data: লজিক্যাল ভলিউম বাড়ান বা ডেটা ডিরেক্টরি বড় ডিস্কে সরান

১৯.৭ Query using Wrong Index / No Index

লক্ষণ: সিপিইউ ইউসেজ ১০০% হয়ে আছে।

ডিটেকশন: EXPLAIN কমান্ড এবং Slow Query Log। যদি দেখেন rows কলামে বিশাল সংখ্যা (যেমন ১ মিলিয়ন) স্ক্যান হচ্ছে, তার মানে ইনডেক্স কাজ করছে না।

✅ সমাধান:

  • WHERE ক্লজের কলামগুলোর জন্য কম্পোজিট ইনডেক্স তৈরি করুন
  • ইনডেক্স রি-বিল্ড করুন (OPTIMIZE TABLE)

১৯.৮ Replication Lag

লক্ষণ: স্লেভ সার্ভারে ডেটা আপডেট হতে দেরি হচ্ছে (Seconds_Behind_Master > 0)।

✅ সমাধান:

  • Parallel Workers: স্লেভকে মাল্টি-থ্রেডেড করুন (slave_parallel_workers = 4)
  • Heavy Query: স্লেভে ভারী রিপোর্ট জেনারেশন বন্ধ করুন বা আলাদা অ্যানালিটিক্স নোড ব্যবহার করুন
  • Hardware: মাস্টারের চেয়ে স্লেভ যেন দুর্বল কনফিগারেশনের না হয়

১৯.৯ Temp Table Overflow (Disk I/O Spike)

সমস্যা: কুয়েরি খুব স্লো, ডিস্ক I/O অনেক হাই।

🔍 কারণ:

GROUP BY বা ORDER BY করার সময় মেমোরিতে জায়গা না হলে MySQL ডিস্কে টেম্পোরারি টেবিল বানায়। বিশেষ করে TEXT বা BLOB কলাম সিলেক্ট করলে এটি সাথে সাথেই ডিস্কে চলে যায়।

✅ সমাধান:

  • Increase Memory: tmp_table_size এবং max_heap_table_size বাড়ান
  • Optimize: প্রয়োজন না হলে TEXT কলাম কুয়েরিতে আনবেন না

১৯.১০ MySQL using too much RAM

সমস্যা: সার্ভারের র‍্যাম ফুল, ওএস MySQL-কে কিল (OOM Kill) করে দিচ্ছে।

✅ সমাধান:

  • innodb_buffer_pool_size: মোট র‍্যামের ৬০-৭০% এর বেশি দেবেন না
  • max_connections কমান যদি দরকার না হয়
  • প্রতিটি কানেকশনের জন্য sort_buffer_size এবং join_buffer_size ডিফল্ট (ছোট) রাখুন

১৯.১১ MySQL Crash Recovery

কারণ: হার্ডওয়্যার ফেইলর বা পাওয়ার লস।

✅ রিকভারি:

  • সাধারণত InnoDB অটোমেটিক রিকভার করে (Redo Log ব্যবহার করে)
  • লগ চেক করুন: /var/log/mysql/error.log

১৯.১২ InnoDB Corruption (The Nightmare)

এরর: InnoDB: Corruption detected, Page checksum mismatch

🔍 কারণ:

ডিস্কের ফিজিক্যাল সমস্যা বা র‍্যামের সমস্যা।

✅ সমাধান (Emergency Mode):

  • my.cnf ফাইলে innodb_force_recovery সেট করুন
  • Level 1-3: সেফ, শুধু রিড করা যাবে। ডাম্প (mysqldump) নিয়ে নিন
  • Level 4-6: রিস্কি, ডেটা লস হতে পারে
  • রিকভার করার পর নতুন ইনস্টলেশনে ডেটা রিস্টোর করুন

১৯.১৩ Long-running Queries Freeze System

সমস্যা: কেউ একজন বিশাল রিপোর্টিং কুয়েরি চালিয়েছে, বাকি সব ট্রানজেকশন স্লো।

✅ সমাধান:

  • রিপোর্টিং কুয়েরি সবসময় Read Replica তে চালান
  • কুয়েরিতে LIMIT ব্যবহার করুন
  • প্রোডাকশন টাইমে ভারী কুয়েরি চালাবেন না

১৯.১৪ Slow COUNT(*)

সমস্যা: SELECT COUNT(*) FROM users রেজাল্ট দিতে ১০ সেকেন্ড নিচ্ছে।

✅ সমাধান:

  • যদি এক্সাক্ট সংখ্যার দরকার না হয়, SHOW TABLE STATUS এর Rows কলাম ব্যবহার করুন (ইন্সট্যান্ট)
  • অ্যাপ্লিকেশনে (Redis) কাউন্টার ক্যাশ করে রাখুন

১৯.১৫ DELETE Millions of Rows

❌ ভুল:

DELETE FROM logs WHERE date < '2023-01-01';

(এটি সার্ভার হ্যাং করে দেবে)

✅ সঠিক (Chunks):

DELETE FROM logs WHERE date < '2023-01-01' LIMIT 5000;

(লুপ চালিয়ে করুন)

Partitioning: যদি টেবিল পার্টিশন করা থাকে, তবে DROP PARTITION এক সেকেন্ডে কাজ করবে।

১৯.১৬ Large ALTER TABLE

সমস্যা: কলাম এড করতে গিয়ে টেবিল লক হয়ে আছে।

✅ সমাধান:

  • pt-online-schema-change: এটি ব্যবহার করলে টেবিল লক ছাড়াই স্কিমা চেঞ্জ করা যায়
  • gh-ost: গিটহাবের টুল

১৯.১৭ MySQL Error Codes Cheat Sheet

ইন্টারভিউ এবং কাজের জন্য এই কোডগুলো মুখস্থ রাখা ভালো:

Error CodeMeaningQuick Fix
1045Access deniedইউজারনেম/পাসওয়ার্ড বা হোস্ট পারমিশন চেক করুন
2006MySQL server has gone awayপ্যাকেট সাইজ অনেক বড় (max_allowed_packet বাড়ান) বা কানেকশন টাইমআউট
1213Deadlock foundকুয়েরি রি-ট্রাই করুন
1205Lock wait timeout exceededঅন্য কোনো ট্রানজেকশন লক ধরে রেখেছে। প্রসেস কিল করুন
1114The table is fullডিস্ক ফুল বা কনফিগ লিমিট
1062Duplicate entryইউনিক কনস্ট্রেইন্ট ভায়োলেশন
1292Incorrect datetime valueডেট ফরম্যাট ঠিক করুন

১৯.১৮ Senior-Level Checklist

প্রোডাকশন এনভায়রনমেন্ট স্টেবল রাখতে এই রুলসগুলো মেনে চলুন:

  • স্লো কুয়েরি লগ অন রাখুন এবং সপ্তাহে একবার চেক করুন
  • ব্যাকআপ এবং রিস্টোর প্রসেস টেস্ট করুন
  • সার্ভার মনিটরিং (CPU, RAM, Disk, IOPS) সেটআপ করুন (PMM বা Grafana দিয়ে)
  • কানেকশন পুল এবং টাইমআউট সঠিকভাবে কনফিগার করুন
  • root ইউজার রিমোটলি ডিজেবল রাখুন

❓ Interview Q&A

Q: MySQL has gone away এরর কেন হয়?

সাধারণত দুটি কারণে: ১. কানেকশন টাইমআউট হয়ে গেছে (wait_timeout)। ২. ক্লায়েন্ট এমন কোনো প্যাকেট পাঠিয়েছে যা max_allowed_packet এর চেয়ে বড় (যেমন বিশাল ইমেজ বা BLOB)।

Q: TRUNCATE এবং DELETE এর মধ্যে ট্রাবলশুটিং পার্থক্য কী?

DELETE স্লো এবং লগ জেনারেট করে (রোলব্যাক সম্ভব)। TRUNCATE ফাস্ট এবং মেটাডেটা রিসেট করে (রোলব্যাক সম্ভব নয় - DDL)। বড় টেবিল খালি করতে TRUNCATE নিরাপদ যদি রোলব্যাক দরকার না হয়।

🎯 অধ্যায় ১৯ এর সারাংশ (Summary)

এই অধ্যায়ে আমরা শিখলাম:

  • Slow Query: EXPLAIN দিয়ে চেক করুন, ইনডেক্স যোগ করুন
  • Deadlock: Fixed Order + Retry Logic
  • Connection: max_connections বাড়ান, Connection Pool ব্যবহার করুন
  • Charset: সবসময় utf8mb4 ব্যবহার করুন
  • Delete Millions: ছোট ব্যাচে DELETE করুন (LIMIT 1000)
  • Error Codes: 1045, 2006, 1213, 1205 - মনে রাখুন

✨ PART 19 শেষ। আপনি এখন যেকোনো ডেটাবেস ডিজাস্টার হ্যান্ডেল করতে প্রস্তুত। পরবর্তী অধ্যায়ে আমরা শিখব MySQL for Developers—যেখানে আমরা দেখব কোড লেভেলে (Node/PHP/Laravel) কীভাবে ডেটাবেস কানেকশন এবং কুয়েরি অপটিমাইজ করতে হয়।

প্রস্তুত তো? 🚀

🔒 কপিরাইট সুরক্ষিত কন্টেন্ট 🔒

কপি, স্ক্রিনশট, প্রিন্ট করা সম্পূর্ণ নিষিদ্ধ।