--- title: "Mysql 笔记" date: 2019-10-30T11:51:23+08:00 lastmod: 2019-10-30T11:51:23+08:00 tags: ["mysql"] categories: ["database"] --- ## MySQL 5.7 配置文件 my.cnf ``` [mysqld] datadir = /db/mysql socket = /var/lib/mysql/mysql.sock symbolic-links = 0 log-timestamps = SYSTEM slow-query-log = 1 slow-query-log-file = /var/log/mysqld/slow.log long-query-time = 8 #log-queries-not-using-indexes = 1 log-error = /var/log/mysqld/error.log pid-file = /var/run/mysqld/mysqld.pid max-connections = 1000 max-connect-errors = 1000 max-user-connections = 600 interactive-timeout = 3600 wait-timeout = 3600 skip-name-resolve = 1 lower-case-table-names = 1 default-time-zone = '+08:00' character-set-server = utf8mb4 sql-mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES bind-address = 0.0.0.0 table-open-cache = 2048 default-storage-engine = innodb innodb-autoinc-lock-mode = 2 innodb-flush-log-at-trx-commit = 0 # 建议物理内存一半 innodb-buffer-pool-size = 8G innodb-buffer-pool-instances = 8 max-allowed-packet = 512M query-cache-size = 0 query-cache-type = 0 # 建议点分 ip 的最后一个数字 server-id = 123 # bin log #binlog-format = ROW #log-bin = /var/lib/mysql/mysql-bin #expire-logs-days = 3 # relay log #read-only = 1 #replicate-wild-do-table = db1.% #relay-log = /var/lib/mysql/mysql-relay-bin #slave-parallel-type = logical-clock ``` ## 复制表结构 ```sql create table db1.t1 like db2.t2; create table db1.t1 select db2.t2 where 1=2; ``` ## 复制表结构及其数据 ```sql create table db1.t1 select db2.t2 [where ...] ``` ## 复制表数据 ``` insert into db2.t2(column1, column2 ...) select column1, column2 ... from db1.t1 [where ...] ``` ## 通过复制表文件来复制表数据 - 在db2中创建同结构表 ```sql create table db2.t1 like db1.t1; ``` - 丢弃表空间 ```sql alter table db2.t1 discard tablespace; ``` - 复制 t1 的表数据文件 ```bash #关闭数据库 systemctl stop mysqld cd /var/lib/mysql scp db1/t1.idb db2/t1.idb chown mysql.mysql db2/t1.idb #启动数据库 systemctl start mysqld ``` - 导入表空间 ```sql alter table db2.t1 import tablespace; ``` ## 设置一个表的空列自增 ```sql -- 删除可能存在的主键 alter table 表名 drop primary key; alter table 表名 modify 列名 auto_increment primary key; ``` ## 查看数据库中每个表的全部列名 ```sql select table_name, column_name from information_schema.columns where table_schema = '数据库名'; ``` ## 查看数据库中每个表的行数 ```sql select table_name, table_rows from information_schema.tables where table_schema = '数据库名'; ``` ## 查看数据库中每个表的索引 ```sql select table_name, column_name, index_name from INFORMATION_SCHEMA.STATISTICS where table_schema = '数据库名'; ``` ## 表的部分列数据到另一个表 ```sql update db2.t2(column1, column2 ...) = ( select column1, column2 from db1.t1 where db1.t1.id = db2.t2.id); ``` ## 把语句执行结果写到文件 ```bash mysql -uroot -p -hsever_ip -Ddb_name -Ne "select ... from table_name;" > file_name ``` ## 表分区 - 查看表的分区情况 ```sql select table_schema, table_name, partition_name, table_rows from information_schema.partitions where table_name = 'table_name'; ``` - 建表时指定 ```sql create table table_name(...) partition by range columns(column_name) (partition part_name values less than(some_value)); ``` - 修改成分区表 ```sql alter table table_name partition by range(column_name) (partition part_name values less than(som_value)); ``` - 增加分区 ```sql alter table table_name add partition (partition part_name values less than(som_value)); ``` - 删除分区 ```sql alter table table_name drop partition part_name; ``` - 合并/拆分分区 ```sql alter table table_name reorganize part_old_1, part_old_2, part_old_3 into (partition part_new_1 values less than(value_1), partition part_new_2 values less than(value_2)); ``` - 重建分区,整理分区碎片 ```sql alter table table_name rebuild partition part_name_1, part_name_2; ``` - 优化分区,回收空间,整理碎片 ```sql alter table table_name optimize partition part_name_1, part_name_2; ``` - 分析分区,读取并保存分区的健分布 ```sql alter table table_name analyze partition part_name_1, part_name_2; ``` - 修复分区 ```sql alter table table_name repair partition part_name_1, part_name_2; ``` - 检查分区 ```sql alter table table_name check partition part_name_1, part_name_2; ``` ## MySQL 5.7 从库多线程同步 ```sql stop slave; set global slave_parallel_type='logical_clock'; set global slave_parallel_workers=4; start slave; show processlist; ``` ## MySQL 5.7 提示密码复杂度不够 ```sql set global validate_password_policy=0; ``` ## MySQL 5.7 从库复制失败跳过指定数量的事务 ```sql stop slave; -- 跳过一个事务 SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; start slave; -- 修改 my.cnf slave-skip-errors=1062,1053,1146,1032 #跳过指定error no类型的错误 slave-skip-errors=all #跳过所有错误 ``` ## MySQL 5.7 查看全部任务 ```sql -- 分号换成 \G 显示完整 sql show processlist; show full processlist; SELECT command FROM information_schema.processlist; ``` ## MySQL 5.7 ssl 连接 ``` --ssl-mode=REQUIRED ``` ## MariaDB 10.1 修改密码 ```sql UPDATE user SET password=password('newpassword') WHERE user='root'; ``` ## MySQL 5.7 编码 - 查看 ```sql SHOW VARIABLES LIKE 'character_set%'; ``` - 数据库连接参数中,characterEncoding=utf8 会被自动识别为 utf8mb4,但是 autoReconnect=true 必须指定 - 更改数据库编码 ```sql ALTER DATABASE db_name CHARSET UTF8MB4 COLLATE UTF8MB4_GENERAL_CI; ``` - 更改表编码 ```sql ALTER TABLE table_name CONVERT TO CHARSET UTF8MB4 COLLATE UTF8MB4_GENERAL_CI; ``` ## MySQL 5.7 升级数据库管理表结构 ```bash mysql_upgrade -u root -p ``` ## MySQL 5.7 误删 root 后恢复 root 账户 - 停止 mysql 服务 ```bash systemctl stop mysqld ``` - 修改 my.cnf ``` # 添加如下一行 skip-grant-tables ``` - 启动 mysql 服务 ```bash systemctl start mysqld ``` - 重建 root 账户,并授权 ```sql insert into user set user='root', ssl_cipher='', x509_issuer='', x509_subject=''; update user set Host='localhost', select_priv='y', insert_priv='y', update_priv='y', Alter_priv='y', delete_priv='y', create_priv='y', drop_priv='y', reload_priv='y', shutdown_priv='y', Process_priv='y', file_priv='y', grant_priv='y', References_priv='y', index_priv='y', create_user_priv='y', show_db_priv='y', super_priv='y', create_tmp_table_priv='y', Lock_tables_priv='y', execute_priv='y', repl_slave_priv='y', repl_client_priv='y', create_view_priv='y', show_view_priv='y', create_routine_priv='y', alter_routine_priv='y', create_user_priv='y', event_priv='y', trigger_priv='y', create_tablespace_priv='y' where user='root'; flush privileges; ``` - 停止 mysql 服务 ```bash systemctl stop mysqld ``` - 修改 my.cnf ``` # 删除或注释刚添加的如下一行 skip-grant-tables ``` - 启动 mysql 服务,root 账户正常可用 ```bash systemctl start mysqld ``` ## 通过EXPLAIN分析SQL的执行计划 - 使用 ```sql explain sql ``` - select_type 查询类型 - SIMPLE 简单表,没有表连接或子查询 - PRIMARY 最外层的查询 - UNION union语句的后置查询 - SUBQUERY 第一个子查询 - table 表/别名 - type 访问类型 - ALL 全表扫描 - index 全索引扫描 - range 索引范围扫描 - ref 非唯一索引扫描 - eq_ref 唯一索引扫描 - const,system 单表最多一个匹配行 - NULL 不需要扫描表或索引 - possible_keys 查询可能使用的索引 - key 实际使用的索引 - key_len 使用的索引字段的长度 - ref 其他匹配字段 - rows 扫描行的数量 - filtered 满足查询条件的记录占存储引擎返回记录的比例 - Extra 执行情况说明 - Using Index 全部使用索引,没有回表查询 - Using Where 有回表查询 - Using Index Condition ICP优化,直接在存储引擎完成条件过滤 - Using Flesort 依靠索引顺序达不到排序效果,需额外排序 ## 统计 insert、delete、update 和 select 次数 ```sql show global status where Variable_name in ('com_insert', 'com_delete', 'com_update', 'com_select'); ``` ## csv 文件 - 导出 ``` # Shell 终端 # mysql -e "select * from t1 into outfile '/var/lib/mysql-files/t1.csv' fields terminated by ',' enclosed by '\"' escaped by '\\\' lines terminated by '\n'" # MySQL 终端 # MySQL> select * from t1 into outfile '/var/lib/mysql-files/t1.csv' fields terminated by ',' enclosed by '\"' escaped by '\\' lines terminated by '\n'; ``` - 导入 ``` # Shell 终端 # mysql -e "load data infile '/var/lib/mysql-files/t1.csv' into table t1 fields terminated by ',' enclosed by '\"' escaped by '\\\' lines terminated by '\n'" # MySQL 终端 # MySQL> load data infile '/var/lib/mysql-files/t1.csv' into table t1 fields terminated by ',' enclosed by '\"' escaped by '\\' lines terminated by '\n'; ``` ## mysql8 配置登录失败 5 次锁定 5 分钟 - 安装插件 ``` docker exec -ti mysql mysql -e " install plugin CONNECTION_CONTROL soname 'connection_control.so'; install plugin CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS soname 'connection_control.so'; " ``` - 查看插件列表 ``` docker exec -ti mysql mysql -e "show plugins" # 此时会看到最后两行时新激活的插件 ``` - 修改 my.cnf,增加两行 ``` connection-control-failed-connections-threshold=5 connection-control-min-connection-delay=300000 ``` - 重启 mysql