为什么数据库需要事务?
讲道理应该是这样
这三步骤、必然不得出问题,上面的案例,就是这三步发生了问题!
如果有事务
、就不会发生这样的事
事务就是
这三件事、三个动作,是一根绳上的蚂蚱,要么都成功,要么都失败
转账要么到表弟账户、要么就转不出去、回到自己卡里
TRANSACTION 事务
原子性强调转账的三个步骤要么成功、要么失败
在一个事务中的所有SQL语句,要么全部执行成功,要么全部失败,即使成功的SQL语句也会被撤销,回到执行之前的状态。
一致性是指数据库从一个状态、变为另一个状态
事务开始前、与结束后,数据库的完整性约束没有被破坏。
例如转账,无论成功、或者失败、这500不会多、也不会少
要么超哥卡里扣了500元、表弟多了500元
要么超哥转账失败500元未动、表弟一毛钱也没拿到
这个总和永远是500元,不多也不少
隔离性指的是每个读写事务对其他的事务操作,都是相互隔离不受影响的。
例如同是工商银行
事务一旦提交后,结果就是永久性生效。
超哥转账500给了表弟,表弟也收到钱了,这件事就结束了,真实生效了。
更多高级mysql知识,超哥后期会再补充
从 MySQL 5.6.5 开始新增了一种基于 GTID 的复制方式。
通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。
这种方式强化了数据库的主备一致性,故障恢复以及容错能力。
在原来基于二进制日志的复制中,从库需要告知主库要从哪个偏移量进行增量同步,如果指定错误会造成数据的遗漏,从而造成数据的不一致。
借助GTID,在发生主备切换的情况下,MySQL的其它从库可以自动在新主库上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护
,也减少了人为设置复制位置发生误操作的风险。
另外,基于GTID的复制可以忽略已经执行过的事务,减少了数据发生不一致的风险。
GTID (Global Transaction ID) 是对于一个已提交事务的编号,并且是一个全局唯一的编号。
GTID 实际上 是由 UUID+TID 组成的。
其中 UUID 是一个 MySQL 实例的唯一标识。
TID 代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。下面是一个GTID的具体形式:
形式语法
GTID = source_id :transaction_id具体结果
2E11FA47-61CA-11E1-9E33-C70AA9429562:28
在上面的定义中,每一个GTID均代表一个数据库的事务,等号右边的source_id表示执行事务的源服务器主库的uuid(也就是server_uuid)
而transaction_id是一个从1开始的自增的序列号,表示在这个主库上执行的第n个事务。
只要保证每台数据库的server_uuid全局唯一,以及每台数据库生成的transaction_id自身唯一,就能保证GTID的全局唯一性。
还记得以前我们在myf中配置了一个参数
server_id=5
并且超哥要求master、slave的server_id必须唯一
为什么换成server_uuid
MySQL 5.6用128位的server_uuid代替了原本32位的server_id的大部分功能。
原因很简单,server_id依赖于myf的手工配置,有可能会产生冲突,而自动产生128位uuid的算法可以保证所有的MySQL uuid都不会发生冲突。
在进行首次启动时,MySQL会自动生成一个server_uuid,并且保存到数据库目录下的autof文件里,这个文件目前存在的唯一目的就是保存server_uuid。
在MySQL再次启动时其会读取autof文件,继续使用上次生成的server_uuid。
GTID复制原理流程
master进行数据更新时、在事务前产生GTID号、一起记录到binlog日志。
slave的I/O线程将变更的binlog数据,写入到本地中继日志relay_log
slave的SQL线程从中继日志中获取
GTID
号,和本地的binlog对比查看是否有记录
如果没有记录,slave数据库从relay_log中继日志
中获取数据,且执行该GTID的事务,记录到binlog中
根据GTID号就可以知道事务最初是在哪个数据库上提交的
有了GTID号、可以方便主从复制的故障切换
如图、在没有GTID以前,主从复制的故障切换
只需要在slave-C上执行新的change master to xxx ,指定master-B即可
问题是,同一个事务、在每台服务器上的binlog名字和位置点、可能都是不一样的
比如执行一条SQL,创建了一个新数据库,执行了一个事务,在master-A机器的binlog中数据位置如下
mysql> show master status-> ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 557 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
但是可能在机器master-B中的bin中,同一个SQL执行后,binlog数据位置可能是
mysql> show master status-> ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 1251 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
那么这就是一个难题了,如果master-A宕机,需要切换到master-B
slave-C如何知道当前同步的起停数据位置点呢?master_log_file和master_log_pos填什么?
这就是为什么mysql官方开发了GTID复制方法。
往后,同一个事务的GTID在所有节点上都是一致的,slave-C机器根据GTID就可以知道数据的停止点在哪。
并且,mysql还提供了非常方便的参数
master_auto_position
,能够自动的获取GTID值,让运维更加省心了。
优点
缺点
可以是单机多实例
也可以是多服务器
这里超哥用两台linux虚拟机服务器、初始化安装好mysql
m1 10.211.55.12 3306
m2 10.211.55.9 3306
m1 myf
[root@mysql-server56 ~]# cat /mm_data/3306/myf
[client]
default-character-set=utf8[mysqld]
character-set-server=utf8
socket=/mm_data/3306/mysql.sock
basedir=/application/mysql-5.6.40-linux-glibc2.12-x86_64/
datadir=/mm_data/3306/data
log-bin=/mm_data/3306/mysql-binserver-id=1
expire_logs_days=7
log-slave-updates=1
binlog-format=ROW
gtid-mode=on
enforce-gtid-consistency=true[mysqld_safe]
log-error=/mm_data/3306/mysql_3306_error.log
pid-file=/mm_data/3306/mysqld_3306.pid
sql_mode=NO_ENGINE_SUBSTITUTION,STRTICT_TRANS_TABLES
[root@mysql-server56 ~]#
slave myf
[client]
default-character-set=utf8[mysqld]
character-set-server=utf8
socket=/mm_data/3306/mysql.sock
basedir=/application/mysql-5.6.40-linux-glibc2.12-x86_64/
datadir=/mm_data/3306/data
log-bin=/mm_data/3306/mysql-bin
server-id=2
expire_logs_days=7
log-slave-updates=1
binlog-format=ROW
gtid-mode=on
enforce-gtid-consistency=true[mysqld_safe]
log-error=/mm_data/3306/mysql_3306_error.log
pid-file=/mm_data/3306/mysqld_3306.pid
sql_mode=NO_ENGINE_SUBSTITUTION,STRTICT_TRANS_TABLES
除了server-id完全一致,重启2个机器的mysql
参数解释
m1操作,创建用于slave复制的账号、权限
mysql> grant replication slave on *.* to 'repl'@'10.211.55.%' identified by 'repl888';
Query OK, 0 rows affected (0.01 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
导出主库数据
备注
mysql提示: 当前数据库实例中开启了 GTID 功能, 在开启有 GTID 功能的数据库实例中, 导出其中任何一个库, 如果没有显示地指定--set-gtid-purged参数, 都会提示这一行信息. 意思是默认情况下, 导出的库中含有 GTID 信息, 如果不想导出包含有 GTID 信息的数据库, 需要显示地添加--set-gtid-purged=OFF参数. 于是乎, dump 变成了如下样子➜ mysqldump -uroot -p --set-gtid-purged=OFF userdb > userdb.sql使用以上这条命令 dump 出来的库是不包含 GTID 信息的
命令
[root@mysql-server56 ~]# mysqldump -S /mm_data/3306/mysql.sock -A -B -x --set-gtid-purged=OFF|gzip > /mm_data/m1_alldb_$(date +%F).
[root@mysql-server56 ~]#
mysql> show global variables like '%gtid%';
+---------------------------------+------------------------------------------+
| Variable_name | Value |
+---------------------------------+------------------------------------------+
| binlog_gtid_simple_recovery | OFF |
| enforce_gtid_consistency | ON # 确保这里打开 |
| gtid_executed | 20bdbbd9-a5cd-11eb-a6af-001c4279bcf3:1-4 |
| gtid_mode | ON # 确保这里打开
| gtid_owned | |
| gtid_purged | |
| simplified_binlog_gtid_recovery | OFF |
+---------------------------------+------------------------------------------+
7 rows in set (0.00 sec)# 查看uuid信息
mysql> show global variables like 'server%';
+----------------+--------------------------------------+
| Variable_name | Value |
+----------------+--------------------------------------+
| server_id | 1 |
| server_id_bits | 32 |
| server_uuid | 20bdbbd9-a5cd-11eb-a6af-001c4279bcf3 |
+----------------+--------------------------------------+
3 rows in set (0.00 sec)# 数据插入后,会生成新的GTID
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000004 | 811 | | | 20bdbbd9-a5cd-11eb-a6af-001c4279bcf3:1-4 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)#
[root@mysql-server56 ~]# scp -rp /mm_data/m1_alldb_ root@10.211.55.9:/mm_data/
root@10.211.55.9's password:
m1_alldb_ 100% 177KB 21.2MB/s 00:00[root@mysql-server56 ~]#
导入m1发来的数据
[root@chaoge_slave1 mm_data]# zcat m1_alldb_ |mysql -S /mm_data/3306/mysql.sock
[root@chaoge_slave1 mm_data]#
登录slave,配置m1的复制信息
[root@chaoge_slave1 mm_data]# mysql -S /mm_data/3306/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or g.
Your MySQL connection id is 2
Server version: 5.6.40-log MySQL Community Server (GPL)Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or 'h' for help. Type 'c' to clear the current sql> change master to-> master_host='10.211.55.12',-> master_port=3306,-> master_user='repl',-> master_password='repl888',-> master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.02 sec)mysql>
# 启动slave,测试主从复制
mysql> show slave statusG
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 10.211.55.12Master_User: replMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000004Read_Master_Log_Pos: 657Relay_Log_File: mysqld_3306-relay-bin.000002Relay_Log_Pos: 867Relay_Master_Log_File: mysql-bin.000004Slave_IO_Running: YesSlave_SQL_Running:
# master上写入数据
mysql> create database kings_cc;
Query OK, 1 row affected (0.00 sec)mysql># slave检查数据
mysql> show databases like '%kings%';
+--------------------+
| Database (%kings%) |
+--------------------+
| kings_cc |
+--------------------+
1 row in set (0.00 sec)# 查看slave的GTID信息
# 超哥这里的环境是双主
mysql> show master status;
+------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+
| mysql-bin.000004 | 644131 | | | 20bdbbd9-a5cd-11eb-a6af-001c4279bcf3:1-4,
7b2ec017-a62c-11eb-a91d-001c426c932a:1-115 |
+------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
至此基于GTID的主从复制也搭建好了。
数据写入后,GTID变化,事务更新
# master数据更新mysql> create table tanks_cc(id int,name varchar(50));
Query OK, 0 rows affected (0.02 sec)mysql> show master statusG
*************************** 1. row ***************************File: mysql-bin.000004Position: 987Binlog_Do_DB:Binlog_Ignore_DB:
Executed_Gtid_Set: 20bdbbd9-a5cd-11eb-a6af-001c4279bcf3:1-5
1 row in set (0.00 sec)# slave
mysql> show master statusG
*************************** 1. row ***************************File: mysql-bin.000004Position: 644307Binlog_Do_DB:Binlog_Ignore_DB:
Executed_Gtid_Set: 20bdbbd9-a5cd-11eb-a6af-001c4279bcf3:1-5,
7b2ec017-a62c-11eb-a91d-001c426c932a:1-115
1 row in set (0.00 sec)
本文发布于:2024-02-02 16:54:49,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170686408845162.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |