MySQL replace into 语句浅析(二)_MySQL教程
推荐:MySQL replace into 语句浅析(一)这篇文章主要介绍了MySQL replace into 语句浅析(一),本文讲解了replace into的原理、使用方法及使用的场景和使用示例,需要的朋友可以参考下 一 介绍 在笔者支持业务过程中,经常遇到开发咨询replace into 的使用场景以及注意事项,这里做个总结。从功能原理,性能和注
这篇文章主要介绍了MySQL replace into 语句浅析(二),本文着重给出了几个特殊案例分析,需要的朋友可以参考下
一 介绍
上一篇文章介绍了replace into的基本原理。本章内容通过一个例子说明 replace into 带来的潜在的数据质量风险,当涉及replace into操作的表含有自增主键时,主备切换后会造成数据覆盖等不一致的情况发生。
二 案例分析
在主库上操作
代码如下:
root@test 12:36:51>show create table t1 \G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
root@test 12:37:41>insert into t1(name) values('a')
此时检查主备库上t1的表结构都是一样的,AUTO_INCREMENT 都是2.
代码如下:
root@test 12:37:51>show create table t1 \G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
在主库上进行进行replace into操作
root@test 12:37:58>replace into t1(name) values('a');
root@test 12:38:40>replace into t1(name) values('a');
root@test 12:38:49>select * from t1;
+----+------+
| id | name |
+----+------+
| 3 | a |
+----+------+
1 row in set (0.00 sec)
此时检查主备库中t1 表结构,请注意AUTO_INCREMENT=4
代码如下:
root@test 12:38:51>show create table t1 \\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从库上t1的表结构 ,AUTO_INCREMENT=2
代码如下:
root@test 12:39:35>show create table t1 \G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
root@test 12:39:43>select * from t1;
+----+------+
| id | name |
+----+------+
| 3 | a |
+----+------+
1 row in set (0.00 sec)
【分析】
表t1的表结构 AUTO_INCREMENT=2 而主库上的t1表结构的AUTO_INCREMENT=4.原本replace操作是在自增主键的情况下,遇到唯一键冲突时执行的是delete+insert,但是在记录binlog时,却记录成了update操作,update操作不会涉及到auto_increment的修改。备库应用了binlog之后,备库的表的auto_increment属性不变。
三 风险点:
如果主备库发生主从切换,备库变为原来的主库,按照原来的业务逻辑再往下会发生什么?
代码如下:
root@test 12:40:46>replace into t1(name) values('a');
Query OK, 2 rows affected (0.00 sec)
root@test 12:40:48>select * from t1;
+----+------+
| id | name |
+----+------+
| 2 | a | ---id由原来的3变成了2.
+----+------+
1 row in set (0.00 sec)
如果t1表本来就存在多条记录 ,主从切换之后,应用写新的主库则会发生主键冲突,这个留给各位读者自己测试一下。^_^
四 解决方法
推荐使用 insert into table values(,....) on duplicate key update 语法结构来解决业务需求。 来避免replace into 给含有自增主键的表带来主从不一致情况。
代码如下:
root@test 01:14:28>insert into t1(name) values('a');
Query OK, 1 row affected (0.00 sec)
root@test 01:14:51>insert into t1(name) values('b');
Query OK, 1 row affected (0.00 sec)
root@test 01:14:54>insert into t1(name) values('c');
Query OK, 1 row affected (0.00 sec)
root@test 01:14:57>select * from t1;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
+----+------+
3 rows in set (0.00 sec)
root@test 01:16:17>show create table t1 \G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
root@test 01:16:26>insert into tt(name) values('a') on duplicate key update name='a';
Query OK, 1 row affected (0.00 sec)
root@test 01:17:09>show create table t1 \G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
五 总结
分享:MySQL定期自动删除表单位8亿多条的日志表,经过自动分表之后,需要自动删除30天前创建的日志表。 但是只是在Master下线这些日志表,而Slave还需要保持在线,以备查询。 由于Master-Slave结构,在Drop表之前,设置@@session.sql_log_bin=0,那么Drop的行为就没有记录到binlog,所以Slave的日
- 防止服务器宕机时MySQL数据丢失的几种方案
- MySQL Semisynchronous Replication介绍
- MySQL延迟关联性能优化方法
- MySQL 5.7增强版Semisync Replication性能优化
- MySQL Index Condition Pushdown(ICP)性能优化方法实例
- MySQL order by性能优化方法实例
- MySQL slave_net_timeout参数解决的一个集群问题案例
- 使用innodb_force_recovery解决MySQL崩溃无法重启问题
- MySQL replace into 语句浅析(一)
- MySQL定期自动删除表
- MySQL中的CONCAT函数使用教程
- MySQL中的RAND()函数使用详解
- 相关链接:
- 教程说明:
MySQL教程-MySQL replace into 语句浅析(二)。