web-dev-qa-db-ja.com

「ALTER TABLE DROP PARTITION」時に「テーブルメタデータロックの待機」を回避しますか?

多くのユーザーがアクセスする必要があるいくつかのテーブルがあります。

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)))

ロックせずにこれを達成するための効率的な方法は何ですか?

6
quanta

あなたが求めていることは不可能です。ストレージエンジンに関係なく、あらゆる種類のDDLがテーブルをロックします。アクティブなテーブルからパーティションを削除する必要がある場合は、次のことを行う必要があります。

  1. MySQLレプリケーションのセットアップ(まだ行っていない場合)
  2. スレーブに対してv3_cam_dateを含むすべてのSELECTを実行します
  3. スレーブ上のSTOP SLAVE;
  4. マスターでALTER TABLE ... DROP PARTITIONを実行します。
  5. v3_cam_dateを含むすべてのSELECTをマスターに対して実行する
  6. スレーブ上のSTART SLAVE;ALTER TABLE ... DROP PARTITIONをスレーブに複製)

これはおそらく唯一の手段です。他の唯一の手段は、ALTER TABLE ... DROP PARTITIONを待つだけです。

この状況では、アプリケーションに何らかの介入が必要です。アプリケーション内では、マスター上に書き込みDBVIPを作成し、次の3つのオプションのいずれかで読み取りDBVIPを使用する必要があります。

オプション1

  • スレーブで読み取りDBVIPを保持する

オプション#2

  • 読み取りDBVIPをマスターに保持する
  • ALTER TABLEを実行する必要がある場合は、Read DBVIPをスレーブに移動します
  • ALTER TABLEが完了したら、読み取りDBVIPをマスターに移動します

オプション#3

  • LoadBalancerでの読み取りDBVIPのセットアップ
  • オンデマンドでLoadBalanced DBVIPからマスターを削除する

オプション#1は、長期的には最も簡単な方法のようです。

8
RolandoMySQLDBA

この種の問題を回避するには、トランザクションを確実にコミットまたはロールバックしてください。

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が実行されたセッションを終了できます。

2
Sameer Kumar