# MySQL Optimisation, Performance, and Logging

====================================================================================

## MySQL Optimisation

====================================================================================

#### MySQL Tuner Script

```
wget -O mysqltuner.pl mysqltuner.pl && perl mysqltuner.pl 
```

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">------------------------------------------------------------------------------------------------------------------------------------------------</span></span>

##### Check MySQL default config files

```
/usr/sbin/mysqld --verbose --help | grep -A 1 "Default options"
```

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">------------------------------------------------------------------------------------------------------------------------------------------------</span></span>

#### <span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">MySQL Variables</span></span>

<table border="1" id="bkmrk-innodb_buffer_pool_s" style="border-collapse: collapse; width: 100%; height: 537.109px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 130.578px;"><td style="height: 130.578px;">innodb\_buffer\_pool\_size</td><td style="height: 130.578px;">Specifies the size of the memory buffer used by InnoDB to cache data and indexes. Setting this appropriately can significantly improve read/write performance for InnoDB tables.  
  
***Recommendation:** For dedicated MySQL servers, set to 70-80% of available memory.*  
</td></tr><tr style="height: 113.781px;"><td style="height: 113.781px;">query\_cache\_size</td><td style="height: 113.781px;">Controls the size of the query cache, which stores results of SELECT queries to speed up subsequent identical queries. Effective use depends on query patterns and workload.  
  
***Recommendation:** Enable and configure it based on the workload if beneficial; otherwise, keep it disabled.*  
</td></tr><tr style="height: 130.578px;"><td style="height: 130.578px;">key\_buffer\_size</td><td style="height: 130.578px;">Sets the size of the buffer used for index blocks for MyISAM tables. Adjusting this can enhance performance for MyISAM-based applications.  
  
***Recommendation:** Set according to the size of your MyISAM indexes; for mixed storage engines, allocate more memory to InnoDB buffer pool.*  
</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">max\_connections</td><td style="height: 63.3906px;">Limits the number of simultaneous client connections allowed to the MySQL server. Properly setting this prevents resource exhaustion and maintains server stability.</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">tmp\_table\_size =

max\_heap\_table\_size =

</td><td style="height: 63.3906px;">Define the maximum size of temporary tables created in memory. Optimizing these can reduce disk I/O and improve query performance.</td></tr><tr style="height: 35.3906px;"><td style="height: 35.3906px;">sort\_buffer\_size=256K

</td><td style="height: 35.3906px;">Buffer size for sorts.</td></tr><tr><td>max\_connections=151

</td><td> Maximum number of simultaneous client connections.  
  
***Recommendation:** Increase based on expected load and server capacity.*  
</td></tr><tr><td>innodb\_log\_file\_size

</td><td>Size of each log file in the log group.

***Recommendation:** Increase to improve performance, particularly for write-heavy applications.*

</td></tr><tr><td>innodb\_log\_buffer\_size

</td><td>Size of the buffer for log data before it is written to disk.  
  
***Recommendation:** Increase for high transaction throughput to reduce disk I/O.*

</td></tr></tbody></table>

#### Logging

<table border="1" id="bkmrk-slow_query_log-enabl" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>slow\_query\_log</td><td>Enables logging of queries that exceed a certain execution time.  
  
***Recommendation:** Enable and use for identifying slow queries; configure `long_query_time` to set the threshold.*  
</td></tr><tr><td>log\_error = /var/log/mysql.log</td><td>Path to the error log file.  
  
  
</td></tr><tr><td>general\_log=/var/log/mysql.log</td><td>Enables logging of all queries.  
  
***Recommendation:** Use with caution due to potential performance impact and disk consumption; useful for debugging.*  
</td></tr></tbody></table>

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">====================================================================================</span></span>

#### MyISAM v InnoDB

**InnoDB has row-level locking.** MyISAM only has full table-level locking.

- **InnoDB:**
    - Default storage engine in MySQL.
    - Supports ACID-compliant transactions.
    - Provides row-level locking and foreign key constraints.
    - Uses a clustered index for primary key storage.
- **MyISAM:**
    - Older storage engine, primarily used before InnoDB became the default.
    - Provides table-level locking.
    - Faster for read-heavy operations.
    - Does not support transactions or foreign keys.

<span class="TextRun SCXO176926821 BCX0" data-contrast="auto" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO176926821 BCX0">Check table engine:</span></span><span class="EOP SCXO176926821 BCX0"> </span>

```
mysql -e "SELECT TABLE_SCHEMA as DbName ,TABLE_NAME as TableName ,ENGINE as Engine FROM information_schema.TABLES WHERE ENGINE='MyISAM' AND TABLE_SCHEMA NOT IN('mysql','information_schema','performance_schema');"
```

<span class="TextRun SCXO176926821 BCX0" data-contrast="auto" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO176926821 BCX0">Generate commands to swap table engine from MyISAM to InnoDB</span></span>

```
mysql -e "SELECT CONCAT('ALTER TABLE \`', TABLE_SCHEMA,'\`.\`',TABLE_NAME, '\` ENGINE = InnoDB;') FROM information_schema.TABLES WHERE ENGINE='MyISAM' AND TABLE_SCHEMA NOT IN('mysql','information_schema','performance_schema');"
```

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">====================================================================================</span></span>

### Deadlocks

A deadlock is a situation where two or more transactions are unable to proceed because each one is waiting for a lock held by the other transaction. This creates a cycle of dependencies that cannot be resolved without external intervention.

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">------------------------------------------------------------------------------------------------------------------------------------------------</span></span>

#### Check for deadlocks:  


<div class="dark bg-gray-950 rounded-md border-[0.5px] border-token-border-medium" id="bkmrk-show-engine-innodb-s"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-keyword">SHOW</span> ENGINE INNODB STATUS;`</div><div class="overflow-y-auto p-4" dir="ltr">  
</div></div><div class="dark bg-gray-950 rounded-md border-[0.5px] border-token-border-medium" id="bkmrk-show-status-like-%27ta"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-keyword">SHOW</span> STATUS <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'Table_locks_%'</span>;`</div></div>- **Table\_locks\_immediate**: The number of times a table lock was acquired immediately.
- **Table\_locks\_waited**: The number of times a table lock couldn't be acquired immediately and had to wait.

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">------------------------------------------------------------------------------------------------------------------------------------------------</span></span>

##### Deadlock logging

This will cause MySQL to log all deadlock errors to the error log, which can then be examined for more details.

<div class="dark bg-gray-950 rounded-md border-[0.5px] border-token-border-medium" id="bkmrk-set-global-innodb_pr"><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-keyword">SET</span> <span class="hljs-keyword">GLOBAL</span> innodb_print_all_deadlocks <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;`</div></div><span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">------------------------------------------------------------------------------------------------------------------------------------------------</span></span>

MySQL Monitoring software such as NewRelic can provide further information on deadlocks and general MySQL performance issues.

##### Resolving Deadlocks

Once identified, you can resolve deadlocks by:

- **Rewriting Queries**: Optimize queries to reduce lock contention.
- **Using Consistent Locking Order**: Ensure all transactions acquire locks in a consistent order.
- **Adding Indexes**: Improve query performance and reduce the duration of locks.
- **Reducing Transaction Size**: Break large transactions into smaller ones to reduce lock time.
- **Implementing Retries**: Add retry logic in your application to handle deadlocks gracefully.

<span class="TextRun SCXO108973998 BCX0" data-contrast="none" lang="EN-GB" xml:lang="EN-GB"><span class="NormalTextRun SCXO108973998 BCX0">------------------------------------------------------------------------------------------------------------------------------------------------</span></span>