When dealing with sluggish INSERT/UPDATE operations in InnoDB, start by checking the following metrics:
SHOW ENGINE INNODB STATUS;
SHOW STATUS LIKE 'innodb_row_lock%';
SHOW PROCESSLIST;
For transactional workloads, consider these approaches:
-- Bad practice: Individual autocommit transactions
INSERT INTO orders (customer_id, amount) VALUES (1, 100);
INSERT INTO order_items (order_id, product_id) VALUES (LAST_INSERT_ID(), 5);
-- Better: Batch in single transaction
START TRANSACTION;
INSERT INTO orders (customer_id, amount) VALUES (1, 100);
SET @order_id = LAST_INSERT_ID();
INSERT INTO order_items (order_id, product_id) VALUES (@order_id, 5);
COMMIT;
For mass inserts, use multi-value syntax:
-- Slow approach (multiple statements)
INSERT INTO log_entries (message) VALUES ('entry1');
INSERT INTO log_entries (message) VALUES ('entry2');
-- Optimized bulk insert
INSERT INTO log_entries (message) VALUES
('entry1'), ('entry2'), ('entry3'), ('entry4');
Balance between query performance and write overhead:
-- Remove unused indexes that slow down writes
SELECT * FROM sys.schema_unused_indexes
WHERE object_schema = 'your_db';
-- Consider covering indexes for frequent operations
ALTER TABLE products
ADD INDEX idx_cover (category_id, price, stock);
Key configuration parameters for write-heavy workloads:
innodb_flush_log_at_trx_commit = 2 # Trade durability for speed
innodb_buffer_pool_size = 70% of RAM
innodb_log_file_size = 1-2GB
innodb_io_capacity = 2000 # For SSDs
innodb_thread_concurrency = 0 # Let InnoDB decide
To identify and address locking contention:
-- Check current locks
SELECT * FROM performance_schema.data_locks;
-- Find blocking transactions
SELECT * FROM sys.innodb_lock_waits;
-- Solution: Optimize transaction isolation
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Implement these in your code:
// Python example with connection pooling
import mysql.connector
from mysql.connector import pooling
dbconfig = {
"database": "app_db",
"user": "app_user",
"password": "secret"
}
connection_pool = mysql.connector.pooling.MySQLConnectionPool(
pool_name = "app_pool",
pool_size = 10,
**dbconfig
)
# Usage:
with connection_pool.get_connection() as conn:
cursor = conn.cursor()
cursor.executemany(
"INSERT INTO metrics (time, value) VALUES (%s, %s)",
[(t1,v1), (t2,v2), ...]
)
conn.commit()
When standard optimizations aren't enough:
-- Consider temporary tables for complex ETL
CREATE TEMPORARY TABLE temp_import LIKE products;
LOAD DATA INFILE '/path/to/data.csv' INTO TABLE temp_import;
INSERT INTO products SELECT * FROM temp_import;
DROP TEMPORARY TABLE temp_import;
-- Partitioning for time-series data
ALTER TABLE sensor_data
PARTITION BY RANGE (UNIX_TIMESTAMP(created_at)) (
PARTITION p202301 VALUES LESS THAN (UNIX_TIMESTAMP('2023-02-01')),
PARTITION p202302 VALUES LESS THAN (UNIX_TIMESTAMP('2023-03-01'))
);
When dealing with sluggish INSERT/UPDATE performance in InnoDB, start by examining these key metrics:
-- Check current locks
SELECT * FROM performance_schema.events_waits_current
WHERE EVENT_NAME LIKE '%lock%';
-- Monitor transaction throughput
SHOW ENGINE INNODB STATUS;
-- Check for long-running transactions
SELECT * FROM information_schema.innodb_trx
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 10;
These my.cnf adjustments often yield immediate improvements:
[mysqld]
innodb_buffer_pool_size = 4G # 50-70% of available RAM
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2 # For better write performance
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_read_io_threads = 8
innodb_write_io_threads = 8
Common anti-patterns I've fixed in production:
// Bad: Single-row operations in loop
foreach ($items as $item) {
$db->beginTransaction();
$db->query("UPDATE products SET stock = stock - 1 WHERE id = ?", [$item['id']]);
$db->commit();
}
// Good: Batch operation
$db->beginTransaction();
$stmt = $db->prepare("UPDATE products SET stock = stock - 1 WHERE id = ?");
foreach ($items as $item) {
$stmt->execute([$item['id']]);
}
$db->commit();
For massive data loads, consider these approaches:
-- Multi-value INSERT
INSERT INTO table (col1, col2) VALUES
(v1, v2), (v3, v4), (v5, v6);
-- LOAD DATA INFILE (5-10x faster than INSERTs)
LOAD DATA INFILE '/path/to/data.csv'
INTO TABLE my_table
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
-- Temporary table approach
CREATE TEMPORARY TABLE temp_table LIKE target_table;
-- Bulk insert into temp table
INSERT INTO target_table SELECT * FROM temp_table;
DROP TEMPORARY TABLE temp_table;
Indexes speed up reads but slow down writes. Balance them carefully:
-- Check unused indexes that slow down writes
SELECT * FROM sys.schema_unused_indexes;
-- Consider using covering indexes
ALTER TABLE orders ADD INDEX idx_covering (customer_id, status, created_at);
Set up these metrics in your monitoring system:
-- Track InnoDB row operations
SELECT name, count
FROM information_schema.innodb_metrics
WHERE name LIKE '%rows%';
-- Check for table fragmentation
SELECT table_name,
data_free / (data_length + index_length) AS frag_ratio
FROM information_schema.tables
WHERE table_schema = 'your_db' AND data_length > 0;