多くのユーザーがアクセスする必要があるいくつかのテーブルがあります。
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) */
ユーザーがパーティションを削除したい場合ALTER TABLE v3_cam_date DROP PARTITION pcurrent_2013227
、多くのトランザクションがWaiting for table metadata lock
状態:
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)))
ロックせずにこれを達成するための効率的な方法は何ですか?
あなたが求めていることは不可能です。ストレージエンジンに関係なく、あらゆる種類のDDLがテーブルをロックします。アクティブなテーブルからパーティションを削除する必要がある場合は、次のことを行う必要があります。
v3_cam_date
を含むすべてのSELECTを実行しますSTOP SLAVE;
ALTER TABLE ... DROP PARTITION
を実行します。v3_cam_date
を含むすべてのSELECTをマスターに対して実行するSTART SLAVE;
(ALTER TABLE ... DROP PARTITION
をスレーブに複製)これはおそらく唯一の手段です。他の唯一の手段は、ALTER TABLE ... DROP PARTITION
を待つだけです。
この状況では、アプリケーションに何らかの介入が必要です。アプリケーション内では、マスター上に書き込みDBVIPを作成し、次の3つのオプションのいずれかで読み取りDBVIPを使用する必要があります。
ALTER TABLE
を実行する必要がある場合は、Read DBVIPをスレーブに移動しますALTER TABLE
が完了したら、読み取りDBVIPをマスターに移動しますオプション#1は、長期的には最も簡単な方法のようです。
この種の問題を回避するには、トランザクションを確実にコミットまたはロールバックしてください。
sELECTテーブルが共有モードでロックされているため。
ここに例があります
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
スリープモードにあるすべてのセッションを強制終了するか、SELECTが実行されたセッションを終了できます。