From f8bbf3b1b03eece0c124f1281e2e682f5937c17a Mon Sep 17 00:00:00 2001 From: Carlos Salguero Date: Tue, 14 Mar 2017 17:16:30 -0300 Subject: [PATCH] PT-94 Fixed updates to PK while osc is running --- bin/pt-online-schema-change | 14 +- t/pt-online-schema-change/issue-1646713.t | 100 +++++++++++ .../samples/issue-1646713.sql | 155 ++++++++++++++++++ 3 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 t/pt-online-schema-change/issue-1646713.t create mode 100644 t/pt-online-schema-change/samples/issue-1646713.sql diff --git a/bin/pt-online-schema-change b/bin/pt-online-schema-change index 09746696..3abaf3b5 100755 --- a/bin/pt-online-schema-change +++ b/bin/pt-online-schema-change @@ -10695,10 +10695,22 @@ sub create_triggers { = "CREATE TRIGGER `${prefix}_ins` AFTER INSERT ON $orig_tbl->{name} " . "FOR EACH ROW " . "REPLACE INTO $new_tbl->{name} ($qcols) VALUES ($new_vals)"; + + my $upd_index_cols = join(" AND ", map { + my $new_col = $_; + my $old_col = $old_col_for{$new_col} || $new_col; + my $new_qcol = $q->quote($new_col); + my $old_qcol = $q->quote($old_col); + "OLD.$old_qcol <=> NEW.$new_qcol" + } @{$tbl_struct->{keys}->{$del_index}->{cols}} ); + my $update_trigger = "CREATE TRIGGER `${prefix}_upd` AFTER UPDATE ON $orig_tbl->{name} " . "FOR EACH ROW " - . "REPLACE INTO $new_tbl->{name} ($qcols) VALUES ($new_vals)"; + . "BEGIN " + . "DELETE IGNORE FROM $new_tbl->{name} WHERE !($upd_index_cols) AND $del_index_cols;" + . "REPLACE INTO $new_tbl->{name} ($qcols) VALUES ($new_vals);" + . "END "; my @triggers = ( ['del', $delete_trigger], diff --git a/t/pt-online-schema-change/issue-1646713.t b/t/pt-online-schema-change/issue-1646713.t new file mode 100644 index 00000000..f077349f --- /dev/null +++ b/t/pt-online-schema-change/issue-1646713.t @@ -0,0 +1,100 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use threads; +use threads::shared; + +use English qw(-no_match_vars); +use Test::More; + +use Data::Dumper; +use PerconaTest; +use Sandbox; +use SqlModes; +use File::Temp qw/ tempdir /; + +plan tests => 2; + +require "$trunk/bin/pt-online-schema-change"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); + +our ($master_dbh, $master_dsn) = $sb->start_sandbox( + server => 'master', + type => 'master', + env => q/FORK="pxc" BINLOG_FORMAT="ROW"/, +); + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} + +# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic +# so we need to specify --set-vars innodb_lock_wait_timeout=3 else the +# tool will die. +my @args = (qw(--set-vars innodb_lock_wait_timeout=3)); +my $output; +my $exit_status; +my $sample = "t/pt-online-schema-change/samples/"; + +$sb->load_file('master', "$sample/issue-1646713.sql"); + +sub start_thread { + my ($dsn_opts, $sleep_time) = @_; + my $dp = new DSNParser(opts=>$dsn_opts); + my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); + my $dbh = $sb->get_dbh_for('master'); + diag("Thread started: Sleeping $sleep_time seconds before updating the PK field for row with id=1 in test.sbtest"); + sleep($sleep_time); + $dbh->do("UPDATE `test`.`o1` SET id=0 WHERE id=1"); + diag("Row updated"); +} +my $thr = threads->create('start_thread', $dsn_opts, 3); +$thr->detach(); +threads->yield(); + +diag("Starting osc. A row will be updated in a different thread."); +my $dir = tempdir( CLEANUP => 1 ); +$output = output( + sub { pt_online_schema_change::main(@args, "$master_dsn,D=test,t=o1", + '--execute', + '--alter', "ADD COLUMN c INT", + '--chunk-size', '1', + ), + }, +); + + +like( + $output, + qr/Successfully altered/s, + "bug-1646713 duplicate rows in _t_new for UPDATE t set pk=0 where pk=1", +); + +my $rows = $master_dbh->selectrow_arrayref( + "SELECT COUNT(*) FROM `test`.`o1` WHERE id=0"); +is( + $rows->[0], + 1, + "bug-1646713 correct value after updating the PK" +) or diag(Dumper($rows)); + +threads->exit(); + +$master_dbh->do("DROP DATABASE IF EXISTS test"); + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +$sb->stop_sandbox(qw(master)); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; diff --git a/t/pt-online-schema-change/samples/issue-1646713.sql b/t/pt-online-schema-change/samples/issue-1646713.sql new file mode 100644 index 00000000..e4ac06e0 --- /dev/null +++ b/t/pt-online-schema-change/samples/issue-1646713.sql @@ -0,0 +1,155 @@ +DROP DATABASE IF EXISTS `test`; +CREATE DATABASE IF NOT EXISTS `test`; +USE test; + +-- MySQL dump 10.13 Distrib 5.7.14-8, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: test +-- ------------------------------------------------------ +-- Server version 5.7.14-8-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `sbtest` +-- + +DROP TABLE IF EXISTS `o1`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `o1` ( + `id` int +(10) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1100001 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `sbtest` +-- + +LOCK TABLES `o1` WRITE; +/*!40000 ALTER TABLE `o1` DISABLE KEYS */; +INSERT INTO `o1` VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9), +(10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25),(26),(27),(28),(29), +(30),(31),(32),(33),(34),(35),(36),(37),(38),(39), +(40),(41),(42),(43),(44),(45),(46),(47),(48),(49), +(50),(51),(52),(53),(54),(55),(56),(57),(58),(59), +(60),(61),(62),(63),(64),(65),(66),(67),(68),(69), +(70),(71),(72),(73),(74),(75),(76),(77),(78),(79), +(80),(81),(82),(83),(84),(85),(86),(87),(88),(89), +(90),(91),(92),(93),(94),(95),(96),(97),(98),(99), +(100),(101),(102),(103),(104),(105),(106),(107),(108),(109), +(110),(111),(112),(113),(114),(115),(116),(117),(118),(119), +(120),(121),(122),(123),(124),(125),(126),(127),(128),(129), +(130),(131),(132),(133),(134),(135),(136),(137),(138),(139), +(140),(141),(142),(143),(144),(145),(146),(147),(148),(149), +(150),(151),(152),(153),(154),(155),(156),(157),(158),(159), +(160),(161),(162),(163),(164),(165),(166),(167),(168),(169), +(170),(171),(172),(173),(174),(175),(176),(177),(178),(179), +(180),(181),(182),(183),(184),(185),(186),(187),(188),(189), +(190),(191),(192),(193),(194),(195),(196),(197),(198),(199), +(200),(201),(202),(203),(204),(205),(206),(207),(208),(209), +(210),(211),(212),(213),(214),(215),(216),(217),(218),(219), +(220),(221),(222),(223),(224),(225),(226),(227),(228),(229), +(230),(231),(232),(233),(234),(235),(236),(237),(238),(239), +(240),(241),(242),(243),(244),(245),(246),(247),(248),(249), +(250),(251),(252),(253),(254),(255),(256),(257),(258),(259), +(260),(261),(262),(263),(264),(265),(266),(267),(268),(269), +(270),(271),(272),(273),(274),(275),(276),(277),(278),(279), +(280),(281),(282),(283),(284),(285),(286),(287),(288),(289), +(290),(291),(292),(293),(294),(295),(296),(297),(298),(299), +(300),(301),(302),(303),(304),(305),(306),(307),(308),(309), +(310),(311),(312),(313),(314),(315),(316),(317),(318),(319), +(320),(321),(322),(323),(324),(325),(326),(327),(328),(329), +(330),(331),(332),(333),(334),(335),(336),(337),(338),(339), +(340),(341),(342),(343),(344),(345),(346),(347),(348),(349), +(350),(351),(352),(353),(354),(355),(356),(357),(358),(359), +(360),(361),(362),(363),(364),(365),(366),(367),(368),(369), +(370),(371),(372),(373),(374),(375),(376),(377),(378),(379), +(380),(381),(382),(383),(384),(385),(386),(387),(388),(389), +(390),(391),(392),(393),(394),(395),(396),(397),(398),(399), +(400),(401),(402),(403),(404),(405),(406),(407),(408),(409), +(410),(411),(412),(413),(414),(415),(416),(417),(418),(419), +(420),(421),(422),(423),(424),(425),(426),(427),(428),(429), +(430),(431),(432),(433),(434),(435),(436),(437),(438),(439), +(440),(441),(442),(443),(444),(445),(446),(447),(448),(449), +(450),(451),(452),(453),(454),(455),(456),(457),(458),(459), +(460),(461),(462),(463),(464),(465),(466),(467),(468),(469), +(470),(471),(472),(473),(474),(475),(476),(477),(478),(479), +(480),(481),(482),(483),(484),(485),(486),(487),(488),(489), +(490),(491),(492),(493),(494),(495),(496),(497),(498),(499), +(500),(501),(502),(503),(504),(505),(506),(507),(508),(509), +(510),(511),(512),(513),(514),(515),(516),(517),(518),(519), +(520),(521),(522),(523),(524),(525),(526),(527),(528),(529), +(530),(531),(532),(533),(534),(535),(536),(537),(538),(539), +(540),(541),(542),(543),(544),(545),(546),(547),(548),(549), +(550),(551),(552),(553),(554),(555),(556),(557),(558),(559), +(560),(561),(562),(563),(564),(565),(566),(567),(568),(569), +(570),(571),(572),(573),(574),(575),(576),(577),(578),(579), +(580),(581),(582),(583),(584),(585),(586),(587),(588),(589), +(590),(591),(592),(593),(594),(595),(596),(597),(598),(599), +(600),(601),(602),(603),(604),(605),(606),(607),(608),(609), +(610),(611),(612),(613),(614),(615),(616),(617),(618),(619), +(620),(621),(622),(623),(624),(625),(626),(627),(628),(629), +(630),(631),(632),(633),(634),(635),(636),(637),(638),(639), +(640),(641),(642),(643),(644),(645),(646),(647),(648),(649), +(650),(651),(652),(653),(654),(655),(656),(657),(658),(659), +(660),(661),(662),(663),(664),(665),(666),(667),(668),(669), +(670),(671),(672),(673),(674),(675),(676),(677),(678),(679), +(680),(681),(682),(683),(684),(685),(686),(687),(688),(689), +(690),(691),(692),(693),(694),(695),(696),(697),(698),(699), +(700),(701),(702),(703),(704),(705),(706),(707),(708),(709), +(710),(711),(712),(713),(714),(715),(716),(717),(718),(719), +(720),(721),(722),(723),(724),(725),(726),(727),(728),(729), +(730),(731),(732),(733),(734),(735),(736),(737),(738),(739), +(740),(741),(742),(743),(744),(745),(746),(747),(748),(749), +(750),(751),(752),(753),(754),(755),(756),(757),(758),(759), +(760),(761),(762),(763),(764),(765),(766),(767),(768),(769), +(770),(771),(772),(773),(774),(775),(776),(777),(778),(779), +(780),(781),(782),(783),(784),(785),(786),(787),(788),(789), +(790),(791),(792),(793),(794),(795),(796),(797),(798),(799), +(800),(801),(802),(803),(804),(805),(806),(807),(808),(809), +(810),(811),(812),(813),(814),(815),(816),(817),(818),(819), +(820),(821),(822),(823),(824),(825),(826),(827),(828),(829), +(830),(831),(832),(833),(834),(835),(836),(837),(838),(839), +(840),(841),(842),(843),(844),(845),(846),(847),(848),(849), +(850),(851),(852),(853),(854),(855),(856),(857),(858),(859), +(860),(861),(862),(863),(864),(865),(866),(867),(868),(869), +(870),(871),(872),(873),(874),(875),(876),(877),(878),(879), +(880),(881),(882),(883),(884),(885),(886),(887),(888),(889), +(890),(891),(892),(893),(894),(895),(896),(897),(898),(899), +(900),(901),(902),(903),(904),(905),(906),(907),(908),(909), +(910),(911),(912),(913),(914),(915),(916),(917),(918),(919), +(920),(921),(922),(923),(924),(925),(926),(927),(928),(929), +(930),(931),(932),(933),(934),(935),(936),(937),(938),(939), +(940),(941),(942),(943),(944),(945),(946),(947),(948),(949), +(950),(951),(952),(953),(954),(955),(956),(957),(958),(959), +(960),(961),(962),(963),(964),(965),(966),(967),(968),(969), +(970),(971),(972),(973),(974),(975),(976),(977),(978),(979), +(980),(981),(982),(983),(984),(985),(986),(987),(988),(989), +(990),(991),(992),(993),(994),(995),(996),(997),(998),(999), +(10000); +/*!40000 ALTER TABLE `o1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2017-03-14 15:19:26