## 15.19 InnoDB 和 MySQL 复制

[](<>)

可以以副本上的存储引擎与源上的存储引擎不同的方式使用复制。例如，您可以将修改复制到`InnoDB`表上的源到`MyISAM`副本上的表。有关更多信息，请参阅，[第 17.4.4 节，“使用具有不同源和副本存储引擎的复制”](replication-solutions-diffengines.html).

有关设置副本的信息，请参阅[第 17.1.2.6 节，“设置副本”](replication-setup-replicas.html)， 和[第 17.1.2.5 节，“选择数据快照的方法”](replication-snapshot-method.html).要在不删除源或现有副本的情况下创建新副本，请使用[MySQL 企业备份](mysql-enterprise-backup.html)产品。

源上失败的事务不影响复制。MySQL 复制基于 MySQL 写入修改数据的 SQL 语句的二进制日志。失败的事务（例如，由于外键违规或回滚）不会写入二进制日志，因此不会发送到副本。看[第 13.3.1 节，“START TRANSACTION、COMMIT 和 ROLLBACK 语句”](commit.html).

**复制和级联。**级联动作`InnoDB`源上的表在副本上执行*只要*如果共享外键关系的表使用`InnoDB`在源和副本上。无论您使用的是基于语句的复制还是基于行的复制，都是如此。假设您已经开始复制，然后在源上创建两个表，其中`InnoDB`被定义为默认存储引擎，使用如下[`创建表`](create-table.html)声明：

```
CREATE TABLE fc1 (
    i INT PRIMARY KEY,
    j INT
);

CREATE TABLE fc2 (
    m INT PRIMARY KEY,
    n INT,
    FOREIGN KEY ni (n) REFERENCES fc1 (i)
        ON DELETE CASCADE
);
```

如果副本有`MyISAM`定义为默认存储引擎，在副本上创建相同的表，但它们使用`MyISAM`存储引擎和`外键`选项被忽略。现在我们在源上的表中插入一些行：

```
source> INSERT INTO fc1 VALUES (1, 1), (2, 2);
Query OK, 2 rows affected (0.09 sec)
Records: 2  Duplicates: 0  Warnings: 0

source> INSERT INTO fc2 VALUES (1, 1), (2, 2), (3, 1);
Query OK, 3 rows affected (0.19 sec)
Records: 3  Duplicates: 0  Warnings: 0
```

此时，在源和副本上，表`fc1`包含 2 行和表`fc2`包含 3 行，如下所示：

```
source> SELECT * FROM fc1;
+---+------+
| i | j    |
+---+------+
| 1 |    1 |
| 2 |    2 |
+---+------+
2 rows in set (0.00 sec)

source> SELECT * FROM fc2;
+---+------+
| m | n    |
+---+------+
| 1 |    1 |
| 2 |    2 |
| 3 |    1 |
+---+------+
3 rows in set (0.00 sec)

replica> SELECT * FROM fc1;
+---+------+
| i | j    |
+---+------+
| 1 |    1 |
| 2 |    2 |
+---+------+
2 rows in set (0.00 sec)

replica> SELECT * FROM fc2;
+---+------+
| m | n    |
+---+------+
| 1 |    1 |
| 2 |    2 |
| 3 |    1 |
+---+------+
3 rows in set (0.00 sec)
```

现在假设您执行以下操作[`删除`](delete.html)关于来源的声明：

```
source> DELETE FROM fc1 WHERE i=1;
Query OK, 1 row affected (0.09 sec)
```

由于级联，表`fc2`源上现在只包含 1 行：

```
source> SELECT * FROM fc2;
+---+---+
| m | n |
+---+---+
| 2 | 2 |
+---+---+
1 row in set (0.00 sec)
```

但是，级联不会在副本上传播，因为在副本上[`删除`](delete.html)为了`fc1`不删除任何行`fc2`.副本的副本`fc2`仍然包含最初插入的所有行：

```
replica> SELECT * FROM fc2;
+---+---+
| m | n |
+---+---+
| 1 | 1 |
| 3 | 1 |
| 2 | 2 |
+---+---+
3 rows in set (0.00 sec)
```

这种差异是由于级联删除由内部处理`InnoDB`存储引擎，这意味着不会记录任何更改。
