mysql主主同步两个数据库同时写入,实现原理:自动增长主键不重复

本文介绍了一种解决多主自增长ID重复的方法,通过在不同服务器上设置auto_increment_offset和auto_increment_increment参数来确保ID的唯一性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

出现的问题(多主自增长ID重复)

 

解决方法:

我们只要保证两台服务器上插入的自增长数据不同就可以了

如:A查奇数IDB插偶数ID,当然如果服务器多的话,你可以定义算法,只要不同就可以了

 

在这里我们在A,B上加入参数,以实现奇偶插入

 

Amy.ini上加入参数

 

auto_increment_offset = 1

auto_increment_increment = 2

这样Aauto_increment字段产生的数值是:1, 3, 5, 7, …等奇数ID

 

Bmy.ini上加入参数

 

auto_increment_offset = 2

auto_increment_increment = 2

这样Bauto_increment字段产生的数值是:2, 4, 6, 8, …等偶数ID

 

可以看出,你的auto_increment字段在不同的服务器之间绝对不会重复,所以Master-Master结构就没有任何问题了。当然,你还可以使用3台,4台,或者N台服务器,只要保证auto_increment_increment = N 再设置一下auto_increment_offset为适当的初始值就可以了,那样,我们的MySQL可以同时有几十台主服务器,而不会出现自增长ID重复。

 

在这里我们说的是2MYSQL服务器,你也可以扩展到多台,实现方法类似

A -> B -> C-> D ->A

这样一个环形的备份结构就形成了,最后可要记住 自增长ID(主键)要设计好哦,否则会出错的。

