04月08, 2020
收藏本站

一些MySQL知识点(持续更新-20220705)

1. skip-slave-start

有时mysql启动的时候,不希望自动开启同步,则可以在my.cnf添加skip-slave-start

2. change replication filter

mysql 5.7.3版本之后开始支持在线更改同步过滤配置,不用重启mysql。 引用官网的release公告

Replication: Replication filtering rules can now be set dynamically on the slave using the SQL statement CHANGE REPLICATION FILTER introduced in this release.
复制:现在可以使用此版本中引入的SQL语句CHANGE REPLICATION FILTER在从属服务器上动态设置复制过滤规则。

注意:如果原来字段已经有过滤配置,此时要新增,需要把之前的过滤加上,否则会被覆盖!!

例子:在已有同步db1.tb1的基础上,添加同步过滤db1.tb2表

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.101
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: relaylog.000001
                Relay_Log_Pos: 2068
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: db1.tb1
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 


mysql> STOP SLAVE sql_thread;  #需要先停止sql_thread;

mysql> CHANGE REPLICATION FILTER REPLICATE_DO_TABLE =  (db1.tb1,db1.tb2);

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.101
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: relaylog.000001
                Relay_Log_Pos: 2068
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: db1.tb1,db1.tb2
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 


mysql> start slave sql_thread;

另,使用wild过滤,需要加单引号,如:

CHANGE REPLICATION FILTER
REPLICATE_WILD_DO_TABLE = ('db1.t1%','db2.t1%'),
REPLICATE_WILD_IGNORE_TABLE =  ('db1.t2%','db2.t2%');

3. mysql5.7配置pid-file

配置my.cnf的时候一直以为中横线跟下划线一样,所以配置pid_file=mysqld.pid一直无效,查启动脚本mysql.service才发现要用pid-file

4. interactive_timeout和wait_timeout

wait_timeout:非交互式连接超时时间(例如jdbc连接)
interactive_timeout:交互式连接超时时间(mysql客户端连接)

引申出一个mysql的error问题:

[Note] Aborted connection 25442 to db: 'test' user: 'root' host: 'localhost' (Got timeout reading communication packets)

当连接空闲时间超过上面的timeout就会被mysql服务端断开。可修改interactive_timeout=10,然后用客户端连接mysql,10s后日志就会出现上面的提醒,再次执行的时候显示“MySQL server has gone away”

Got timeout reading communication packets很可能mysql服务端主动断开(调大wait_timeout)
Got an error reading communication packets很可能是客户端主动断开

5. 异构同步

库名不一样的主从同步,在从库配置replicate-rewrite-db = old_db -> new_db

6.临时表

mysql临时表分为磁盘临时表内存临时表

磁盘临时表使用引擎:Innodb、MyISAM、Temptable的文件map表(8.0)
内存临时表使用引擎:Memory、Temptable(8.0)

