MySQL参数 · innodb_additional_mem_pool_size

参数简介

innodb_additional_mem_pool_size 是 InnoDB 用来保存数据字典信息和其他内部数据结构的内存池的大小,单位是 byte,参数默认值为8M。数据库中的表数量越多,参数值应该越大,如果 InnoDB 用完了内存池中的内存,就会从操作系统中分配内存,同时在 error log 中打入报警信息。目前8.0+的版本已经移除了这个参数。

innodb_use_sys_malloc 配置为 ON 时,innodb_additional_mem_pool_size 失效(直接从操作系统分配内存)。

innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 在 MySQL 5.7.4 中移除。

参数合理值预估

./storage/innobase/handler/ha_innodb.cc:
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;

./storage/innobase/srv/srv0srv.cc:        mem_init(srv_mem_pool_size);

storage/innobase/mem/mem0dbg.cc: mem_comm_pool = mem_pool_create(size);

从源码中可以看出,innodb_additional_mem_pool_size 的参数值用于指定内存池 mem_comm_pool 的大小;

storage/innobase/mem/mem0mem.cc:
        block = static_cast<mem_block_t*>(
                mem_area_alloc(&len, mem_comm_pool));

函数 mem_area_alloc 从 mem_comm_pool 内存池中分配内存;

storage/innobase/mem/mem0pool.cc:

/* If we are using os allocator just make a simple call
to malloc */
        if (UNIV_LIKELY(srv_use_sys_malloc)) {
        return(malloc(*psize));
}

........

area = UT_LIST_GET_FIRST(pool->free_list[n]);

if (area == NULL) {
        ret = mem_pool_fill_free_list(n, pool);

        if (ret == FALSE) {
                /* Out of memory in memory pool: we try to allocate
                from the operating system with the regular malloc: */

                mem_n_threads_inside--;
                mutex_exit(&(pool->mutex));

                return(ut_malloc(size));
        }

        area = UT_LIST_GET_FIRST(pool->free_list[n]);
}

如果 innodb_use_sys_malloc (上述代码中的srv_use_sys_malloc) 设置为 ON,或者内存池中没有足够的内存可供分配,则直接从操作系统中分配内存。

mem_area_alloc 调用栈如下(use database 触发断点)

#0  mem_area_alloc
#1  0x000000000118048d in mem_heap_create_block_func
#2  0x000000000149a390 in mem_heap_create_func
#3  0x00000000014aa6d5 in dict_load_table
#4  0x0000000001481082 in dict_table_open_on_name
#5  0x000000000109d769 in ha_innobase::open
#6  0x00000000006d5245 in handler::ha_open
#7  0x0000000000b830ae in open_table_from_share
#8  0x000000000091deee in open_table
#9  0x0000000000922eea in open_and_process_table
#10 0x000000000092492f in open_tables
#11 0x0000000000926c21 in open_normal_and_derived_tables
#12 0x0000000000a83834 in mysqld_list_fields
#13 0x00000000009f28e1 in dispatch_command
#14 0x00000000009eeb51 in do_command
#15 0x0000000000982cb6 in do_handle_one_connection
#16 0x000000000098238b in handle_one_connection
#17 0x0000000001877f91 in pfs_spawn_thread
#18 0x0000003d8c007851 in start_thread ()
#19 0x0000003d8bce767d in clone ()

函数 dict_load_table 中会为每张表分配32k的空间 ( mem_heap_create(32000) 实际分配32744字节空间 ),数据字典中每张表所占空间的上限是32k,具体占用空间根据列数和索引数量分配,分配完成后回收32k中未使用的空间

storage/innobase/dict/dict0load.cc: heap = mem_heap_create(32000);

show engine innodb status BUFFER POOL AND MEMORY Dictionary cache

实际使用的数据字典缓存,不会超过每张表32k,实测过程中,每张表不包括索引占4K,每个索引占2k,列数对空间占用影响不大。

测试用表如下,未建索引时,1000张表占用空间4M,增加列占用空间增长不明显,每增加一个索引,占用空间增加2M,可以估测每张表占用空间4k(不含索引),每个索引占用空间2k。

