mysql互为主从的环境,更新一条语句同时提交,为什么会出现数据不一致?

m1:

begin;

update t1 set c2=‘b1‘ where c1=2;

commit;

m2:

begin;

update t1 set c2=‘b2‘ where c1=2;

commit;

m1和m2同时提交,复制不会报错,但是m1和m2的数据不一致,为什么?

因为sql_thread线程根据主键更新数据,不会校验行数据

如何避免这种问题:

只在单节点进行写入,如 keepalived+双主,MGR,PXC如果多节点写入都有这种问题发生。

例1:

表有主键和自增的情况:

[email protected] [testdb]>show create table t1\G

*************************** 1. row ***************************

Table: t1

Create Table: CREATE TABLE `t1` (

`c1` int(11) NOT NULL AUTO_INCREMENT,

`c2` varchar(10) DEFAULT NULL,

PRIMARY KEY (`c1`)

) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

m1: m2:

[email protected] [testdb]>select * from t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | aaa  |

|  2 | bbb  |

|  3 | ccc  |

|  4 | ccc  |

|  6 | ddd  |

|  8 | eee  |

+----+------+


[email protected] [testdb]>select * from t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | aaa  |

|  2 | bbb  |

|  3 | ccc  |

|  4 | ccc  |

|  6 | ddd  |

|  8 | eee  |

+----+------+

[email protected] [testdb]>begin; [email protected] [testdb]>begin;
[email protected] [testdb]>update t1 set c2=‘b1‘ where c1=2; [email protected] [testdb]>update t1 set c2=‘b2‘ where c1=2;

[email protected] [testdb]>select * from t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | aaa  |

|  2 | b1   |

|  3 | ccc  |

|  4 | ccc  |

|  6 | ddd  |

|  8 | eee  |

+----+------+


[email protected] [testdb]>select * from t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | aaa  |

|  2 | b2   |

|  3 | ccc  |

|  4 | ccc  |

|  6 | ddd  |

|  8 | eee  |

+----+------+

[email protected] [testdb]>commit; [email protected] [testdb]>commit;

[email protected] [testdb]>select * from t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | aaa  |

|  2 | b2   |

|  3 | ccc  |

|  4 | ccc  |

|  6 | ddd  |

|  8 | eee  |

+----+------+


[email protected] [testdb]>select * from t1;

+----+------+

| c1 | c2   |

+----+------+

|  1 | aaa  |

|  2 | b1   |

|  3 | ccc  |

|  4 | ccc  |

|  6 | ddd  |

|  8 | eee  |

+----+------+

总结:update一条记录同时提交,有主键的情况下,sql_thread是根据主键匹配行记录,不会校验行数据,所以m1更新了m2中表的记录,m2更新了m1中表的记录。

例2:有没有主键同时更新一行数据的情况:

[email protected] [testdb]>show create table t2\G

*************************** 1. row ***************************

Table: t2

