45

我有一张表分布在运行 MySql 4 的两台服务器上。我需要将它们合并到一台服务器中以用于我们的测试环境。

这些表实际上每个都有数百万条记录,它们在两台服务器上的原因是因为它们有多大。表的任何更改和分页都会给我们带来太大的性能损失。

因为它们在生产环境中,所以我不可能在现有服务器上以任何方式更改它们。

问题是主键是一个唯一的自动递增字段,因此存在交叉点。

我一直在试图弄清楚如何使用 mysqldump 命令忽略某些字段,但是 --disable-keys 只是改变了表,而不是完全摆脱了键。

在这一点上,看起来我需要修改数据库结构以利用主键的校验和或哈希作为实际上应该是唯一的两个唯一字段的组合......我真的不想做这个。

帮助!

4

10 回答 10

30

为了解决这个问题,我查找了这个问题,找到了@pumpkinthehead 的答案,并意识到我们需要做的就是用 NULL 查找+替换每一行中的主键,以便 mysql 将使用默认的 auto_increment 值。

(your complete mysqldump command) | sed -e "s/([0-9]*,/(NULL,/gi" > my_dump_with_no_primary_keys.sql

原始输出:

INSERT INTO `core_config_data` VALUES
    (2735,'default',0,'productupdates/configuration/sender_email_identity','general'),
    (2736,'default',0,'productupdates/configuration/unsubscribe','1'),

转换输出:

INSERT INTO `core_config_data` VALUES
    (NULL,'default',0,'productupdates/configuration/sender_email_identity','general'),
    (NULL,'default',0,'productupdates/configuration/unsubscribe','1'),

注意:这仍然是一个 hack;例如,如果您的自动增量列不是第一列,但 99% 的时间都解决了我的问题,它将失败。

于 2015-02-24T19:26:13.623 回答
28

如果您不关心 auto_increment 列的值是什么,那么只需加载第一个文件,重命名表,然后重新创建表并加载第二个文件。最后,使用

INSERT newly_created_table_name (all, columns, except, the, auto_increment, column)
       SELECT all, columns, except, the, auto_increment, column
         FROM renamed_table_name
于 2009-06-19T15:54:54.757 回答
13

您可以创建没有主键列的表视图,然后在该视图上运行 mysqldump。

因此,如果您的表“用户”有以下列:id、name、email

> CREATE VIEW myView AS
  SELECT name, email FROM users

编辑:啊,我明白了,我不确定是否还有其他方法。

于 2009-06-19T15:48:11.183 回答
7
  1. 克隆你的表
  2. 删除克隆表中的列
  3. 转储没有结构的克隆表(但使用 -c 选项获取完整插入)
  4. 在您想要的地方导入
于 2011-11-21T16:54:10.113 回答
7

这是一个彻头彻尾的痛苦。我通过运行类似的东西来解决这个问题

sed -e "s/([0-9]*,/(/gi" export.sql > expor2.sql 

在转储上摆脱主键,然后

sed -e "s/VALUES/(col1,col2,...etc.) VALUES/gi" LinxImport2.sql > LinxImport3.sql

对于除主键之外的所有列。当然,您必须小心([0-9]*,不要替换您真正想要的任何东西。

希望对某人有所帮助。

于 2012-04-12T20:30:27.833 回答
4
SELECT null as fake_pk, `col_2`, `col_3`, `col_4` INTO OUTFILE 'your_file'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM your_table;

LOAD DATA INFILE 'your_file' INTO TABLE your_table
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';

为了增加幻想,您可以在接收表上设置一个插入前触发器,该触发器在插入发生之前为到达行设置新的主键,从而使用常规转储并仍然清除您的 pk。没有经过测试,但对它很有信心。

于 2009-06-19T16:03:52.400 回答
2

使用虚拟临时主键:

mysqldump正常使用--opts -c。例如,您的主键是“id”。编辑输出文件并在表结构中添加一行“dummy_id”,其类型与“id”相同(当然不是主键)。然后修改INSERT语句并将“id”替换为“dummy_id”。导入后,删除“dummy_id”列。

于 2010-01-22T12:42:12.170 回答
0

jimyi 是在正确的轨道上。

这是自动增量键是 PITA 的原因之一。一种解决方案不是删除数据,而是添加数据。

CREATE VIEW myView AS
SELECT id*10+$x, name, email FROM users

(其中 $x 是唯一标识原始数据库的单个数字)在源数据库上创建视图(您暗示这可能是不可能的)或使用像 Autocracy 描述的提取例程或将数据加载到临时表中测试盒。

或者,不要在测试系统上创建表 - 而是为 src 数据放入单独的表,然后创建一个从它们两者中获取的视图:

CREATE VIEW users AS
(SELECT * FROM users_on_a) UNION (SELECT * FROM users_on_b)

C。

于 2010-01-22T13:15:48.357 回答
0

我一直在使用的解决方案是对我正在导出的数据进行常规 SQL 导出,然后使用 RegEx 查找和替换编辑器从插入语句中删除主键。我个人使用 Sublime Text,但我确信 TextMate、Notepad++ 等也可以这样做。

然后我只需通过将查询复制粘贴到 HeidiSQL 的查询窗口或 PHPMyAdmin 来运行查询应该插入数据的数据库。如果有很多数据,我将插入查询保存到 SQL 文件并改用文件导入。复制和粘贴大量文本通常会使 Chrome 冻结。

这听起来可能需要做很多工作,但我很少在导出和导入之间使用超过几分钟的时间。可能比我在接受的解决方案上使用的要少得多。我已经在几十万行上使用了这种解决方法而没有问题,但我认为当你达到数百万时它会出现问题。

于 2012-06-08T07:05:34.893 回答
0

我喜欢临时表路由。

create temporary table my_table_copy
select * from my_table;

alter table my_table_copy drop id;

// Use your favorite dumping method for the temporary table

像其他人一样,这不是一个万能的解决方案(特别是考虑到 OP 的数百万行),但即使是 10^6 行,它也需要几秒钟才能运行但可以工作。

于 2019-06-10T20:44:16.237 回答