Create Table: CREATE TABLE `1000` (
  `id` int(11) DEFAULT NULL,
  `a` varchar(255) DEFAULT NULL,
 `b` varchar(255) DEFAULT NULL,
  `c` varchar(255) DEFAULT NULL,
  `d` varchar(255) DEFAULT NULL,
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

引入和移除该参数的原因

早期操作系统的内存分配器性能和可伸缩性较差,并且当时没有适合多核心CPU的内存分配器。所以,InnoDB 实现了一套自己的内存分配系统,做为内存系统的参数之一,引入了innodb_additional_mem_pool_size

随着多核心CPU的广泛应用和操作系统的成熟,操作系统能够提供性能更高、可伸缩性更好的内存分配器,包括 Hoard、libumem、mtmalloc、ptmalloc、tbbmalloc 和 TCMalloc 等。InnoDB 实现的内存分配器相比操作系统的内存分配器并没有明显优势,所以在之后的版本,会移除 innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 两个参数,统一使用操作系统的内存分配器。

文章转自:https://developer.aliyun.com/article/32384

官方文档:https://dev.mysql.com/doc/refman/8.0/en/dynamic-system-variables.html

MySQL的四种事务隔离级别

一、事务的基本要素(ACID)

1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

二、事务的并发问题

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

三、MySQL事务隔离级别

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

 

 

Redis Sentinel

一、哨兵模式概述

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

001
Redis哨兵

这里的哨兵有两个作用

  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。

二、Redis配置哨兵模式

配置3个哨兵和1主2从的Redis服务器来演示这个过程。

服务类型 是否是主服务器 IP地址 端口
Redis 192.168.11.128 6379
Redis 192.168.11.129 6379
Redis 192.168.11.130 6379
Sentinel 192.168.11.128 26379
Sentinel 192.168.11.129 26379
Sentinel 192.168.11.130 26379
002
多哨兵监控Redis

首先配置Redis的主从服务器,修改redis.conf文件如下

# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass "123456"
# 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
slaveof 192.168.11.128 6379
# 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456

上述内容主要是配置Redis服务器,从服务器比主服务器多一个slaveof的配置和密码。

配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy一份进行修改

# 禁止保护模式
protected-mode no
# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor mymaster 192.168.11.128 6379 2
# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123456

上述关闭了保护模式,便于测试。

有了上述的修改,我们可以进入Redis的安装目录的src目录,通过下面的命令启动服务器和哨兵


# 启动Redis服务器进程
./redis-server ../redis.conf
# 启动哨兵进程
./redis-sentinel ../sentinel.conf

注意启动的顺序。首先是主机(192.168.11.128)的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程。

三、Java中使用哨兵模式

/**
 * 测试Redis哨兵模式
 * @author liu
 */
public class TestSentinels {
    @SuppressWarnings("resource")
    @Test
    public void testSentinel() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(10);
        jedisPoolConfig.setMaxIdle(5);
        jedisPoolConfig.setMinIdle(5);
        // 哨兵信息
        Set<String> sentinels = new HashSet<>(Arrays.asList("192.168.11.128:26379",
                "192.168.11.129:26379","192.168.11.130:26379"));
        // 创建连接池
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"123456");
        // 获取客户端
        Jedis jedis = pool.getResource();
        // 执行两个命令
        jedis.set("mykey", "myvalue");
        String value = jedis.get("mykey");
        System.out.println(value);
    }
}

上面是通过Jedis进行使用的,同样也可以使用Spring进行配置RedisTemplate使用。

        <bean id = "poolConfig" class="redis.clients.jedis.JedisPoolConfig">
            <!-- 最大空闲数 -->
            <property name="maxIdle" value="50"></property>
            <!-- 最大连接数 -->
            <property name="maxTotal" value="100"></property>
            <!-- 最大等待时间 -->
            <property name="maxWaitMillis" value="20000"></property>
        </bean>
        
        <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
            <constructor-arg name="poolConfig" ref="poolConfig"></constructor-arg>
            <constructor-arg name="sentinelConfig" ref="sentinelConfig"></constructor-arg>
            <property name="password" value="123456"></property>
        </bean>
        
        <!-- JDK序列化器 -->
        <bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
        
        <!-- String序列化器 -->
        <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
        
        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
            <property name="connectionFactory" ref="connectionFactory"></property>
            <property name="keySerializer" ref="stringRedisSerializer"></property>
            <property name="defaultSerializer" ref="stringRedisSerializer"></property>
            <property name="valueSerializer" ref="jdkSerializationRedisSerializer"></property>
        </bean>
        
        <!-- 哨兵配置 -->
        <bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
            <!-- 服务名称 -->
            <property name="master">
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <property name="name" value="mymaster"></property>
                </bean>
            </property>
            <!-- 哨兵服务IP和端口 -->
            <property name="sentinels">
                <set>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="192.168.11.128"></constructor-arg>
                        <constructor-arg name="port" value="26379"></constructor-arg>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="192.168.11.129"></constructor-arg>
                        <constructor-arg name="port" value="26379"></constructor-arg>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="192.168.11.130"></constructor-arg>
                        <constructor-arg name="port" value="26379"></constructor-arg>
                    </bean>
                </set>
            </property>
        </bean>

