【问题标题】:How can this query break my mysql replication?此查询如何破坏我的 mysql 复制?
【发布时间】:2011-12-16 11:20:12
【问题描述】:

我有一个标准的单向主从设置。 这些表有 MyIsam 存储引擎。

版本是:

大师 服务器版本:5.1.41-3ubuntu12.10-log 协议版本:10

第一个奴隶: 服务器版本:5.1.41-3ubuntu12.10 协议版本:10

第二个奴隶: 服务器版本:5.1.49-1ubuntu8.1 协议版本:10

我已将除专用复制用户之外的所有用户设置为在从属设备上只读。

在主服务器上执行的以下语句未正确复制:

$insert = "INSERT INTO search_affiliate_product
(film_id, ext_id, affiliate_id, `status`, url, created_at)
SELECT film_id, LPAD(imdb, 7, '0'), $affiliate_id, 5, CONCAT('http://www.imdb.com/title/tt', LPAD(imdb, 7, '0'),'/'), NOW() FROM search_film_entity
WHERE film_id NOT IN (SELECT film_id FROM search_affiliate_product WHERE affiliate_id = $affiliate_id)
AND status IN (5, 9)
AND release_year BETWEEN 0 AND $year
AND imdb > 0";

从机收到此错误:

Error 'Duplicate entry '271769' for key 'PRIMARY'' on query. Default database:     'flimmit_search_14'. Query: 'INSERT INTO `search_affiliate_product` (`affiliate_id`,     `ext_id`, `url`, `status`, `film_id`, `created_at`, `updated_at`) VALUES ('16', '1991/JohnnyStecchino', 'http://www.cineman.ch/movie/1991/JohnnyStecchino/review.html', '5', '102164', '2011-10-26 02:30:05', '2011-10-26 02:30:05')'

我还做了一些其他的观察:

  • 语句通过 bin 日志(中继日志和主日志)“按原样”传输,因此不包含插入的显式数据,但带有 select 和 subselect 的整个语句在slave,依赖本地数据。

  • 如果我查看主表和从表并按主键排序,我会看到上述语句在两台服务器上生成的一系列插入。之前和之后的行是同步的。该语句生成的该范围内的许多行也是相等的。但也有分歧。

我认为问题可能是由于并发sql事务。这样插入过程会干扰其他插入,因此值会混淆,而在从属设备上不会发生这种情况,因为日志是按程序处理的。

我还注意到,在语句的插入过程中,似乎插入了一些未在另一台服务器上插入的 ID,并且插入了一些重复项(字段 ext_id 上的重复项,该字段由另一台服务器的 imdb 字段填充表,这是独一无二的......

我真的被困在这里了。

有什么建议吗?我真的很想知道为什么会这样。

我考虑过选择所有 id 并在应用程序中创建单个插入语句或在执行表之前锁定表。我认为这可以解决它,但我真的很想了解这个错误。

下一个奇怪的事情是第二个奴隶似乎运行良好!只有第一个奴隶有问题。我只是不明白。

【问题讨论】:

    标签: mysql database replication myisam


    【解决方案1】:

    这种复制只能在 innodb 下可靠地完成,并在客户端进行以下设置

    [mysqld]
    innodb_flush_log_at_trx_commit=1
    sync_binlog=1
    

    【讨论】:

      【解决方案2】:

      我会说您在search_affiliate_product 表上的(猜测)ID 列的 AUTO_INCREMENT 计数器已经失步。具体来说,我怀疑第一个从站上的 AUTO_INCREMENT 值以某种方式领先于等效的主站值。我猜从服务器 2 上的值保持在步中,这就是为什么那里不会发生错误。

      如果您在主服务器、服务器 1 和服务器 2 上运行以下命令,您应该能够看到这是否正确:

      select auto_increment
       from information_schema.tables
       where table_name = 'search_affiliate_product';
      

      可能发生这种情况的原因之一是数据直接插入到从服务器 1 上的 search_affiliate_product 中,即不是通过主服务器,因此增加了 AUTO_INCREMENT 值并导致它领先于主服务器。

      一个简单的解决方法是使用从服务器 1 获取最大 ID:

      select max(id) from search_affiliate_product;
      

      假设您得到一个值 123456。将 100 加到它上面以获得好运,然后更改主 search_affiliate_product 表的 auto_increment 值:

      alter table search_affiliate_product auto_increment = 123556;
      

      然后尝试再次运行插入。

      如果不是这样,那我猜它又回到了绘图板上!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-15
        • 2011-01-19
        • 1970-01-01
        • 2019-09-26
        • 2019-01-15
        • 2011-01-30
        • 1970-01-01
        • 2020-08-09
        相关资源
        最近更新 更多