Create Table: CREATE TABLE `t2` (

`c1` int(11) DEFAULT NULL,

`c2` varchar(20) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8

m1 m2

[email protected] [testdb]>select * from t2;

+------+------+

| c1   | c2   |

+------+------+

|    1 | aaa  |

|    2 | bbb  |

+------+------+


[email protected] [testdb]>select * from t2;

+------+------+

| c1   | c2   |

+------+------+

|    1 | aaa  |

|    2 | bbb  |

+------+------+

[email protected] [testdb]>begin; [email protected] [testdb]>begin;
[email protected] [testdb]>update t2 set c2=‘b1‘ where c1=2; [email protected] [testdb]>update t2 set c2=‘b2‘ where c1=2;

[email protected] [testdb]>select * from t2;

+------+------+

| c1   | c2   |

+------+------+

|    1 | aaa  |

|    2 | b1   |

+------+------+


[email protected] [testdb]>select * from t2;

+------+------+

| c1   | c2   |

+------+------+

|    1 | aaa  |

|    2 | b2   |

+------+------+

[email protected] [testdb]>commit; [email protected] [testdb]>commit;

[email protected] [testdb]>select * from t2;

+------+------+

| c1   | c2   |

+------+------+

|    1 | aaa  |

|    2 | b1   |

+------+------+


[email protected] [testdb]>select * from t2;

+------+------+

| c1   | c2   |

+------+------+

|    1 | aaa  |

|    2 | b2   |

+------+------+


[email protected] [testdb]>show slave status\G

Last_Errno: 1032

Last_Error: Could not execute Update_rows event on table testdb.t2; Can‘t find record in ‘t2‘, Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event‘s master log mysql-bin.000013, end_log_pos 759


[email protected] [testdb]>show slave status\G

Last_Errno: 1032

Last_Error: Could not execute Update_rows event on table testdb.t2; Can‘t find record in ‘t2‘, Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event‘s master log mysql-bin.000026, end_log_pos 3064

总结:update一条记录同时提交,有没有主键的情况下,sql_thread是根据全表扫描匹配行记录,所以m1更新在m2中找不到需要更新的行,报1032错误,m2更新在m1中找不到需要更新的行,也报1032错误。

时间: 2024-08-20 14:04:06

mysql互为主从的环境,更新一条语句同时提交,为什么会出现数据不一致?的相关文章

MySQL互为主从模型实现基于SSL复制

一.MySQL复制 1.MySQL复制过程描述 MySQL主服务器上每一次发生的有可能产生修改或者产生修改的操作都会在主服务器上基于语句或基于行写入二进制日志,从服务器会在此期间启用一个IO线程不断的向主服务器发送请求,主服务器的二进制日志一但有更新,则会启用binlog dump线程,把数据发送给对方,从服务器接收到数据后则会将二进制日志的内容同步至本地的中继日志保存,而后启用SQL线程,将日志中的操作语句写入本地从服务器数据库: 2.mysql复制的同步和异步 同步:客户端向主服务器执行一条

Keepalived+Mysql互为主从高可用安装配置

Keepalived+Mysql互为主从高可用安装配置环境介绍:keepalived_vip=192.168.1.210    (写虚拟ip)mysql_master01      eth0:192.168.1.211  eth1:172.20.27.211 (1核1G)mysql_master02      eth0:192.168.1.212  eth1:172.20.27.212 (1核1G) 1.安装mysql数据库(所有节点安装)  //此处省略安装mysql服务2.编辑my.cnf配

Mysql互为主从问题

我搭建的是mysql 互为主从 复制 两台机器的mysql环境完全相同 第一部分测试: B为master  A为slave的同步测试 在B上创建表lian,并插入数据mysql> create table lian (a int,b char(10)); mysql> insert into lian (a,b)values(22,'hahah'); mysql> show tables;+------+| Tables_in_test |+------+| lian          

Mysql互为主从

Mysql互为主从环境:系统环境:centos6.5_x64Mysql-A:172.18.49.10Mysql-B:172.18.49.2Mysql安装已经完成.两台mysql上时间同步: ntpdate pool.ntp.org 在A上操作: vi /etc/my.cnf 添加:log-bin=mysql-bin //开启二进制日志server-id=1 //mysql的idrelay_log=relaylogs service mysqld restart 登录mysql,新建同步用户: m

Mysql互为主从+keepalived实现高可用性(1)

1)规则: 1) db-51    192.168.4.51  Mysql 5.7 2) db-52 192.168.4.52 Mysql 5.7 vip: 192.168.4.50 2)创建Mysql互为主从: 1.在192.168.4.51 (db-51)安装Mysql,创建同步复制用户(用于192.168.4.52(db-52)主机同步数据) 1 [[email protected]51 ~]#tar -xf mysql-5.7.17.tar -C mysql 2 [[email prot

KeepAlived+MySQL互为主从

解决Master单点问题,两台mysql互为主备,双向replication.当一master挂了,则将slave切换为master,继续工作.好,给定两台机器 主机A:192.168.1.201 主机B:192.168.1.202 一.互为主从 1.配置 主机A上,vim /etc/my.cnf,添加: [mysqld] log-bin=mysql-bin server-id=1 #服务id要和B不同 binlog_do_db=db1 master-host = 192.168.1.202 #

Mysql互为主从架构配置

MySQL主主复制结构区别于主从复制结构.在主主复制结构中,两台服务器的任 何一台上面的数据库存发生了改变都会同步到另一台服务器上,这样两台服务器 互为主从,并且都能向外提供服务. 这就比使用主从复制具有更好的性能. 接下来我将使用两个同样的服务器来实现这个效果: server1_mysql:192.168.1.108 server2_mysql: 192.168.1.110 拓扑结构:server1_mysql-------server2_mysql 1.创建用户并授权server1:mysq

Linux下 Mysql 互为主从

系统环境:CentOS 6.5 master1:192.168.100.204 master2:192.168.100.205 mysql版本:mysql-5.6.19 注:mysql的5.5以下的版本和5.5以上的版本配置方法不一样 以下两个节点安装 1:防火墙打开相应端口 #  /sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT #  /etc/rc.d/init.d/iptables save 2:安装相关依赖包 #  yum -y

MySQL互为主从+Keepalived高可用数据库集群

1.剧情回顾 在之前的博客上,我做了一个MySQL主从配置的实验,链接在这:http://blog.51cto.com/superpcm/2094958 .在这里我决定把这两个数据库做成互为主从,然后在这两个互为主从的数据库上配置keepalived,实现高可用,怎么配置可以参考我前文高可用的实验博客,http://blog.51cto.com/superpcm/2095395 . 最后实现的的拓扑图如下: 2.配置MySQL 互为主从复制 之前可能没有说明,实验默认都是开放所有端口给同一网段的