Exécution de MySQL 5.1.57 sur InnoDB et avez un problème de verrouillage de la base de données.
J'ai deux sessions distinctes connectées à une seule base de données MySQL. Lors de la première session, j'exécute une longue requête sélectionnée (techniquement une requête lente) sur la table A. Puis sur l'autre connexion, je gère une petite requête de mise à jour sur la table B.
Edit: Comme décrit au fond de ce sujet, ce problème se produit également lorsque les tables/requêtes sont dans des bases de données distinctes tout à fait, et ne se limite pas aux tables/requêtes sont dans la même base de données.
Pour une raison quelconque, la mise à jour sur la table B ne terminera pas tant que la recherche de la requête de sélection longue, comme si elles sont sur la même connexion. De plus, la "liste de processus" montre la deuxième requête en tant que "éléments de libération", alors qu'il attend d'exécuter.
Existe-t-il des paramètres ou des problèmes de configuration qui entraîneraient ces requêtes de s'exécuter séquentiellement plutôt que simultanément?
Merci d'avance pour l'aide.
Tableau A
CREATE TABLE `history` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`log` text NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id_idx` (`user_id`),
CONSTRAINT `history_user_id_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=364398 DEFAULT CHARSET=utf8
Tableau B
CREATE TABLE `client` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`root_id` int(11) DEFAULT NULL,
`salesperson_id` int(11) DEFAULT NULL,
`name` varchar(127) DEFAULT NULL,
`notes` text,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `root_id_idx` (`root_id`),
KEY `salesperson_id_idx` (`salesperson_id`),
CONSTRAINT `client_root_id_client_id` FOREIGN KEY (`root_id`) REFERENCES `client` (`id`) ON DELETE CASCADE,
CONSTRAINT `client_salesperson_id_user_id` FOREIGN KEY (`salesperson_id`) REFERENCES `user` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=757 DEFAULT CHARSET=utf8
Query 1 :
SELECT *
FROM `history`
WHERE log LIKE '%a%' ORDER BY log ASC LIMIT 0, 20000; // (fictitious query to replicate the issue)
Prend environ 10 secondes pour courir
Query 2 :
UPDATE `client` SET name = 'Test Name' WHERE id = 24; // hangs until query 1 is complete
Informations de version MySQL
+ ------------------------- + ------------------ ------------- + | Nom de variable | Valeur | + ------------------------- + ----------------- --------------- + | Innodb_version | 1.0.16 | [.____] | Protocol_version | 10 | [.____] | Version | 5.1.57-LOG | | VERSION_COMMENT | MySQL Community Server (GPL) | [.____] | VERSION_COMPILE_MACHINE | x86_64 | | Version_Compile_os | Inconnu-Linux-gnu | + -------------------------- + ---------------- -------------------- +
Remarque: il s'agit d'un serveur Amazon RDS (M1.Large)
variables globales innodb
+ --------------------------------- + ---------- -------------- + | variable_name | Valeur | [. .____] + --------------------------------- + -------- + ---------------- | have_innodb | OUI | [. .____] | ignore_builtin_innodb | ON | | innodb_adaptive_flushing | ON | | innodb_adaptive_hash_index | ON | | innodb_additional_mem_pool_size | 2097152 | [. .____] | innodb_autoextend_increment | 8 | [. .____] | innodb_autoinc_lock_mode | 1 | [. .____] | innodb_buffer_pool_size | 5882511360 | [. .____] | innodb_change_buffering | inserts | [. .____] | innodb_checksums | ON | | innodb_commit_concurrency | 0 | [. .____] | innodb_concurrency_tickets | 500 | [. .____] | innodb_data_file_path | ibdata1: 10M: autoextend | [. .____] | innodb_data_home_dir |/Rdsdbdata/db/InnoDB | [. .____] | innodb_doublewrite | ON | | innodb_fast_shutdown | 1 | [. .____] | innodb_file_format | Antelope | [. .____] | innodb_file_format_check | Barracuda | [. .____] | innodb_file_per_table | ON | | innodb_flush_log_at_trx_commit | 1 | [. .____] | innodb_flush_method | O_DIRECT | [. .____] | innodb_force_recovery | 0 | [. .____] | innodb_io_capacity | 200 | [. .____] | innodb_lock_wait_timeout | 50 | [. .____] | innodb_locks_unsafe_for_binlog | OFF | [. .____] | innodb_log_buffer_size | 8388608 | [. .____] | innodb_log_file_size | 134217728 | [. .____] | innodb_log_files_in_group | 2 | [. .____] | innodb_log_group_home_dir |/Rdsdbdata/log/InnoDB | | innodb_max_dirty_pages_pct | 75 | [. .____] | innodb_max_purge_lag | 0 | [. .____] | innodb_mirrored_log_groups | 1 | [. .____] | innodb_old_blocks_pct | 37 | [. .____] | innodb_old_blocks_time | 0 | [. .____] | innodb_open_files | 300 | [. .____] | innodb_read_ahead_threshold | 56 | [. .____] | innodb_read_io_threads | 4 | [. .____] | innodb_replication_delay | 0 | [. .____] | innodb_rollback_on_timeout | OFF | [. .____] | innodb_spin_wait_delay | 6 | [. .____] | innodb_stats_method | nulls_equal | | innodb_stats_on_metadata | ON | | innodb_stats_sample_pages | 8 | [. .____] | innodb_strict_mode | OFF | [. .____] | innodb_support_xa | ON | | innodb_sync_spin_loops | 30 | [. .____] | innodb_table_locks | ON | | innodb_thread_concurrency | 0 | [. .____] | innodb_thread_sleep_delay | 10000 | [. .____] | innodb_use_sys_malloc | ON | | innodb_version | 1.0.16 | [. .____] | innodb_write_io_threads | 4 | [. .____] + --------------------------------- + -------- + ----------------
variables de connexion
+ ---------------------- + ------- + | variable_name | Valeur | + ---------------------- + ------- + | max_connections | 623 | [. .____] | max_user_connections | 0 | [. .____] + ---------------------- + ------- + [. .____]
problème persiste entre bases de données séparées
D'autres essais ont montré que nous pouvons recréer cette question sur une base de données différente tous ensemble, ce qui annule toute question sur le verrouillage de la table. Pour recréer cela, nous configurons le tableau A/requête 1 dans une base de données, et le tableau B/Requête 2 dans une base de données entièrement séparée (sur le même serveur). Lorsque la requête 1 est en cours d'exécution, Query 2 attend jusqu'à ce que # 1 est terminée avant de terminer.
Cela conduit moi de croire qu'il ya quelque chose pour tout le serveur (OS de verrouillage de fichier de niveau?) Qui est à l'origine de cette question, non liée à une base de données de l'une ou une table. Des idées?
subventions de l'utilisateur
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS,
REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES,
LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW,
CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.*
TO 'username'@'%' IDENTIFIED BY PASSWORD 'password' WITH GRANT OPTION
Après une semaine de transaction avec AWS Soutien et d'exécution de plusieurs points de repère, la réponse à la question est que RDS a des capuchons d'E/S via leur système d'exploitation/système de fichiers qui interdisent de grandes requêtes de manipuler correctement ce type de scénario.
Nous ne pouvions pas recréer ce problème sur une pile de lampes standard, même sur une micro-instance. Après avoir quitté les options, nous nous sommes tournés vers AWS pour leur soutien.
Nous avons fourni l'ensemble de données exact, configurons une instance RDS pour AWS à tester et à condition que les instructions exactes comment recréer le problème. RDS a pu recréer la question et après leurs tests, ils sont revenus avec cette réponse:
"RDS a enquêté sur cette enquête et il utilise essentiellement le disque I/O (écrit) qui conduit à la deuxième requête étant lente." ... "MySQL utilise une table temporaire pour cela, ce qui conduit à la base de données effectuant de nombreuses écrivies malgré une sélection."
Donc, en effet, car il s'agit d'un goulot d'étranglement généré par RDS, ce scénario ne se produira probablement que sur RDS et non une installation MySQL régulière.
En fin de compte: si vous avez ce problème, passez à une configuration de base de données différente.
Votre première requête demande 20 000 rangées. ce qui est victime de victime ici ???
Votre pool Buffer InnoDB et vos fichiers journaux.
À cause de SELECT * FROM history WHERE log LIKE '%a%' ORDER BY log ASC LIMIT 0, 20000;
, toutes les pages de données de la table d'historique sont de hogging InnoDb Ressources.
Depuis que vous utilisez Amazon RDS, vous ne pouvez pas redimensionner les fichiers journaux Innodb. Ils sont toujours 128m sous tous les modèles RDS MySQL. Votre piscine tampon peut être remplie (vous avez 5882511360 ensemble pour celui-ci, soit 5610m ou 5,4785g). Naturellement, plus grand modèle signifie plus d'iops.
Vous pouvez exécuter ceci pour voir à quel point la piscine tampon est pleine
SELECT FORMAT(A.num * 100.0 / B.num,2) BufferPoolFullPct FROM
(SELECT variable_value num FROM information_schema.global_status
WHERE variable_name = 'Innodb_buffer_pool_pages_data') A,
(SELECT variable_value num FROM information_schema.global_status
WHERE variable_name = 'Innodb_buffer_pool_pages_total') B;
Un autre aspect que je vois est le champ log
(texte). Vous demandez un ORDER BY
sur cette grosse colonne.
Vous devez modifier la première requête pour accélérer la sélection. En d'autres termes, aller chercher des morceaux d'histoire plus petits.
Si vous ne pouvez pas modifier les données ou la requête, vous ne pouvez rien configurer sauf pour passer à m1.xlarge (livré avec 11922309120 en tant que piscine tampon taille = 11370m = 11.1035g) Bien que la taille du fichier de journal soit toujours bloquée à 128 m.
En dehors de l'infrastructure, il est possible de choisir de bloquer les inserts, les mises à jour et la suppression dans INNODB.
J'ai écrit à ce sujet avant
Nous avons eu le même problème. Mais notre serveur n'était pas dans le nuage.
Notre système d'exploitation Ubuntu avait été défini sur CFQ. Cela a affamé les insertions/mises à jour sur la table sélectionnée. Nous sommes passés à l'option Date limite pour notre problème d'IO-Scheduler et le problème de blocage a été parti.
cat /sys/block/sda/queue/scheduler
date limite d'anticipation noop [CFQ]
echo deadline > /sys/block/sda/queue/scheduler
cat /sys/block/sda/queue/scheduler
noop anticipatif [date limite] cfq