J'ai des tables que de nombreux utilisateurs doivent accéder à:
mysql> show create table v3_cam_date\G
*************************** 1. row ***************************
Table: v3_cam_date
Create Table: CREATE TABLE `v3_cam_date` (
`campaignid` mediumint(9) NOT NULL DEFAULT '0',
`totalclick` mediumint(9) unsigned NOT NULL DEFAULT '0',
`totalview` int(11) unsigned NOT NULL DEFAULT '0',
`realclick` mediumint(9) unsigned NOT NULL DEFAULT '0',
`clickcharge` mediumint(9) unsigned NOT NULL DEFAULT '0',
`viewcharge` int(11) unsigned NOT NULL DEFAULT '0',
`uv` mediumint(9) unsigned NOT NULL DEFAULT '0',
`uc` mediumint(9) unsigned NOT NULL DEFAULT '0',
`dt` date NOT NULL DEFAULT '0000-00-00',
`ctr` decimal(5,3) NOT NULL DEFAULT '0.000' COMMENT '=-1: meaning not available(N/A)',
`moneyc` int(11) unsigned NOT NULL DEFAULT '0',
`moneyv` int(11) unsigned NOT NULL DEFAULT '0',
KEY `ix_campaignid_dt` (`campaignid`,`dt`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (TO_DAYS(dt))
(PARTITION p0 VALUES LESS THAN (0) ENGINE = InnoDB,
PARTITION p01 VALUES LESS THAN (734502) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (734683) ENGINE = InnoDB,
PARTITION p03 VALUES LESS THAN (734863) ENGINE = InnoDB,
PARTITION p04 VALUES LESS THAN (734959) ENGINE = InnoDB,
PARTITION p5 VALUES LESS THAN (735141) ENGINE = InnoDB,
PARTITION p06 VALUES LESS THAN (735210) ENGINE = InnoDB,
PARTITION MERGER_2013227 VALUES LESS THAN (735291) ENGINE = InnoDB,
PARTITION pcurrent_2013227 VALUES LESS THAN (735292) ENGINE = InnoDB) */
Quand un utilisateur veut déposer une partition ALTER TABLE v3_cam_date DROP PARTITION pcurrent_2013227
, il peut causer de nombreuses transactions dans le Waiting for table metadata lock
Etat:
Id: 31560182
User: alice
Host: 192.168.3.40:36132
db: db
Command: Query
Time: 806
State: Waiting for table metadata lock
Info: SELECT COUNT(DISTINCT A.`campaignid`) INTO _campaigncomplete
FROM `ox_campaigns` A
INNER JOIN `selfserving_users` B ON B.`user_id` = A.`uid`
INNER JOIN `v3_cam_date` C ON C.`campaignid` = A.`campaignid`
WHERE A.`revenue_type` = 5 AND A.`deleted` = 0 AND A.`expire` = DATE_ADD( (SELECT `sys_date_cpc` FROM `000_sys_params_v4`) , INTERVAL 1 DAY)
AND A.`isExpired` = 0 AND IF( NAME_CONST('_permitid',3) = -1, 1=1, IF( NAME_CONST('_permitid',3) = 0, A.`uid` IN (SELECT C.`user_id` FROM `selfserving_users` C WHERE C.`groupid` = NAME_CONST('_groupid',17) ) ,A.`uid` = NAME_CONST('userid',5770)))
Quel est le moyen efficace d'accomplir cela sans verrouillage?
Ce que vous demandez est impossible. Indépendamment du moteur de stockage, DDL de tout type verrouille une table. Si vous devez supprimer une partition d'une table active, vous devriez:
v3_cam_date
contre l'esclaveSTOP SLAVE;
sur l'esclaveALTER TABLE ... DROP PARTITION
sur le maître.v3_cam_date
contre le maîtreSTART SLAVE;
sur l'esclave (reproduit ALTER TABLE ... DROP PARTITION
à l'esclave)C'est probablement votre seul recours. Le seul autre recours est de simplement attendre le ALTER TABLE ... DROP PARTITION
.
Cette situation nécessite une certaine intervention dans la demande. Dans votre application, vous devez créer un DBVIP d'écriture sur le maître et utiliser le DBVIP de lecture avec l'une des trois (3) options suivantes:
ALTER TABLE
, déplacez la lecture DBVIP à l'esclaveALTER TABLE
a été terminé, déplacez la lecture DBVIP au MasterL'option n ° 1 semble être la voie la plus simple à long terme.
Pour éviter ce type de problème, assurez-vous de commettre ou de retourner votre transaction.
en raison de la table Select est verrouillé en mode partagé.
Voici exemple
session1 > start transaction;
Query OK, 0 rows affected (0.00 sec)
session1 > select * from test order by id;
+----+------+
| id | a |
+----+------+
| 1 | x |
| 2 | y |
+----+------+
2 rows in set (0.00 sec)
session2 > ALTER TABLE test add column c char(32) default 'xyz';
session3 > show processlist;
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------------------------------+
| 1 | sameer | localhost | test | Sleep | 253| | NULL |
| 2 | sameer | localhost | test | Query | 3 | Waiting for table metadata lock | ALTER TABLE test add column c char(32) default 'xyz' |
| 3 | sameer | localhost | test | Query | 0 | NULL | show processlist |
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------------------------------+
3 rows in set (0.00 sec)
session1 > rollback;
Query OK, 0 rows affected (0.00 sec)
session2 > ALTER TABLE test add column c char(32) default 'xyz';
Query OK, 2 rows affected (46.32 sec)
Records: 2 Duplicates: 0 Warnings: 0
Vous pouvez tuer toutes les sessions qui sont en mode veille ou la session de sortie d'où sélectionnez l'exécution.