四、哨兵模式的其他配置项

配置项 参数类型 作用
port 整数 启动哨兵进程端口
dir 文件夹目录 哨兵进程服务临时文件夹,默认为/tmp,要保证有可写入的权限
sentinel down-after-milliseconds <服务名称><毫秒数(整数)> 指定哨兵在监控Redis服务时,当Redis服务在一个默认毫秒数内都无法回答时,单个哨兵认为的主观下线时间,默认为30000(30秒)
sentinel parallel-syncs <服务名称><服务器数(整数)> 指定可以有多少个Redis服务同步新的主机,一般而言,这个数字越小同步时间越长,而越大,则对网络资源要求越高
sentinel failover-timeout <服务名称><毫秒数(整数)> 指定故障切换允许的毫秒数,超过这个时间,就认为故障切换失败,默认为3分钟
sentinel notification-script <服务名称><脚本路径> 指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,比较常用

sentinel down-after-milliseconds配置项只是一个哨兵在超过规定时间依旧没有得到响应后,会自己认为主机不可用。对于其他哨兵而言,并不是这样认为。哨兵会记录这个消息,当拥有认为主观下线的哨兵达到sentinel monitor所配置的数量时,就会发起一次投票,进行failover,此时哨兵会重写Redis的哨兵配置文件,以适应新场景的需要。

 

CentOS 7x安装Mysql8.0.x

其实官网有教程的,我这里记录下来,是因为要写一个自动化安装脚本,虽然不经常用到,但是还是写出来比较好。

Mysql8.0仅支持CentOS 7x系统下安装,反正6.5的测试过一次,但是安装成功,启动失败,原因是缺少依赖。

Mysql8.0相信只会安装到64位的机器上。

  • 首先,下载mysql8.0的压缩包:

# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.18-linux-glibc2.12-x86_64.tar.xz
# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.18-el7-x86_64.tar.gz
# wget http://mysql.mirror.kangaroot.net/Downloads/MySQL-8.0/mysql-8.0.18-el7-x86_64.tar.gz
wget http://ftp.ntu.edu.tw/MySQL/Downloads/MySQL-8.0/mysql-8.0.18-el7-x86_64.tar.gz

我测试了最后一个,下载速度最快,所以贴上来好了。

  • 解压缩

