这个查询如何破坏我的mysql复制?

时间:2011-10-27 12:14:53

标签: mysql database replication myisam

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

版本是:

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

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

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

我已将专用复制用户旁边的所有用户设置为仅在从属设备上读取。

在master上执行的以下语句未正确复制:

$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的整个语句在奴隶,依赖本地数据。

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

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

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

我真的被困在这里。

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

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

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

2 个答案:

答案 0 :(得分:2)

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

[mysqld]
innodb_flush_log_at_trx_commit=1
sync_binlog=1

答案 1 :(得分:1)

我会说ID表上(猜测)search_affiliate_product列的AUTO_INCREMENT计数器已经不合时宜了。具体来说,我怀疑第一个奴隶的AUTO_INCREMENT值以某种方式超过了等效的主值。我猜奴隶服务器2上的值仍然保持在步骤,这就是为什么不会出现错误的原因。

如果在master,server 1和server 2上运行以下命令,您应该能够看到是否为真:

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

可能发生这种情况的原因之一是数据直接插入到从服务器1上的search_affiliate_product,即不通过主服务器,因此增加AUTO_INCREMENT值并使其超前于主服务器。< / p>

对此的一个简单修复是使用以下命令从从属服务器1获取最大ID:

select max(id) from search_affiliate_product;

假设您获得的值为123456.为了好运而添加100,然后更改主search_affiliate_product表的auto_increment值:

alter table search_affiliate_product auto_increment = 123556;

然后再次尝试运行插入。

如果情况并非如此,那么我猜它会回到绘图板上!