MySQL lower_case_file_system & lower_case_table_names

〇 lower_case_file_system
该参数是用于描述data目录所在的操作系统是否为大小写敏感,该参数为bool类型,但无法修改。
0 — 大小写敏感
1 — 大小写不敏感
比如跑在linux上的都是OFF或者0。

〇 lower_case_table_names
该参数为静态,可设置为0、1、2。

0 — 大小写敏感。(Unix,Linux默认)
创建的库表将原样保存在磁盘上。如create database TeSt;将会创建一个TeSt的目录,create table AbCCC …将会原样生成AbCCC.frm。
SQL语句也会原样解析。

1 — 大小写不敏感。(Windows默认)
创建的库表时,MySQL将所有的库表名转换成小写存储在磁盘上。
SQL语句同样会将库表名转换成小写。
如需要查询以前创建的Test_table(生成Test_table.frm文件),即便执行select * from Test_table,也会被转换成select * from test_table,致使报错表不存在。

2 — 大小写不敏感(OS X默认)
创建的库表将原样保存在磁盘上。
但SQL语句将库表名转换成小写。

修改lower_case_table_names导致的常见不良隐患:
如果在lower_case_table_names=0时,创建了含有大写字母的库表,改为lower_case_table_names=1后,则会无法被查到。

注意事项:
将默认的lower_case_tables_name为0设置成1,需先将已经存在的库表名转换为小写

1)针对仅表名存在大写字母的情况:
①、lower_case_tables_name=0时,执行rename table成小写。
②、设置lower_case_tables_name=1,重启生效。

2)针对库名存在大写字母的情况:
①、lower_case_tables_name=0时,使用mysqldump导出,并删除老的数据库。
②、设置lower_case_tables_name=1,重启生效。
③、导入数据至实例,此时包含大写字母的库名已转换为小写。

转换操作需要自行测试,不同操作系统,不同MySQL版本可能有不同的情况。

mysqldump Error 3024: Query execution was interrupted

mysqldump时可能出现的一个error,完整报错如下:
mysqldump: Error: Query execution was interrupted, maximum statement execution time exceeded when trying to dump tablespaces
mysqldump: Error 3024: Query execution was interrupted, maximum statement execution time exceeded when dumping table `$tb_name` at row: 25002

在SELECT时也有可能报该错:
ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded

该问题仅发生在5.7.8+的版本

原因是max_execution_time设置过小导致。

将max_execution_time设置成很小的值,执行mysqldump(本质也是执行SELECT)或者SELECT语句即可复现:

  1. [17:23:01] root@localhost [(none)]> SET GLOBAL max_execution_time=10;
  2. Query OK, 0 rows affected (0.00 sec)
  3. [17:23:11] root@localhost [(none)]> SELECT * FROM test.t1 LIMIT 100000;
  4. ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded
  5. mysqldump -uxxx -pxxx -S xxx.socket -A > /tmp/a.sql
  6. mysqldump: Error 3024: Query execution was interrupted, maximum statement execution time exceeded when dumping table `$tb_name` at row: 0

 

可以考虑以下解决方案:

① 通过hints,设置一个较大的N值。
SELECT /*+ MAX_EXECUTION_TIME(N) */ * FROM t1 LIMIT 100000;

② 修改max_execution_time值,将该值设置为较大一个值,或设置为0(不限制)。

 

相关参数:

max_execution_time
该参数5.7.8被添加,单位为ms,动态参数,默认为0。
设置为0时意味着SELECT超时不被设置(不限制超时时间)。
不作用于存储过程中的SELECT语句,并且只作用于只读的SELECT,比如INSERT … SELECT … 是不被作用的。

 

 

使用mysqlbinlog备份binlog 搭建Binlog Server

binlog是增量备份必备之一,在有些场景下,实时或定期备份binlog是有必要的。

〇 常用的参数:
-R | –read-from-remote-server 表示开启binlog备份,在对应的主节点上请求binlog到本地。

–raw 被复制过来的binlog以二进制的格式存放,如果不加该参数则为text格式。

-r | –result-file 指定目录或文件名:
若指定了–raw参数,-r的值指定binlog的存放目录和文件名前缀;若没有指定–raw参数,-r的值指定文本存放的目录和文件名。