5.6及以前版本:磁盘临时表(.frm/.ibd)存放在临时目录(variables.tmpdir),undo log存放在共享表空间,无redo log;会话断开,临时文件自动释放;
5.7版本:磁盘临时(.frm)存放在临时目录,但数据文件和undo log存放在ibtmp1单独表空间中,只有重启数据库才会回收ibtmp1中的空间;
8.0以后:磁盘临时表的数据单独放在Session临时表空间池(#innodb_temp目录下的ibt文件)里面,临时表的undo放在global的表空间ibtmp1里面。

磁盘临时表文件形态
#sql固定开头,b12 mysql进程id的16进制,15ea6线程id的16进制,0 自增id,可用于分析哪个线程使用了临时表。 image.png

MySQL · 引擎特性 · 临时表那些事儿
注意到里面有句话

在5.6中,隐式临时表依然在tmpdir下,在复杂SQL执行的过程中,就能看到这临时表,一旦执行结束,就被删除。值得注意的是,5.6中,这种隐式创建的临时表,只能用MyISAM引擎,即没有internal_tmp_disk_storage_engine这个参数可以控制。所以,当我们的系统中只有innodb表时,也会看到MyISAM的某些指标在变动

7.“双1”配置

2021-04-15
经常看到有些数据库培训机构在说双1,一开始没明白这是什么简称。(感觉也没必要说得这么神秘)

“双1”指mysql配置中sync_binlog和innodb_flush_log_at_trx_commit设置为1,以此保证数据库的一致性

sync_binlog:控制binlog刷新到磁盘的数量。

  • 0 性能最高,取消实时刷新到磁盘,依靠操作系统,mysql crash可能丢数据;
  • 1 最安全,实时刷新到磁盘,影响写入性能;
  • N 收集N个提交就刷新,也是可能丢数据和影响写入性能;

innodb_flush_log_at_trx_commit:控制innodb刷新模式

  • 0 每秒一次写入和刷新到磁盘,mysql崩溃会丢数据
  • 1 事务提交时写入磁盘,数据不会丢失
  • 2 事务提交后写入磁盘,linux崩溃后才会丢数据

安全模式:sync_binlog 1 ,innodb_flush_log_at_trx_commit 1
高性能:sync_binlog 0 , innodb_flush_log_at_trx_commit 2

8.mysql和mysqld区别

mysql :客户端连接程序
mysqld:服务端启动程序
在修改/usr/lib/systemd/system/mysqld.service里的启动路径ExecStart时,需要指定的就是mysqld的路径

9.元数据锁MDL

DML都会对表加上MDL读锁,DDL则对表加MDL写锁,当出现锁等待时,进程显示Waiting for table metadata lock

即使是对表进行新增字段时,也可能导致数据库崩溃。
复现:

// session 1
begin;
select * from t_test;
// 一直不提交

// session 2 
// 此时新增字段
alter table t_test add column val varchar(10);  // blocked状态

// session 3
// 此时其它DML操作都被阻塞,处于blocked
select * from t_test;

10. 无符号类型下的Error

20210917
最近在审个表结构,有个字段是剩余报名人数,本身是想避免出现超卖现象,建议开发把类型改为无符号int unsigned,没想到上线RC后出现错误: Data truncation: BIGINT UNSIGNED value is out of range in '(test.t_course.plan_limit - 4)'
SQL大概如下:

update t_course set xxx='yyy' where id=10 and plan_limit - 4 > 0

mysql 当两个字段相减时,如果其中一个或两个字段类型是unsigned无符号类型,如果相减的值小于0则会报错(BIGINT UNSIGNED value is out of range),需要调整SQL顺序,如上面改成:

update t_course set xxx='yyy' where id=10 and plan_limit > 4 

11. strace问题追踪

链路追踪排查:

strace -o /tmp/test.log -f -tt mysql --login-path=local -e "show databases"

12. timestamp default null

alter table xxx add column ts timestamp default null可能提示Invalid default value for 'ts'
原因在于参数配置:explicit_defaults_for_timestamp = off 解决办法就是将其改为on
字面上意思:是否明确timestamp的默认值
在mysql5.6.6之前,timestamp的默认行为,如果没有明确声明null,默认为not null(其它类型相反,没有显示声明not null,默认null)

13. max_connections

最大连接数,计算公式={MIN(DBInitMemory/4+500,100000)}(参考腾讯云CDB,DBInitMemory单位M)。
例如:MySQL实例是4核8000M

max_connections=MIN(8000/4+500,100000)=2500

14. 快速安全关闭mysql

# 设置最大脏页比例为0,
set global innodb_max_dirty_pages_pct=0;

# 查询当前脏页数
select count(1) from information_schema.innodb_buffer_page_lru where oldest_modification>0;

#等到上面脏页数为0时,表示脏页都刷新到磁盘,可以重启mysql了

15. mysqldump参数建议

目前表的字符集规范都为utf8mb4,但导出的时候没有指定的话,可能出现emoji表情导出失效,建议参数如下:

mysqldump --login-path=dev --single-transaction --set-gtid-purged=off --default-character-set=utf8mb4 

16. binlog2sql

建议直接使用michael-liumh版本的binlog2sql,有对json和emoji进行修复。michael-liumh_binlog2sql


Comments