tar -xzvf mysql-8.0.18-el7-x86_64.tar.gz
mv mysql-8.0.18-el7-x86_64/* /alidata/server/mysql
mkdir -p /alidata/server/mysql/data
ln -s /alidata/server/mysql-8.0.18 /usr/local/mysql
chmod 777 /alidata/server/mysql
chmod 777 /alidata/server/mysql/data

  • 权限配置

groupadd mysql
useradd -g mysql -s /sbin/nologin mysql
chown -R mysql:mysql /alidata/server/mysql/
chown -R mysql:mysql /alidata/server/mysql/data/
chown -R mysql:mysql /alidata/log/mysql
chmod -R 777 /alidata/server/mysql/support-files
chmod -R 777 /alidata/server/mysql/bin
\cp -f /alidata/server/mysql/support-files/mysql.server /etc/init.d/mysqld
sed -i ‘s#^basedir=$#basedir=/alidata/server/mysql#’ /etc/init.d/mysqld
sed -i ‘s#^datadir=$#datadir=/alidata/server/mysql/data#’ /etc/init.d/mysqld

  • 输出my.cnf文件

cat > /etc/my.cnf <<END
[client]
port=3306
default-character-set=utf8
[mysqld]
port = 3306
socket = /tmp/mysql.sock
default_authentication_plugin=mysql_native_password
skip-external-locking
log-error=/alidata/log/mysql/error.log
character-set-server=utf8
default-storage-engine=INNODB
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

log-bin=mysql-bin
binlog_format=mixed
server-id = 1

innodb_buffer_pool_size=512M
innodb_flush_log_at_trx_commit=1
innodb_lock_wait_timeout=120
innodb_log_buffer_size=4M
innodb_log_file_size=256M
interactive_timeout=120
join_buffer_size=2M
key_buffer_size=32M
max_allowed_packet=16M
max_connections=100
max_heap_table_size=64M
myisam_max_sort_file_size=64G
myisam_sort_buffer_size=32M
read_buffer_size=512kb
read_rnd_buffer_size=4M
server_id=1
skip-external-locking=on
sort_buffer_size=256kb
table_open_cache=256
thread_cache_size=16
tmp_table_size=64M
wait_timeout=120

[mysql]
default-character-set=utf8
END

  • 最后,安装并启动

/alidata/server/mysql/bin/mysqld –initialize –user=mysql
chmod 755 /etc/init.d/mysqld
/etc/init.d/mysqld start

*需要注意:

mysql8.0安装成功后,会把初始密码写到log-error对应的文件中,我这里设置的路径是/alidata/log/mysql/error.log,打开这个文件,找到密码,并使用:mysql -uroot -p

登陆终端,把密码修改了,不然的话登陆上去,也操作不了其他。

修改密码的代码:

#alter user ‘root’@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘bsiidno6gH0′;
#flush privileges

最后,贴出整个shell代码:

#!/bin/bash

yum install -y libaio

ifubuntu=$(cat /proc/version | grep ubuntu)
if14=$(cat /etc/issue | grep 14)

if [ `uname -m` == "x86_64" ];then
machine=x86_64
else
machine=i686
fi
if [ $machine == "x86_64" ];then
  rm -rf mysql-8.0.18-el7-x86_64
  if [ ! -f mysql-8.0.18-el7-x86_64.tar.gz ];then
#   wget http://zy-res.oss-cn-hangzhou.aliyuncs.com/mysql/mysql-5.6.21-linux-glibc2.5-x86_64.tar.gz
#   wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.18-linux-glibc2.12-x86_64.tar.xz
#   wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.18-el7-x86_64.tar.gz
#   wget http://mysql.mirror.kangaroot.net/Downloads/MySQL-8.0/mysql-8.0.18-el7-x86_64.tar.gz
    wget http://ftp.ntu.edu.tw/MySQL/Downloads/MySQL-8.0/mysql-8.0.18-el7-x86_64.tar.gz
  fi
  tar -xzvf mysql-8.0.18-el7-x86_64.tar.gz
  mv mysql-8.0.18-el7-x86_64/* /alidata/server/mysql
  mkdir -p /alidata/server/mysql/data
  ln -s /alidata/server/mysql-8.0.18 /usr/local/mysql
  chmod 777 /alidata/server/mysql   
  chmod 777 /alidata/server/mysql/data

else
  echo 'unsupport machine i686'
fi

if [ "$ifubuntu" != "" ] && [ "$if14" != "" ];then
   mv /etc/mysql/my.cnf /etc/mysql/my.cnf.bak
fi

groupadd mysql
useradd -g mysql -s /sbin/nologin mysql
chown -R mysql:mysql /alidata/server/mysql/
chown -R mysql:mysql /alidata/server/mysql/data/
chown -R mysql:mysql /alidata/log/mysql
chmod  -R 777 /alidata/server/mysql/support-files
chmod  -R 777 /alidata/server/mysql/bin
\cp -f /alidata/server/mysql/support-files/mysql.server /etc/init.d/mysqld
sed -i 's#^basedir=$#basedir=/alidata/server/mysql#' /etc/init.d/mysqld
sed -i 's#^datadir=$#datadir=/alidata/server/mysql/data#' /etc/init.d/mysqld
cat > /etc/my.cnf <<END
[client]
port=3306
default-character-set=utf8
[mysqld]
port            = 3306
socket          = /tmp/mysql.sock
default_authentication_plugin=mysql_native_password
skip-external-locking
log-error=/alidata/log/mysql/error.log
character-set-server=utf8
default-storage-engine=INNODB
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

log-bin=mysql-bin
binlog_format=mixed
server-id       = 1

innodb_buffer_pool_size=512M
innodb_flush_log_at_trx_commit=1
innodb_lock_wait_timeout=120
innodb_log_buffer_size=4M
innodb_log_file_size=256M
interactive_timeout=120
join_buffer_size=2M
key_buffer_size=32M
max_allowed_packet=16M
max_connections=100
max_heap_table_size=64M
myisam_max_sort_file_size=64G
myisam_sort_buffer_size=32M
read_buffer_size=512kb
read_rnd_buffer_size=4M
server_id=1
skip-external-locking=on
sort_buffer_size=256kb
table_open_cache=256
thread_cache_size=16
tmp_table_size=64M
wait_timeout=120

[mysql]
default-character-set=utf8


END

/alidata/server/mysql/bin/mysqld --initialize --user=mysql
chmod 755 /etc/init.d/mysqld
/etc/init.d/mysqld start

#mysql password see @/alidata/log/mysql/error.log
#and must by alter root password.
#
#alter user 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'bsiidno6gH0';
#flush privileges
#use mysql mysql
#update user set user.Host='%'where user.User='root';
#export PATH=$PATH:/alidata/server/mysql/bin
#
#/alidata/server/php/bin/php -f ./res/init_mysql.php

官方文档:

https://dev.mysql.com/doc/refman/8.0/en/installing.html

mysql主从复制选项和变量

在主服务器和每个从服务器上,必须设置 server_id系统变量以建立唯一的复制ID。对于每个服务器,应选择一个介于1到2 32 − 1之间的唯一正整数,并且每个ID必须与其他任何复制主服务器或从属正在使用的每个ID不同。范例:server-id=3

有关在主服务器上用于控制二进制日志记录的选项。

下表描述了用于控制复制主服务器的启动选项。与复制相关的系统变量将在本节后面讨论。

  • --show-slave-auth-info
    Property Value
    Command-Line Format --show-slave-auth-info[={OFF|ON}]
    Type Boolean
    Default Value OFF

    SHOW SLAVE HOSTS在主服务器上 的输出中,显示以 --report-user和 --report-password选项开头的从站的从站用户名和密码 。

复制主机上使用的系统变量

以下系统变量用于复制原版或由复制原版使用:

  • auto_increment_increment
    Property Value
    Command-Line Format --auto-increment-increment=#
    System Variable auto_increment_increment
    Scope Global, Session
    Dynamic Yes
    SET_VAR Hint Applies Yes
    Type Integer
    Default Value 1
    Minimum Value 1
    Maximum Value 65535

    auto_increment_increment 和auto_increment_offset 用于主机到主复制的使用,并且可以用于控制其操作 AUTO_INCREMENT的列。这两个变量都具有全局值和会话值,并且每个变量都可以采用1到65535(含)之间的整数值。将这两个变量之一的值设置为0会导致其值设置为1。尝试将这两个变量的值设置为大于65535或小于0的整数会导致其值设置为65535。尝试设定auto_increment_increment或 的值 auto_increment_offset 非整数值会产生错误,并且变量的实际值保持不变。

    注意

    auto_increment_increment 还支持与NDB表一起使用 。

    从MySQL 8.0.18开始,设置此系统变量的会话值不再是受限制的操作。

    在服务器上启动组复制时,值 auto_increment_increment更改为的值 group_replication_auto_increment_increment,默认为7,而 auto_increment_offset更改为服务器ID。停止组复制时,将还原更改。仅当auto_increment_increment 且auto_increment_offset 每个更改的默认值均为1时,才进行并还原这些更改 。如果已将其更改为默认值,则组复制不会更改它们。从MySQL 8.0开始,当组复制处于只有一个服务器写入的单主模式下时,系统变量也不会被修改。

    auto_increment_increment 并auto_increment_offset 影响AUTO_INCREMENT列行为,如下所示:

    • auto_increment_increment 控制连续列值之间的间隔。例如:
      mysql> SHOW VARIABLES LIKE 'auto_inc%';
      +--------------------------+-------+
      | Variable_name            | Value |
      +--------------------------+-------+
      | auto_increment_increment | 1     |
      | auto_increment_offset    | 1     |
      +--------------------------+-------+
      2 rows in set (0.00 sec)
      
      mysql> CREATE TABLE autoinc1
          -> (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
        Query OK, 0 rows affected (0.04 sec)
      
      mysql> SET @@auto_increment_increment=10;
      Query OK, 0 rows affected (0.00 sec)
      
      mysql> SHOW VARIABLES LIKE 'auto_inc%';
      +--------------------------+-------+
      | Variable_name            | Value |
      +--------------------------+-------+
      | auto_increment_increment | 10    |
      | auto_increment_offset    | 1     |
      +--------------------------+-------+
      2 rows in set (0.01 sec)
      
      mysql> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
      Query OK, 4 rows affected (0.00 sec)
      Records: 4  Duplicates: 0  Warnings: 0
      
      mysql> SELECT col FROM autoinc1;
      +-----+
      | col |
      +-----+
      |   1 |
      |  11 |
      |  21 |
      |  31 |
      +-----+
      4 rows in set (0.00 sec)
    • auto_increment_offset 确定AUTO_INCREMENT列值的起点 。考虑以下条件,假设这些语句与描述中给出的示例在同一会话中执行 auto_increment_increment
      mysql> SET @@auto_increment_offset=5;
      Query OK, 0 rows affected (0.00 sec)
      
      mysql> SHOW VARIABLES LIKE 'auto_inc%';
      +--------------------------+-------+
      | Variable_name            | Value |
      +--------------------------+-------+
      | auto_increment_increment | 10    |
      | auto_increment_offset    | 5     |
      +--------------------------+-------+
      2 rows in set (0.00 sec)
      
      mysql> CREATE TABLE autoinc2
          -> (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
      Query OK, 0 rows affected (0.06 sec)
      
      mysql> INSERT INTO autoinc2 VALUES (NULL), (NULL), (NULL), (NULL);
      Query OK, 4 rows affected (0.00 sec)
      Records: 4  Duplicates: 0  Warnings: 0
      
      mysql> SELECT col FROM autoinc2;
      +-----+
      | col |
      +-----+
      |   5 |
      |  15 |
      |  25 |
      |  35 |
      +-----+
      4 rows in set (0.02 sec)

      当的值 auto_increment_offset 大于 auto_increment_increment的值时,auto_increment_offset 将忽略的值 。

    如果更改了这些变量中的任何一个,然后将新行插入到包含AUTO_INCREMENT列的表中 ,则结果似乎违反直觉,因为AUTO_INCREMENT计算该系列 值时不考虑该列中已经存在的任何值,并且下一个插入的值是该系列中的最小值大于该AUTO_INCREMENT列中的最大现有值 。该序列的计算如下:

    auto_increment_offsetN× auto_increment_increment

    其中,N是[1、2、3,…]系列中的正整数值。例如:

    mysql> SHOW VARIABLES LIKE 'auto_inc%';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | auto_increment_increment | 10    |
    | auto_increment_offset    | 5     |
    +--------------------------+-------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT col FROM autoinc1;
    +-----+
    | col |
    +-----+
    |   1 |
    |  11 |
    |  21 |
    |  31 |
    +-----+
    4 rows in set (0.00 sec)
    
    mysql> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
    Query OK, 4 rows affected (0.00 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    mysql> SELECT col FROM autoinc1;
    +-----+
    | col |
    +-----+
    |   1 |
    |  11 |
    |  21 |
    |  31 |
    |  35 |
    |  45 |
    |  55 |
    |  65 |
    +-----+
    8 rows in set (0.00 sec)

    显示auto_increment_increment 并auto_increment_offset 生成5 + N×10 系列的值 ,即[5、15、25、35、45,…]。出现在col之前的列 中的最大值INSERT是31,而该AUTO_INCREMENT 序列中的下一个可用值是35,因此col从该点开始的插入值 和结果如SELECT 查询所示。

    不可能将这两个变量的作用限制在一个表中。这些变量控制MySQL服务器上所有中所有AUTO_INCREMENT列 的行为。如果设置了其中一个变量的全局值,则其影响将持续到通过设置会话值更改或覆盖全局值,或者直到重新启动mysqld为止。如果设置了本地值,则新值将影响 会话期间当前用户在其中插入新行的所有表的列,除非在该会话期间更改了值。 AUTO_INCREMENT

    默认值为 auto_increment_increment1。请参见 mysql第17.5.1.1节“复制和AUTO_INCREMENT”

  • auto_increment_offset
    Property Value
    Command-Line Format --auto-increment-offset=#
    System Variable auto_increment_offset
    Scope Global, Session
    Dynamic Yes
    SET_VAR Hint Applies Yes
    Type Integer
    Default Value 1
    Minimum Value 1
    Maximum Value 65535

    此变量的默认值为1。如果保留其默认值,并且在多主模式下在服务器上启动组复制,则会将其更改为服务器ID。有关更多信息,请参见的描述 auto_increment_increment

    注意

    auto_increment_offset还支持与NDB表一起使用。

    从MySQL 8.0.18开始,设置此系统变量的会话值不再是受限制的操作。

  • immediate_server_version
    Property Value
    Introduced 8.0.14
    System Variable immediate_server_version
    Scope Session
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Integer

    供复制内部使用。该会话系统变量保存服务器的MySQL服务器发行版号,该服务器是复制拓扑中的直接主服务器(例如,80014对于MySQL 8.0.14服务器实例)。如果此即时服务器的发行版不支持会话系统变量,则该变量的值将设置为0(UNKNOWN_SERVER_VERSION)。

    变量的值从主机复制到从机。通过识别这些信息,从属服务器可以通过识别所涉及的版本之间在何处发生语法更改或语义更改并进行适当的处​​理,来正确处理来自较旧版本的主服务器的数据。该信息还可以在组复制环境中使用,在该环境中,复制组的一个或多个成员的版本比其他成员的版本高。可以在每个交易的二进制日志中查看变量的值(作为 Gtid_log_event,或 Anonymous_gtid_log_event (如果服务器上未使用GTID),则可能有助于调试跨版本复制问题。

    设置此系统变量的会话值是受限制的操作。会话用户必须具有 REPLICATION_APPLIER特权(请参见第17.3.3节“复制特权检查”)或足以设置受限制的会话变量的特权(请参见第5.1.9.1节“系统变量特权”)。但是,请注意,该变量并非供用户设置。它是由复制基础结构自动设置的。

  • original_server_version
    Property Value
    Introduced 8.0.14
    System Variable original_server_version
    Scope Session
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Integer

    供复制内部使用。此会话系统变量保存最初提交事务的服务器的MySQL Server版本号(例如, 80014对于MySQL 8.0.14服务器实例)。如果此原始服务器的发行版不支持会话系统变量,则该变量的值将设置为0(UNKNOWN_SERVER_VERSION)。请注意,当原始服务器设置发行版号时,如果复制拓扑中的直接服务器或任何其他中介服务器不支持会话系统变量,那么该变量的值将重置为0,因此不复制其值。

    变量的值的设置和使用方式与 immediate_server_version 系统变量相同。如果该变量的值与immediate_server_version 系统变量的值相同 ,则仅将后者记录在二进制日志中,并指示原始服务器版本是相同的。

    在组复制环境中,查看更改日志事件(这些事件是新成员加入组时每个组成员排队的特殊事务)用组成员的服务器版本对事务进行标记。这样可确保加入成员知道原始供体的服务器版本。因为排队等待特定视图更改的视图更改日志事件在所有成员上都具有相同的GTID,所以仅在这种情况下,同一GTID的实例可能具有不同的原始服务器版本。

    设置此系统变量的会话值是受限制的操作。会话用户必须具有 REPLICATION_APPLIER特权(请参见第17.3.3节“复制特权检查”)或足以设置受限制的会话变量的特权(请参见第5.1.9.1节“系统变量特权”)。但是,请注意,该变量并非供用户设置。它是由复制基础结构自动设置的。

  • rpl_semi_sync_master_enabled
    Property Value
    Command-Line Format --rpl-semi-sync-master-enabled[={OFF|ON}]
    System Variable rpl_semi_sync_master_enabled
    Scope Global
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Boolean
    Default Value OFF

    控制是否在主服务器上启用半同步复制。要启用或禁用插件,请将此变量 分别设置为ONOFF(或1或0)。默认值为 OFF

    仅当安装了主端半同步复制插件时,此变量才可用。

  • rpl_semi_sync_master_timeout
    Property Value
    Command-Line Format --rpl-semi-sync-master-timeout=#
    System Variable rpl_semi_sync_master_timeout
    Scope Global
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Integer
    Default Value 10000

    以毫秒为单位的值,用于控制主机在超时并恢复为异步复制之前,等待提交等待从属服务器进行确认的时间。默认值为10000(10秒)。

    仅当安装了主端半同步复制插件时,此变量才可用。

  • rpl_semi_sync_master_trace_level
    Property Value
    Command-Line Format --rpl-semi-sync-master-trace-level=#
    System Variable rpl_semi_sync_master_trace_level
    Scope Global
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Integer
    Default Value 32

    主服务器上的半同步复制调试跟踪级别。定义了四个级别:

    • 1 =常规级别(例如,时间功能故障)
    • 16 =详细程度(更多详细信息)
    • 32 =净等待级别(有关网络等待的更多信息)
    • 64 =功能级别(有关功能进入和退出的信息)

    仅当安装了主端半同步复制插件时,此变量才可用。

  • rpl_semi_sync_master_wait_for_slave_count
    Property Value
    Command-Line Format --rpl-semi-sync-master-wait-for-slave-count=#
    System Variable rpl_semi_sync_master_wait_for_slave_count
    Scope Global
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Integer
    Default Value 1
    Minimum Value 1
    Maximum Value 65535

    主机在继续之前必须为每个事务接收的从机确认数。默认情况下 rpl_semi_sync_master_wait_for_slave_count 为1,表示半同步复制在收到单个从属确认后继续进行。对于此变量的较小值,性能最佳。

    例如,如果 rpl_semi_sync_master_wait_for_slave_count is为2,则2个从属必须在rpl_semi_sync_master_timeout 半同步复制配置的超时时间继续之前确认事务的接收 。如果在超时期间较少的从服务器确认接收到事务,则主服务器将恢复为正常复制。

    注意

    此行为还取决于 rpl_semi_sync_master_wait_no_slave

    仅当安装了主端半同步复制插件时,此变量才可用。

  • rpl_semi_sync_master_wait_no_slave
    Property Value
    Command-Line Format --rpl-semi-sync-master-wait-no-slave[={OFF|ON}]
    System Variable rpl_semi_sync_master_wait_no_slave
    Scope Global
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Boolean
    Default Value ON

    控制主服务器是否等待由配置的超时时间rpl_semi_sync_master_timeout 到期,即使从服务器的计数下降到小于超时期间配置 的从服务器的数量也是如此 rpl_semi_sync_master_wait_for_slave_count 。

    当的值 rpl_semi_sync_master_wait_no_slave是 ON(默认值),则允许用于从属计数下降到小于 rpl_semi_sync_master_wait_for_slave_count 在超时期限内。只要有足够多的从服务器在超时期限到期之前确认该事务,半同步复制就会继续。

    当的值 rpl_semi_sync_master_wait_no_slave是 OFF,如果从计数降到比配置数量较少 rpl_semi_sync_master_wait_for_slave_count 期间由配置的超时时间段在任何时候 rpl_semi_sync_master_timeout,主回复到正常的复制。

    仅当安装了主端半同步复制插件时,此变量才可用。

  • rpl_semi_sync_master_wait_point
    Property Value
    Command-Line Format --rpl-semi-sync-master-wait-point=value
    System Variable rpl_semi_sync_master_wait_point
    Scope Global
    Dynamic Yes
    SET_VAR Hint Applies No
    Type Enumeration
    Default Value AFTER_SYNC
    Valid Values

    AFTER_SYNC

    AFTER_COMMIT

    此变量控制半同步复制主服务器在将状态返回给提交事务的客户端之前等待事务接收的从属确认的时间点。这些值是允许的:

    • AFTER_SYNC(默认):主服务器将每个事务写入其二进制日志,而从服务器则将二进制日志同步到磁盘。主机在同步后等待从机对交易收据的确认。收到确认后,主服务器将事务提交到存储引擎,并将结果返回给客户端,然后客户端可以继续进行。
    • AFTER_COMMIT:主服务器将每个事务写入其二进制日志,而从服务器将其同步到二进制日志,然后将事务提交到存储引擎。提交后,主机等待从机对交易收据的确认。收到确认后,主机将结果返回给客户端,然后客户端可以继续进行。

    这些设置的复制特征如下:

    • 使用AFTER_SYNC,所有客户端可以同时看到已提交的事务:从属服务器确认了该事务并提交给了主服务器上的存储引擎之后。因此,所有客户端都可以在主服务器上看到相同的数据。如果主服务器发生故障,则所有在主服务器上提交的事务都将复制到从服务器(保存到其中继日志中)。由于从属服务器是最新的,因此主服务器崩溃和故障转移到从属服务器是无损的。但是请注意,在这种情况下无法重新启动主服务器,必须将其丢弃,因为其二进制日志中可能包含未提交的事务,这些事务在二进制日志恢复后被外部化时会与从服务器发生冲突。
    • 使用AFTER_COMMIT,仅在服务器提交到存储引擎并接收到从属确认后,发出事务的客户端才会获得返回状态。在提交之后和从属确认之前,其他客户端可以在提交客户端之前看到提交的事务。如果出现故障,导致从服务器无法处理事务,则在主服务器崩溃并故障转移到从服务器的情况下,此类客户端可能会看到相对于其在主服务器上看到的数据丢失的情况。

    仅当安装了主端半同步复制插件时,此变量才可用。

    由于增加了 rpl_semi_sync_master_wait_point 在MySQL 5.7,创建一个版本的兼容性约束,因为它增加了半同步接口版本:服务器为MySQL 5.7和更高不要从旧版本的半同步复制插件的工作,也没有从旧版本的服务器与半同步复制插件工作适用于MySQL 5.7和更高版本。

原文:https://dev.mysql.com/doc/refman/8.0/en/replication-options-master.html

1234517
 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |