सबसे लोकप्रिय InnoDB त्रुटियों में से एक है InnoDB लॉक प्रतीक्षा समय समाप्त हो गया है, उदाहरण के लिए:
SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
उपरोक्त का सीधा सा मतलब है कि लेन-देन innodb_lock_wait_timeout पर पहुंच गया है, जबकि एक विशेष लॉक प्राप्त करने की प्रतीक्षा कर रहा है जो 50 सेकंड के लिए डिफ़ॉल्ट है। सामान्य कारण हैं:
- आक्रामक लेन-देन इतना तेज़ नहीं है कि वह innodb_lock_wait_timeout अवधि के भीतर लेन-देन को कमिट या रोलबैक कर सके।
- आक्रामक लेन-देन किसी अन्य लेन-देन द्वारा पंक्ति लॉक जारी होने की प्रतीक्षा कर रहा है।
एक InnoDB लॉक वेटिंग टाइमआउट के प्रभाव
InnoDB लॉक वेटिंग टाइमआउट दो प्रमुख प्रभाव पैदा कर सकता है:
- असफल कथन डिफ़ॉल्ट रूप से वापस नहीं लाया जा रहा है।
- भले ही innodb_rollback_on_timeout सक्षम हो, जब लेन-देन में कोई स्टेटमेंट विफल हो जाता है, तब भी ROLLBACK COMMIT की तुलना में अधिक महंगा ऑपरेशन है।
आइए प्रभाव को बेहतर ढंग से समझने के लिए एक सरल उदाहरण के साथ खेलें। डेटाबेस mydb में निम्नलिखित दो तालिकाओं पर विचार करें:
mysql> CREATE SCHEMA mydb;
mysql> USE mydb;
पहली तालिका (तालिका 1):
mysql> CREATE TABLE table1 ( id INT PRIMARY KEY AUTO_INCREMENT, data VARCHAR(50));
mysql> INSERT INTO table1 SET data = 'data #1';
दूसरी तालिका (तालिका 2):
mysql> CREATE TABLE table2 LIKE table1;
mysql> INSERT INTO table2 SET data = 'data #2';
हमने अपने लेन-देन दो अलग-अलग सत्रों में निम्नलिखित क्रम में निष्पादित किए:
आदेश देना | लेन-देन #1 (T1) | लेन-देन #2 (T2) |
1 | तालिका 1 से * चुनें; (ठीक है) | तालिका 1 से * चुनें; (ठीक है) |
2 | अद्यतन तालिका1 डेटा सेट करें ='T1 पंक्ति को अपडेट कर रहा है' जहां id =1; (ठीक है) | |
3 | अपडेट टेबल2 डेटा सेट करें ='T2 पंक्ति को अपडेट कर रहा है' जहां आईडी =1; (ठीक है) | |
4 | अद्यतन तालिका1 डेटा सेट करें ='T2 पंक्ति को अपडेट कर रहा है' जहां आईडी =1; (थोड़ी देर के लिए रुक जाता है और अंत में एक त्रुटि देता है "लॉक प्रतीक्षा समय समाप्त हो गया; लेनदेन को फिर से शुरू करने का प्रयास करें") | |
5 | COMMIT; (ठीक है) | |
6 | COMMIT; (ठीक है) |
mysql> SELECT * FROM table1 WHERE id = 1;
+----+-----------------------------------+
| id | data |
+----+-----------------------------------+
| 1 | T1 is updating the row |
+----+-----------------------------------+
mysql> SELECT * FROM table2 WHERE id = 1;
+----+-----------------------------------+
| id | data |
+----+-----------------------------------+
| 1 | T2 is updating the row |
+----+-----------------------------------+
T2 के सफलतापूर्वक प्रतिबद्ध होने के बाद, तालिका 1 और तालिका 2 दोनों के लिए एक ही आउटपुट "T2 पंक्ति को अपडेट कर रहा है" प्राप्त करने की उम्मीद होगी, लेकिन परिणाम बताते हैं कि केवल तालिका 2 को अपडेट किया गया था। कोई यह सोच सकता है कि यदि किसी लेन-देन में कोई त्रुटि आती है, तो लेन-देन में सभी विवरण स्वतः वापस आ जाएंगे, या यदि कोई लेनदेन सफलतापूर्वक किया जाता है, तो पूरे विवरण को परमाणु रूप से निष्पादित किया गया था। यह गतिरोध के लिए सही है, लेकिन InnoDB लॉक वेटिंग टाइमआउट के लिए नहीं।
जब तक आप innodb_rollback_on_timeout=1 सेट नहीं करते (डिफ़ॉल्ट 0 - अक्षम है), InnoDB लॉक प्रतीक्षा टाइमआउट त्रुटि के लिए स्वचालित रोलबैक नहीं होने वाला है। इसका मतलब है, डिफ़ॉल्ट सेटिंग का पालन करके, MySQL विफल नहीं होगा और पूरे लेनदेन को रोलबैक नहीं करेगा, न ही टाइम आउट स्टेटमेंट को फिर से प्रयास करेगा और अगले स्टेटमेंट को COMMIT या ROLLBACK तक पहुंचने तक संसाधित करेगा। यह बताता है कि लेनदेन T2 आंशिक रूप से क्यों प्रतिबद्ध था!
InnoDB दस्तावेज़ स्पष्ट रूप से कहता है "InnoDB केवल लेन-देन टाइमआउट पर अंतिम विवरण को वापस रोल करता है। डिफ़ॉल्ट रूप से"। इस मामले में, हमें InnoDB द्वारा प्रस्तावित लेनदेन परमाणुता नहीं मिलती है। ACID अनुपालन में परमाणुता या तो हमें लेन-देन के सभी या कुछ भी नहीं मिलती है, जिसका अर्थ है कि आंशिक लेनदेन केवल अस्वीकार्य है।
एक InnoDB लॉक वेट टाइमआउट से निपटना
इसलिए, यदि आप एक InnoDB लॉक प्रतीक्षा त्रुटि का सामना करने पर ऑटो-रोलबैक के लिए लेन-देन की अपेक्षा कर रहे हैं, ठीक उसी तरह जैसे गतिरोध में होता है, तो MySQL कॉन्फ़िगरेशन फ़ाइल में निम्न विकल्प सेट करें:
innodb_rollback_on_timeout=1
एक MySQL पुनरारंभ की आवश्यकता है। MySQL-आधारित क्लस्टर को परिनियोजित करते समय, ClusterControl हर नोड पर हमेशा innodb_rollback_on_timeout=1 सेट करेगा। इस विकल्प के बिना, आपके आवेदन को विफल कथन का पुन:प्रयास करना होगा, या लेन-देन की परमाणुता को बनाए रखने के लिए स्पष्ट रूप से रोलबैक करना होगा।
यह सत्यापित करने के लिए कि कॉन्फ़िगरेशन सही तरीके से लोड है या नहीं:
mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_rollback_on_timeout';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| innodb_rollback_on_timeout | ON |
+----------------------------+-------+
यह जांचने के लिए कि क्या नया कॉन्फ़िगरेशन काम करता है, हम com_rollback काउंटर को ट्रैक कर सकते हैं जब यह त्रुटि होती है:
mysql> SHOW GLOBAL STATUS LIKE 'com_rollback';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_rollback | 1 |
+---------------+-------+
अवरुद्ध लेनदेन को ट्रैक करना
ऐसे कई स्थान हैं जहां हम अवरुद्ध लेनदेन या बयानों को ट्रैक करने के लिए देख सकते हैं। आइए लेन-देन अनुभाग के तहत InnoDB इंजन की स्थिति को देखकर शुरू करें:
mysql> SHOW ENGINE INNODB STATUS\G
------------
TRANSACTIONS
------------
...
---TRANSACTION 3100, ACTIVE 2 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 50, OS thread handle 139887555282688, query id 360 localhost ::1 root updating
update table1 set data = 'T2 is updating the row' where id = 1
------- TRX HAS BEEN WAITING 2 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6 page no 4 n bits 72 index PRIMARY of table `mydb`.`table1` trx id 3100 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000001; asc ;;
1: len 6; hex 000000000c19; asc ;;
2: len 7; hex 020000011b0151; asc Q;;
3: len 22; hex 5431206973207570646174696e672074686520726f77; asc T1 is updating the row;;
------------------
---TRANSACTION 3097, ACTIVE 46 sec
2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1
MySQL thread id 48, OS thread handle 139887556167424, query id 358 localhost ::1 root
Trx read view will not see trx with id >= 3097, sees < 3097
उपरोक्त जानकारी से, हम उन लेन-देन का अवलोकन प्राप्त कर सकते हैं जो वर्तमान में सर्वर में सक्रिय हैं। लेन-देन 3097 वर्तमान में एक पंक्ति को लॉक कर रहा है जिसे लेनदेन 3100 द्वारा एक्सेस करने की आवश्यकता है। हालांकि, उपरोक्त आउटपुट हमें वास्तविक क्वेरी टेक्स्ट नहीं बताता है जो हमें यह पता लगाने में मदद कर सकता है कि क्वेरी/कथन/लेनदेन के किस हिस्से की हमें आगे जांच करने की आवश्यकता है . अवरोधक MySQL थ्रेड आईडी 48 का उपयोग करके, आइए देखें कि हम MySQL प्रक्रिया सूची से क्या एकत्र कर सकते हैं:
mysql> SHOW FULL PROCESSLIST;
+----+-----------------+-----------------+--------------------+---------+------+------------------------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------------+--------------------+---------+------+------------------------+-----------------------+
| 4 | event_scheduler | localhost | <null> | Daemon | 5146 | Waiting on empty queue | <null> |
| 10 | root | localhost:56042 | performance_schema | Query | 0 | starting | show full processlist |
| 48 | root | localhost:56118 | mydb | Sleep | 145 | | <null> |
| 50 | root | localhost:56122 | mydb | Sleep | 113 | | <null> |
+----+-----------------+-----------------+--------------------+---------+------+------------------------+-----------------------+
थ्रेड आईडी 48 कमांड को 'स्लीप' के रूप में दिखाता है। फिर भी, यह हमें यह जानने में बहुत मदद नहीं करता है कि कौन से कथन अन्य लेनदेन को अवरुद्ध करते हैं। ऐसा इसलिए है क्योंकि इस लेनदेन में बयान निष्पादित किया गया है और यह खुला लेनदेन मूल रूप से इस समय कुछ भी नहीं कर रहा है। इस धागे के साथ क्या हो रहा है यह देखने के लिए हमें और नीचे जाने की जरूरत है।
MySQL 8.0 के लिए, InnoDB लॉक प्रतीक्षा इंस्ट्रुमेंटेशन प्रदर्शन_स्कीमा डेटाबेस (या sys डेटाबेस के अंदर innodb_lock_waits तालिका) के अंदर data_lock_waits तालिका के अंतर्गत उपलब्ध है। अगर लॉक वेटिंग इवेंट हो रहा है, तो हमें कुछ इस तरह दिखना चाहिए:
mysql> SELECT * FROM performance_schema.data_lock_waits\G
***************************[ 1. row ]***************************
ENGINE | INNODB
REQUESTING_ENGINE_LOCK_ID | 139887595270456:6:4:2:139887487554680
REQUESTING_ENGINE_TRANSACTION_ID | 3100
REQUESTING_THREAD_ID | 89
REQUESTING_EVENT_ID | 8
REQUESTING_OBJECT_INSTANCE_BEGIN | 139887487554680
BLOCKING_ENGINE_LOCK_ID | 139887595269584:6:4:2:139887487548648
BLOCKING_ENGINE_TRANSACTION_ID | 3097
BLOCKING_THREAD_ID | 87
BLOCKING_EVENT_ID | 9
BLOCKING_OBJECT_INSTANCE_BEGIN | 139887487548648
ध्यान दें कि MySQL 5.6 और 5.7 में, समान जानकारी innodb_lock_waits तालिका में info_schema डेटाबेस के अंतर्गत संग्रहीत है। BLOCKING_THREAD_ID मान पर ध्यान दें। हम इस जानकारी का उपयोग इस थ्रेड द्वारा क्रियान्वित किए जा रहे सभी कथनों को event_statements_history तालिका में देखने के लिए कर सकते हैं:
mysql> SELECT * FROM performance_schema.events_statements_history WHERE `THREAD_ID` = 87;
0 rows in set
ऐसा लगता है कि थ्रेड की जानकारी अब नहीं है। हम निम्नलिखित क्वेरी के साथ event_statements_history तालिका में thread_id कॉलम के न्यूनतम और अधिकतम मान की जांच करके सत्यापित कर सकते हैं:
mysql> SELECT min(`THREAD_ID`), max(`THREAD_ID`) FROM performance_schema.events_statements_history;
+------------------+------------------+
| min(`THREAD_ID`) | max(`THREAD_ID`) |
+------------------+------------------+
| 98 | 129 |
+------------------+------------------+
जिस थ्रेड को हम ढूंढ रहे थे (87) उसे टेबल से काट दिया गया है। हम event_statements_history तालिका के आकार को देखकर इसकी पुष्टि कर सकते हैं:
mysql> SELECT @@performance_schema_events_statements_history_size;
+-----------------------------------------------------+
| @@performance_schema_events_statements_history_size |
+-----------------------------------------------------+
| 10 |
+-----------------------------------------------------+
उपरोक्त का मतलब है कि event_statements_history केवल अंतिम 10 थ्रेड्स को स्टोर कर सकता है। सौभाग्य से, performance_schema में अधिक पंक्तियों को संग्रहीत करने के लिए एक और तालिका है, जिसे event_statements_history_long कहा जाता है, जो समान जानकारी संग्रहीत करता है लेकिन सभी थ्रेड्स के लिए और इसमें अधिक पंक्तियाँ हो सकती हैं:
mysql> SELECT @@performance_schema_events_statements_history_long_size;
+----------------------------------------------------------+
| @@performance_schema_events_statements_history_long_size |
+----------------------------------------------------------+
| 10000 |
+----------------------------------------------------------+
हालाँकि, यदि आप पहली बार event_statements_history_long तालिका को क्वेरी करने का प्रयास करते हैं, तो आपको एक खाली परिणाम मिलेगा। यह अपेक्षित है क्योंकि डिफ़ॉल्ट रूप से, यह उपकरण MySQL में अक्षम है जैसा कि हम निम्नलिखित setup_consumers तालिका में देख सकते हैं:
mysql> SELECT * FROM performance_schema.setup_consumers;
+----------------------------------+---------+
| NAME | ENABLED |
+----------------------------------+---------+
| events_stages_current | NO |
| events_stages_history | NO |
| events_stages_history_long | NO |
| events_statements_current | YES |
| events_statements_history | YES |
| events_statements_history_long | NO |
| events_transactions_current | YES |
| events_transactions_history | YES |
| events_transactions_history_long | NO |
| events_waits_current | NO |
| events_waits_history | NO |
| events_waits_history_long | NO |
| global_instrumentation | YES |
| thread_instrumentation | YES |
| statements_digest | YES |
+----------------------------------+---------+
टेबल इवेंट_स्टेटमेंट_हिस्ट्री_लॉन्ग को सक्रिय करने के लिए, हमें नीचे दिए गए सेटअप_उपभोक्ता तालिका को अपडेट करना होगा:
mysql> UPDATE performance_schema.setup_consumers SET enabled = 'YES' WHERE name = 'events_statements_history_long';
सत्यापित करें कि क्या अभी event_statements_history_long तालिका में पंक्तियाँ हैं:
mysql> SELECT count(`THREAD_ID`) FROM performance_schema.events_statements_history_long;
+--------------------+
| count(`THREAD_ID`) |
+--------------------+
| 4 |
+--------------------+
ठंडा। अब हम तब तक इंतजार कर सकते हैं जब तक कि InnoDB लॉक प्रतीक्षा घटना फिर से शुरू न हो जाए और जब ऐसा हो रहा हो, तो आपको data_lock_waits तालिका में निम्न पंक्ति देखनी चाहिए:
mysql> SELECT * FROM performance_schema.data_lock_waits\G
***************************[ 1. row ]***************************
ENGINE | INNODB
REQUESTING_ENGINE_LOCK_ID | 139887595270456:6:4:2:139887487555024
REQUESTING_ENGINE_TRANSACTION_ID | 3083
REQUESTING_THREAD_ID | 60
REQUESTING_EVENT_ID | 9
REQUESTING_OBJECT_INSTANCE_BEGIN | 139887487555024
BLOCKING_ENGINE_LOCK_ID | 139887595269584:6:4:2:139887487548648
BLOCKING_ENGINE_TRANSACTION_ID | 3081
BLOCKING_THREAD_ID | 57
BLOCKING_EVENT_ID | 8
BLOCKING_OBJECT_INSTANCE_BEGIN | 139887487548648
फिर से, हम उन सभी कथनों को फ़िल्टर करने के लिए BLOCKING_THREAD_ID मान का उपयोग करते हैं, जिन्हें इस थ्रेड द्वारा event_statements_history_long तालिका के विरुद्ध निष्पादित किया गया है:
mysql> SELECT `THREAD_ID`,`EVENT_ID`,`EVENT_NAME`, `CURRENT_SCHEMA`,`SQL_TEXT` FROM events_statements_history_long
WHERE `THREAD_ID` = 57
ORDER BY `EVENT_ID`;
+-----------+----------+-----------------------+----------------+----------------------------------------------------------------+
| THREAD_ID | EVENT_ID | EVENT_NAME | CURRENT_SCHEMA | SQL_TEXT |
+-----------+----------+-----------------------+----------------+----------------------------------------------------------------+
| 57 | 1 | statement/sql/select | <null> | select connection_id() |
| 57 | 2 | statement/sql/select | <null> | SELECT @@VERSION |
| 57 | 3 | statement/sql/select | <null> | SELECT @@VERSION_COMMENT |
| 57 | 4 | statement/com/Init DB | <null> | <null> |
| 57 | 5 | statement/sql/begin | mydb | begin |
| 57 | 7 | statement/sql/select | mydb | select 'T1 is in the house' |
| 57 | 8 | statement/sql/select | mydb | select * from table1 |
| 57 | 9 | statement/sql/select | mydb | select 'some more select' |
| 57 | 10 | statement/sql/update | mydb | update table1 set data = 'T1 is updating the row' where id = 1 |
+-----------+----------+-----------------------+----------------+----------------------------------------------------------------+
अंत में, हमें अपराधी मिल गया। हम थ्रेड 57 की घटनाओं के अनुक्रम को देखकर बता सकते हैं कि उपरोक्त लेनदेन (T1) अभी भी समाप्त नहीं हुआ है (कोई COMMIT या ROLLBACK नहीं), और हम देख सकते हैं कि अंतिम कथन ने अद्यतन के लिए पंक्ति के लिए एक विशेष लॉक प्राप्त किया है। ऑपरेशन जो अन्य लेन-देन (T2) के लिए आवश्यक है और बस वहीं लटका हुआ है। यह बताता है कि हम MySQL प्रोसेसलिस्ट आउटपुट में 'स्लीप' क्यों देखते हैं।
जैसा कि हम देख सकते हैं, उपरोक्त SELECT स्टेटमेंट के लिए आपको पहले से thread_id मान प्राप्त करने की आवश्यकता है। इस क्वेरी को सरल बनाने के लिए, हम दोनों तालिकाओं में शामिल होने के लिए IN क्लॉज और एक सबक्वेरी का उपयोग कर सकते हैं। निम्न क्वेरी उपरोक्त की तरह एक समान परिणाम उत्पन्न करती है:
mysql> SELECT `THREAD_ID`,`EVENT_ID`,`EVENT_NAME`, `CURRENT_SCHEMA`,`SQL_TEXT` from events_statements_history_long WHERE `THREAD_ID` IN (SELECT `BLOCKING_THREAD_ID` FROM data_lock_waits) ORDER BY `EVENT_ID`;
+-----------+----------+-----------------------+----------------+----------------------------------------------------------------+
| THREAD_ID | EVENT_ID | EVENT_NAME | CURRENT_SCHEMA | SQL_TEXT |
+-----------+----------+-----------------------+----------------+----------------------------------------------------------------+
| 57 | 1 | statement/sql/select | <null> | select connection_id() |
| 57 | 2 | statement/sql/select | <null> | SELECT @@VERSION |
| 57 | 3 | statement/sql/select | <null> | SELECT @@VERSION_COMMENT |
| 57 | 4 | statement/com/Init DB | <null> | <null> |
| 57 | 5 | statement/sql/begin | mydb | begin |
| 57 | 7 | statement/sql/select | mydb | select 'T1 is in the house' |
| 57 | 8 | statement/sql/select | mydb | select * from table1 |
| 57 | 9 | statement/sql/select | mydb | select 'some more select' |
| 57 | 10 | statement/sql/update | mydb | update table1 set data = 'T1 is updating the row' where id = 1 |
+-----------+----------+-----------------------+----------------+----------------------------------------------------------------+
हालाँकि, जब भी InnoDB लॉक प्रतीक्षा घटना होती है, तो उपरोक्त क्वेरी को निष्पादित करना हमारे लिए व्यावहारिक नहीं है। एप्लिकेशन से त्रुटि के अलावा, आपको कैसे पता चलेगा कि लॉक प्रतीक्षा घटना हो रही है? हम निम्नलिखित सरल बैश स्क्रिप्ट के साथ इस क्वेरी निष्पादन को स्वचालित कर सकते हैं, जिसे track_lockwait.sh कहा जाता है:
$ cat track_lockwait.sh
#!/bin/bash
## track_lockwait.sh
## Print out the blocking statements that causing InnoDB lock wait
INTERVAL=5
DIR=/root/lockwait/
[ -d $dir ] || mkdir -p $dir
while true; do
check_query=$(mysql -A -Bse 'SELECT THREAD_ID,EVENT_ID,EVENT_NAME,CURRENT_SCHEMA,SQL_TEXT FROM events_statements_history_long WHERE THREAD_ID IN (SELECT BLOCKING_THREAD_ID FROM data_lock_waits) ORDER BY EVENT_ID')
# if $check_query is not empty
if [[ ! -z $check_query ]]; then
timestamp=$(date +%s)
echo $check_query > $DIR/innodb_lockwait_report_${timestamp}
fi
sleep $INTERVAL
done
निष्पादन योग्य अनुमति लागू करें और स्क्रिप्ट को पृष्ठभूमि में निष्क्रिय करें:
$ chmod 755 track_lockwait.sh
$ nohup ./track_lockwait.sh &
अब, हमें केवल /root/lockwait डायरेक्टरी के तहत रिपोर्ट तैयार होने की प्रतीक्षा करने की आवश्यकता है। डेटाबेस वर्कलोड और रो एक्सेस पैटर्न के आधार पर, आप शायद इस डायरेक्टरी के तहत बहुत सारी फाइलें देख सकते हैं। निर्देशिका की बारीकी से निगरानी करें अन्यथा यह बहुत अधिक रिपोर्ट फ़ाइलों से भर जाएगी।
यदि आप ClusterControl का उपयोग कर रहे हैं, तो आप प्रदर्शन -> लेन-देन लॉग के अंतर्गत लेन-देन लॉग सुविधा को सक्षम कर सकते हैं, जहां ClusterControl गतिरोध और लंबे समय से चल रहे लेन-देन पर एक रिपोर्ट प्रदान करेगा जो अपराधी को खोजने में आपके जीवन को आसान बना देगा।
निष्कर्ष
संक्षेप में, यदि हमें MySQL में "लॉक प्रतीक्षा समय समाप्त हो गया" त्रुटि का सामना करना पड़ता है, तो हमें पहले उन प्रभावों को समझने की आवश्यकता है जो इस तरह की त्रुटि से हमारे बुनियादी ढांचे पर पड़ सकते हैं, फिर आक्रामक लेनदेन को ट्रैक करें और कार्रवाई करें यह या तो track_lockwait.sh जैसी शेल स्क्रिप्ट या ClusterControl जैसे डेटाबेस प्रबंधन सॉफ़्टवेयर के साथ होता है।
यदि आप शेल स्क्रिप्ट के साथ जाने का निर्णय लेते हैं, तो बस ध्यान रखें कि वे आपके पैसे बचा सकते हैं लेकिन आपका समय खर्च करेंगे, क्योंकि आपको उनके काम करने के तरीके के बारे में एक या दो चीज़ों को जानना होगा, आवेदन करें अनुमतियां, और संभवत:उन्हें पृष्ठभूमि में चलाने के लिए, और यदि आप शेल जंगल में खो जाते हैं, तो हम मदद कर सकते हैं।
आप जो कुछ भी लागू करने का निर्णय लेते हैं, हमें ट्विटर पर फॉलो करना सुनिश्चित करें या हमारे आरएसएस फ़ीड की सदस्यता लें ताकि आपके सॉफ़्टवेयर और इसका समर्थन करने वाले डेटाबेस दोनों के प्रदर्शन को बेहतर बनाने के बारे में अधिक सुझाव प्राप्त हो सकें, जैसे कि यह पोस्ट MySQL में 6 सामान्य विफलता परिदृश्यों को कवर करती है।पी>