-t 这个选项代表从指定的binlog开始拉取,直到当前主节点上binlog的最后一个。

–stop-never 持续连续从主节点拉取binlog,持续备份到当前最后一个,并继续下去。该参数包含-t

–stop-never-slave-server-id 默认值65535,用于在多个mysqlbinlog进程或者从服务器的情况下,避免ID冲突。

mysqlbinlog开启备份后,直到连接关闭或者被强制kill才会结束。
可通过ps查看到已经开启的备份进程。

用法示例:完整并保持原样的将远程server的binlog拉到本地,并存放在/data/backup_binlog目录中。
注意,-r指定的目录必须写完整,否则会被放在/data目录下,并以”backup_binlog”为前缀命名binlog
如:-r /data/backup_binlog 则会显示为 /data/backup_binlogmysql-bin.000008

〇 用法:

mkdir -p /data/backup_binlog

mysqlbinlog -h$ip -P$port -u$user -p$password -R –raw –stop-never mysql-bin.000008 -r /data/backup_binlog/ &

 

[root@host backup_binlog]# mysql -h$ip -P$port -u$user -p$password -e “SHOW BINARY LOGS”

mysql: [Warning] Using a password on the command line interface can be insecure.

+—————————+———————–+
| Log_name           | File_size           |
+————————-+————————-+
| mysql-bin.000008  | 1073742873   |
| mysql-bin.000009  | 284594590    |
| mysql-bin.000010  | 396303459    |
| mysql-bin.000011   | 154              |
| mysql-bin.000012  | 154              |
| mysql-bin.000013  | 154              |
+———————–+———————-+

检查拉取过来的binlog,与show binary logs结果一致。

[root@sAno1y backup_binlog]# ll

total 1713580

-rw-r—– 1 root root 1073742873 Aug 22 17:12 mysql-bin.000008

-rw-r—– 1 root root 284594590 Aug 22 17:13 mysql-bin.000009

-rw-r—– 1 root root 396303459 Aug 22 17:13 mysql-bin.000010

-rw-r—– 1 root root 154 Aug 22 17:13 mysql-bin.000011

-rw-r—– 1 root root 154 Aug 22 17:13 mysql-bin.000012

-rw-r—– 1 root root 154 Aug 22 17:13 mysql-bin.000013

 

在源实例提交了事务之后,因为加了–stop-never参数,故会持续拉取最新的binlog到本地。

 

 

MySQL Transportable TableSpace(TTS) 使用详解

将大的InnoDB表从一个实例,移动或者复制到另一个实例,有很多的方法,在5.6之前常用的是通过物理或者逻辑备份来实现。
在5.6.6+的版本中,用到了一种基于表空间迁移的快速方法,即类似Oracle TTS。

 

使用起来十分简单,此处将实例1上的表数据通过TTS方式导入实例2

〇 在实例1上创建测试数据:

  1. — 创建待迁移的表
  2. mysql1> CREATE TABLE tts(id int PRIMARY KEY AUTO_INCREMENT, name char(128));
  3. Query OK, 0 rows affected (0.01 sec)
  4. mysql1> INSERT INTO tts(name) VALUES(REPEAT(‘a’,128));
  5. Query OK, 1 row affected (0.00 sec)
  6. mysql1> INSERT INTO tts(name) SELECT name FROM tts;
  7. Query OK, 1 row affected (0.00 sec)
  8. Records: 1 Duplicates: 0 Warnings: 0
  9. mysql1> INSERT INTO tts(name) SELECT name FROM tts;
  10. Query OK, 2 rows affected (0.00 sec)
  11. Records: 2 Duplicates: 0 Warnings: 0
  12. ………………………………
  13. mysql1> INSERT INTO tts(name) SELECT name FROM tts;
  14. Query OK, 262144 rows affected (2.15 sec)
  15. Records: 262144 Duplicates: 0 Warnings: 0
  16. — 已产生92M的ibd文件
  17. mysql1> \! du -sh /data/mysql/test/tts*
  18. 12K /data/mysql/test/tts.frm
  19. 92M /data/mysql/test/tts.ibd

 