<think>我们参考用户提供的引用内容,特别是引用[1]和引用[5]中关于Kettle实现MySQL到Oracle同步的信息。根据引用[1]的思路,我们可以采用以下方法:1.先获取MySQL中的老数据和Oracle中已同步的数据,然后通过转换统一字段,由Kettle根据关键字段和时间戳判断数据在目标端(Oracle)的操作类型(新、更新、删除或无操作)。2.引用[5]提到建立数据库连接时需要注意驱动问题。同时,结合我们之前讨论的同步方法(混合键量法),这里我们针对跨数据库场景(MySQL到Oracle)设计一个同步方案。具体步骤:一、环境准备1.确保Kettle(PentahoDataIntegration)已安装,并已添加MySQL和Oracle的JDBC驱动(引用[3]和[5]提到)。-MySQL驱动:mysql-connector-java-x.x.x.jar-Oracle驱动:ojdbcx.jar二、创建数据库连接1.在Kettle中创建MySQL数据库连接。2.在Kettle中创建Oracle数据库连接(引用[5])。三、设计同步转换(Transformation)核心思路:使用“表输入”步骤从MySQL读取量数据(使用混合键量法),然后通过“插入/更新”步骤写入Oracle。步骤分解:1.读取控制表(存储上次同步的最大时间戳和最大ID)-在Oracle中创建控制表(参考之前的设计):```sqlCREATETABLEsync_control(table_nameVARCHAR2(50)PRIMARYKEY,last_timestampTIMESTAMP,last_max_idNUMBER(20));```-使用“表输入”步骤从Oracle控制表读取上次同步的状态。2.设置变量-使用“设置变量”步骤将上一步读取的last_timestamp和last_max_id设置为变量。3.从MySQL读取量数据-在“表输入”步骤中编写SQL(混合键量法):```sqlSELECT*FROMsource_tableWHEREupdate_time>?OR(update_time=?ANDid>?)```-参数使用上一步设置的变量(注意:两个时间戳参数使用同一个变量,ID参数使用last_max_id变量)。4.将数据写入Oracle目标表-使用“插入/更新”步骤,配置目标表为Oracle中的对应表。-配置关键字段(一般是主键)用于判断更新还是插入。-映射所有需要同步的字段。5.更新控制表-从MySQL量数据中计算新的最大时间戳和最大ID(使用“分组”步骤)。-使用“执行SQL脚本”步骤更新Oracle中的控制表。四、创建调度任务(Job)1.创建一个作业,包含以下步骤:-开始-转换:执行上述同步转换-成功/失败处理(如发送邮件等)五、处理删除数据(可选)如果还需要同步删除操作,可以考虑:1.在源表使用逻辑删除(加删除标志),在同步时处理。2.或者使用全量对比(但性能较差)。六、注意事项1.数据类型转换:MySQL和Oracle的数据类型可能同,需要在Kettle中做字段类型转换。2.事务:在Oracle目标表操作时,建议使用事务(在转换中设置事务大小)。3.性能:对于大数据量,考虑分批处理。下面是一个具体的配置示例:转换设计(Transformation):```mermaidgraphLRA[Oracle控制表输入]-->B[设置变量last_timestamp,last_max_id]B-->C[MySQL表输入(量查询)]C-->D[插入/更新到Oracle目标表]D-->E[分组求新最大时间戳和ID]E-->F[更新Oracle控制表]```详细配置步骤:步骤1:Oracle控制表输入-数据库连接:选择Oracle连接-SQL:`SELECTlast_timestamp,last_max_idFROMsync_controlWHEREtable_name='source_table'`步骤2:设置变量-将上一步的两个字段设置为变量:LAST_TIMESTAMP,LAST_MAX_ID步骤3:MySQL表输入-数据库连接:MySQL连接-SQL:```sqlSELECTid,field1,field2,update_timeFROMsource_tableWHEREupdate_time>?OR(update_time=?ANDid>?)```-参数:替换为变量,位置1和2都是$[LAST_TIMESTAMP],位置3是$[LAST_MAX_ID]步骤4:插入/更新(Oracle目标表)-目标表:Oracle中的目标表-用来查询的关键字:选择id主键)-更新字段:映射所有需要同步的字段步骤5:分组-分组字段:无(计算整个结果集的最大值)-聚合:max_update_time=MAX(update_time),max_id=MAX(id)步骤6:更新控制表-数据库连接:Oracle-SQL:```sqlUPDATEsync_controlSETlast_timestamp=?,last_max_id=?WHEREtable_name='source_table'```-参数:使用步骤5中的max_update_time和max_id注意:如果控制表中没有记录,需要先初始化一条记录。引用[1]中提到的方法实际上是一种更复杂的全量对比方法(将两边数据都取出来比较),但这样性能较低。我们这里采用量查询的方法效率更高。因此,我们推荐使用量查询(混合键)的方法,而是全量对比。关于引用[2]和[4]中提到的物化视图刷新,在Oracle到MySQL的场景中,我们需要在Oracle端使用物化视图,因为我们是MySQL作为源,Oracle作为目标。所以此处采用物化视图方案。最后,关于驱动配置(引用[3]和[5]):-将MySQL的JDBC驱动jar包放入Kettle的lib目录下(如mysql-connector-java-5.1.49.jar)-将Oracle的JDBC驱动jar包放入Kettle的lib目录下(如ojdbc8.jar)重启Kettle生效。这样,我们就完成了从MySQL到Oracle的同步配置。相关问题:1.如何处理源表(MySQL)和目标表(Oracle)之间的字段类型一致?2.如果同步过程中出现网络中断,如何保证数据丢失?3.如何优化Kettle转换以提高同步速度?</think>### Kettle 跨数据库同步 MySQL 到 Oracle 配置教程 #### 一、环境准备(引用[3][5]) 1. **驱动配置**: - 下载 MySQL JDBC 驱动:`mysql-connector-java-x.x.x.jar` - 下载 Oracle JDBC 驱动:`ojdbcx.jar` - 将驱动放入 Kettle 的 `lib` 目录 ```bash # 示例目录结构 kettle/ ├── spoon.sh └── lib/ ├── mysql-connector-java-8.0.28.jar └── ojdbc8.jar ``` 2. **数据库连接创建**: | 步骤 | MySQL 连接 | Oracle 连接 | |---|---|---| | **类型** | JDBC | JDBC | | **主机** | localhost | oracle-server | | **数据库** | source_db | orcl | | **用户** | mysql_user | system | | **密码** | ***** | ***** | | **测试** | 必须通过[^5] | 必须通过[^5] | #### 二、核心同步流程设计(引用[1][2]) ```mermaid graph LR A[MySQL源表] --> B{量数据获取} B --> C[混合键过滤] C --> D[字段类型转换] D --> E[Oracle目标表] E --> F[更新控制表] F --> G[物化视图刷新] ``` #### 三、详细配置步骤 ##### 1. 创建控制表(Oracle端) ```sql -- 在Oracle中执行 CREATE TABLE sync_control ( table_name VARCHAR2(50) PRIMARY KEY, last_timestamp TIMESTAMP, last_max_id NUMBER(20) ); -- 初始化记录 INSERT INTO sync_control VALUES ('orders', TO_TIMESTAMP('2023-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 0); ``` ##### 2. 设计转换(Transformation) **步骤1:读取控制表** - 使用 **表输入** 步骤 - SQL: ```sql SELECT last_timestamp, last_max_id FROM sync_control WHERE table_name='orders' ``` **步骤2:设置变量** - 将 `last_timestamp` 存入变量 `${LAST_TS}` - 将 `last_max_id` 存入变量 `${LAST_ID}` **步骤3:MySQL量查询** - 使用 **表输入** 步骤 - SQL(混合键量法): ```sql SELECT order_id, customer, amount, update_time FROM orders WHERE update_time > STR_TO_DATE('${LAST_TS}', '%Y-%m-%d %H:%i:%s') OR (update_time = STR_TO_DATE('${LAST_TS}', '%Y-%m-%d %H:%i:%s') AND order_id > ${LAST_ID}) ``` **步骤4:字段类型转换** - 使用 **Select Values** 步骤: | 字段名 | MySQL类型 | 转换后类型 | |---|---|---| | update_time | DATETIME | Timestamp | | amount | DECIMAL | NUMBER(10,2) | **步骤5:写入Oracle** - 使用 **插入/更新** 步骤: ```yaml 目标表: ORDERS 关键字段: order_id 更新字段: - customer - amount - update_time ``` **步骤6:更新控制表** - 使用 **执行SQL脚本** 步骤: ```sql UPDATE sync_control SET last_timestamp = ?, last_max_id = ? WHERE table_name='orders' ``` - 参数来源:`MAX(update_time)` 和 `MAX(order_id)` ##### 3. 创建调度任务(Job)(引用[2][4]) ```mermaid graph TB Start[开始] --> LoadVars[加载控制表变量] LoadVars --> Sync[执行同步转换] Sync --> Refresh[刷新物化视图] Refresh --> Log[记录同步日志] Log --> Check[检查下次执行] ``` **关键配置**: 1. **定时触发器**:设置每天 02:00 执行 2. **物化视图刷新**(Oracle端): ```sql BEGIN DBMS_MVIEW.REFRESH('ORDERS_MVIEW'); END; ``` #### 四、冲突解决方案 1. **时间戳重复**:通过 `last_max_id` 解决同时间戳数据遗漏问题 2. **数据类型差异**: | MySQL类型 | Oracle类型 | 转换规则 | |---|---|---| | DATETIME | TIMESTAMP | 直接映射 | | TINYINT(1) | NUMBER(1) | 布尔转换 | | TEXT | CLOB | 使用StringClob类型 | 3. **网络中断处理**: ```mermaid graph LR 失败 --> Retry[5分钟后重试] Retry --> |成功| 继续流程 Retry --> |失败| 冻结任务并告警 ``` #### 五、性能优化建议 1. **索引优化**: - MySQL源表:`CREATE INDEX idx_orders_time ON orders(update_time)` - Oracle目标表:`CREATE INDEX idx_orders_id ON orders(order_id)` 2. **批量提交**: ```yaml 插入/更新配置: 提交记录数量: 1000 使用批量更新: 是 ``` 3. **资源控制**: ```yaml 转换配置: 行集大小: 5000 临时文件目录: /opt/kettle/tmp ``` > 通过混合键机制和物化视图刷新,可确保跨数据库同步的数据一致性[^1][^2][^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值