〇 在实例2上创建和实例1相同表结构的表,并执行(该操作会记录binlog,可临时不记binlog):

  1. SET sql_log_bin=0;
  2. ALTER TABLE tts DISCARD TABLESPACE;
  3. SET sql_log_bin=1;

 

〇 对实例1的该表执行FLUSH TABLE $tb_name FOR EXPORT:

  1. mysql1> FLUSH TABLE tts FOR EXPORT;
  2. Query OK, 0 rows affected (0.05 sec)
  3. — 产生多了一个cfg文件
  4. mysql1> \! du -sh /data/mysql/test/tts*
  5. 4.0K /data/mysql/test/tts.cfg
  6. 12K /data/mysql/test/tts.frm
  7. 92M /data/mysql/test/tts.ibd

 

〇 将实例1的/data/mysql/test/tts.{ibd,cfg}文件拷到实例2所在的datadir对应的库目录中,并为俩文件赋权。

 

〇 恢复实例1中test.tts表的可用性(此时cfg文件已回收):

  1. mysql1> UNLOCK TABLES;
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql1> \! du -sh /data/mysql/test/tts*
  4. 12K /data/mysql/test/tts.frm
  5. 92M /data/mysql/test/tts.ibd

 

〇 将表空间ibd文件恢复至实例2的test.tts表:

  1. mysql2> ALTER TABLE tts IMPORT TABLESPACE;
  2. Query OK, 0 rows affected (0.93 sec)
  3. mysql2> SELECT count(*) FROM tts;
  4. +———-+
  5. | count(*) |
  6. +———-+
  7. | 524288   |
  8. +———-+
  9. 1 row in set (0.34 sec)

 

至此,已经将mysql1实例上的tts表中数据快速地迁移到mysql2实例上了。
discard tablespace
为表加MDL锁,删除change buffer所有相关的缓存项,设置表元数据信息,标志tablespace为删除状态,重新生成表的id,保证基于表id的操作后续均会失败,再将idb文件干掉,在②中的两次du可以看到.idb文件已经被删除了。这是一个十分危险的操作,慎重;此操作也会记录binlog,若在复制结构可能会有意想不到的灾难,切记先临时关闭binlog。
flush table … for export
为表加共享锁,并purge coordinator thread(在并行复制中的sql thread被称为coordinator)停止,并且将脏页强制同步到磁盘,创建并将test.tts表的元数据写入.cfg文件;
FLUSH TABLES … FOR EXPORT在error log中体现了这个过程:
[Note] InnoDB: Sync to disk of ‘”test”.”tts”‘ started.
[Note] InnoDB: Stopping purge
[Note] InnoDB: Writing table metadata to ‘./test/tts.cfg’
[Note] InnoDB: Table ‘”test”.”tts”‘ flushed to disk
unlock tables
此时.cfg文件被删掉,purge coordinator thread也会重新启动;(在做flush table … for export时不能断开会话,避免锁释放造成.cfg文件删除)
UNLOCK TABLES在error log中记录为:
[Note] InnoDB: Deleting the meta-data file ‘./test/tts.cfg’
[Note] InnoDB: Resuming purge
import tablespace
将从实例1上传输过来的.ibd文件和导入到tts表中,此时.cfg文件也必须存在;
ALTER TABLE … IMPORT TABLESPACE在error log中记录为:
[Note] InnoDB: Importing tablespace for table ‘test/tts’ that was exported from host ‘$host1’
[Note] InnoDB: Phase I – Update all pages
[Note] InnoDB: Sync to disk
[Note] InnoDB: Sync to disk – done!
[Note] InnoDB: Phase III – Flush changes to disk
[Note] InnoDB: Phase IV – Flush complete
[Note] InnoDB: “test”.”tts” autoinc value set to 786406
过程为读取cfg文件:表定义,索引定义,索引RootPage,列定义等等。
再读取import文件每一个page,检查完整性,根据读取到的cfg文件,重新设置当前表的元数据信息。
〇 MySQL TTS的限制:
两个实例都必须开启独立表空间(innodb_file_per_table=1)
迁移的两个实例的innodb_page_size必须一致,并且mysql server版本建议一致
不支持在分区表上执行discard tablespace
不支持在有主外键关系的表上执行discard tablespace,除非设置foregin_key_checks=0