MySQL 基础技能与原理 ——高级应用 MySQL DBA Team 彭立勋( http://www.penglixun.com )
内容概要 6. MySQL 数据库同步方案 7. MySQL 与应用程序的优化 8. MySQL 管理基础 9.  网站常见错误分析 10. MySQL 故障案例
MySQL 数据库同步方案 Trigger 同步方案 (Otter) Log 同步方案( Erosa ) 自带 Replication 同步方案
Trigger 同步方案 Otter 采用 Trigger 方式进行同步。基本原理是为每张要同步的表加上一个触发器,表上增删改都会触发 Trigger 把主键记录到一张同步表,同步程序读取同步表的主键和修改类型,到目标表去执行相同的操作,保证最终一致。 优点:安全可靠,不会因为日志格式变化或数据库本身的机制变动带来同步程序的大改动。 缺点:对数据库入侵大,需要为每张表建立 Trigger ,并且在数据库建立存储过程,执行存储过程和触发器会带来一定的数据库压力。
Log 同步方案 Erosa 采用解析日志的方式进行同步。通过解析 Oracle 的 RedoLog 或 MySQL 的 BinLog ,获取在数据库上执行的 SQL 及其顺序,分发到目标数据库去执行一遍,以获得最终一致。 优点:对数据库入侵小,可以将日志拷贝到异地分析,对数据库本身不会增加压力。 缺点:对日志格式依赖大,日志格式发生变动则同步程序需要进行较大改动。
Replication 同步方案 MySQL 自带 Replication 复制方案, Oracle 也有基于块复制的 Stanf by 方案。 MySQL 通过将执行的增删改 SQL 记录到日志,传输到备机再执行一遍保证最终一致性。可以设置日志格式为 ROW (按行记录), Statement (按 SQL 记录), MIXED (混合式,让 MySQL 决定每次记录用哪个格式), DDL 全部通过 Statement 方式记录。 优点: MySQL 自带,无需第三方工具,部署方便, MySQL 自带丰富的参数可以实现各种复制方案,包括双 Master ,级联 Slave 等。 缺点:无法实现多源复制,复制位置丢失很难恢复复制。
MySQL 与应用程序的优化 预处理与绑定变量 连接池设置及影响 应用程序实现 JOIN
预处理与绑定变量 PREPARE 语句 : SET@sql1=‘xxx’; PREPARE stmt1 FROM @sql1; 变量用问号代替(绑定变量)。 作用:将 SQL 预先解析,在一个 Session 内再次使用此语句时不再重新解析。 EXECUTE 语句 : EXECUTE stmt1 USING @val1,@val2; 作用:将绑定变量赋予具体的值并且执行。 DEALLOCATE 语句 :  DEALLOCATE PREPARE stmt1; 作用:销毁一个预解析 SQL ,释放资源。 为何使用绑定绑定变量? 因为绑定变量比直接传值更安全,尤其是拼接 SQL 非常容易被注入攻击。同时绑定变量也可以提高一点效率。 为何使用预处理,尤其在存储过程? 因为预处理可以避免 SQL 的反复解析,尤其是执行速度快的小 SQL ,解析时间甚至可能超过执行时间,采用预处理可以显著提高性能。
连接池设置及影响 MySQL 如何处理连接 ? 每次客户端向数据库服务器请求一个连接,服务器根据用户名密码在已有连接内查找一个相同配置的连接,分配给请求。如果找不到,则数据库分配一个新连接给当前请求。 分配新连接做哪些工作 ? MySQL 新开一个连接,就会创建一个新的 mysql 结构体,其中包括 Join_buffer 、 Sort_buffer 和一个 Session 变量存储数组。 如果连接数过多会怎么样 ? 如果连接 MySQL 的线程太多,那么每个线程分配到的 join_buffer+sort_buffer 总量就会很大,占用大量内存。 如何设置连接池 ? 建议最小值和最大值差距不要太大,避免连接反复的创建和释放,带来 CPU 开销。如果连接数一直比较平稳的应用,则最小值和最大值在平均线附近设置即可。如果连接数长期较高,则最小值也设置大一些。如果连接数长期较低,则最大值偏小设置。
应用程序实现 JOIN 如果需要跨主机进行 JOIN ,跨应用进行 JOIN ,或者数据库不能获得较好的执行计划,都可以自己通过程序来实现 JOIN 。 例如: SELECT a.*,b.* FROM a,b WHERE a.col1=b.col1 AND a.col2> 10 ORDER BY a.col2; 可以利用程序实现,先 SELECT * FROM a WHERE a.col2>10 ORDER BY a.col2;--(1) 利用 (1) 的结果集,做循环, SELECT * FROM b WHERE b.col1=a.col1; 这样可以避免排序,可以在程序里控制执行的速度,有效降低数据库压力,也可以实现跨主机的 JOIN 。 《 内连接实现例子 》 《 外连接实现例子 》
MySQL 管理基础 HA 与海量数据方案 复制搭建方法 简单备份方案 简易故障处理 运维风险点
HA 与海量数据方案 Heartbeat 方案 :利用 Heartbeat 管理 VIP ,利用 crm 管理 MySQL , MySQL 进行双 M 复制。( Linux 系统下没有分库的标准方案) LVS+Keepalived 方案 :利用 Keepalived 管理 LVS 和 VIP , LVS 分发请求到 MySQL , MySQL 进行双 M 复制。( Linux 系统下无分库无事务的方案) Cobar 方案 :利用 Cobar 进行 HA 和分库,应用程序请求 Cobar , Cobar 转发请求道数据库。(有分库的标准方案, Unix 下唯一方案)
复制搭建方法 搭建复制的必备条件:复制的机器之间网络通畅, Master 打开了 binlog 。 搭建复制步骤 : 1.  创建复制账户: GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY‘xxx'; 2. SHOW MASTER STATUS; 记录下 File 和 Postion 。 3.  在 Slave 上 CHANGE MASTER TO master_host=‘IP‘, master_user='repl', master_password=‘xxx’, master_log_file='mysql-bin.00000x', master_log_pos=pos; 4. Slave 上执行 Slave start 开始复制。
简单备份方案 冷备份: MyISAM :拷贝数据目录下数据库名的目录即可,恢复只要拷贝回来即可。 InnoDB :拷贝全部数据目录。 热备份: MyISAM : Flush Tables With Read Lock; 后可以直接拷贝。 InnoDB : xtrackaup 来实现。 逻辑备份: mysqldump –u 用户 – p 密码 数据库  [ 表 1  表 2…] > db.sql 全库完整备份(带复制 Postion ): mysqldump -uroot -p --all-databases --opt --add-drop-database --add-drop-table --events --triggers --routines --default-character-set=utf8 --master-data=2  --single-transaction --complete-insert --quote-names --log-error=/tmp/mysqldump20100803.log >backup_20100803.sql
简易故障处理 启动不成功怎么办? 查看 error.log ,如果报出 can’t create/write dictory ,那就是权限设置错误。 MySQL 的数据目录要求 MySQL 可以读它的上级目录,可以写数据目录。 复制主键冲突怎么办? STOP SLAVE; SET GLOBAL SQL_SLAVE_skip_counter = 1; START SLAVE; SHOW SLAVE STATUS \G ,原理是跳过出错的行。也可以设置 my.cnf 中的 skip_slave_errors=1062 来批量的跳过复制错误(需要重启)。 死锁怎么办? show innodb status; 查看死锁的事务, kill 掉其中一个即可。 大量 SQL 在 freeing items 怎么办? 数据库所在磁盘已满,请检查磁盘空间。
运维风险点 主库的任何操作都会复制到备库。 如果需要备库具备容灾能力,那么不要实时开着 slave 复制,每隔一段时间 slave start 一次,复制追上后 slave stop 停止,直到下一次复制开始。 同时 DROP/ADD 字段或索引可能导致数据库 Crash 。 已经在 MySQL Bug 库中确认此 Bug ,如果表很大,即使花再多的时间,也不要冒险尝试同时 DROP/ADD 字段或索引,分两次,一次 ADD 一次 DROP 。 HA 切换如果主备主键序列一致可能导致冲突。 如果主键是自增并且主备序列一致,那么切换时可能主库存在记录没有来得及复制到备机,导致备机的序列增长盖过主机,导致复制冲突。解决方案是主备生成不一致的主键序列,例如一个奇数,一个偶数,或者利用第三方主键生成器。
网站常见故障分析 SQL 执行计划改变导致 SQL 占用大量 CPU 。 统计 SQL 在数据量增大后占用大量磁盘 IO 和 CPU 。 SQL 中存在 NULL 条件,导致执行计划走错。 存储过程没有使用预处理和绑定变量,导致解析 SQL 占用大量 SQL 。 大批量修改操作没有 SET AUTOCOMMIT=0 ,导致每条 SQL 均提交,效率低。 SQL 未经审核上线,导致没有建立索引,执行计划为全表扫描。
MySQL 故障案例 BRMMS 故障

MySQL基础技能与原理——高级应用

  • 1.
    MySQL 基础技能与原理 ——高级应用MySQL DBA Team 彭立勋( http://www.penglixun.com )
  • 2.
    内容概要 6. MySQL数据库同步方案 7. MySQL 与应用程序的优化 8. MySQL 管理基础 9. 网站常见错误分析 10. MySQL 故障案例
  • 3.
    MySQL 数据库同步方案 Trigger同步方案 (Otter) Log 同步方案( Erosa ) 自带 Replication 同步方案
  • 4.
    Trigger 同步方案 Otter采用 Trigger 方式进行同步。基本原理是为每张要同步的表加上一个触发器,表上增删改都会触发 Trigger 把主键记录到一张同步表,同步程序读取同步表的主键和修改类型,到目标表去执行相同的操作,保证最终一致。 优点:安全可靠,不会因为日志格式变化或数据库本身的机制变动带来同步程序的大改动。 缺点:对数据库入侵大,需要为每张表建立 Trigger ,并且在数据库建立存储过程,执行存储过程和触发器会带来一定的数据库压力。
  • 5.
    Log 同步方案 Erosa采用解析日志的方式进行同步。通过解析 Oracle 的 RedoLog 或 MySQL 的 BinLog ,获取在数据库上执行的 SQL 及其顺序,分发到目标数据库去执行一遍,以获得最终一致。 优点:对数据库入侵小,可以将日志拷贝到异地分析,对数据库本身不会增加压力。 缺点:对日志格式依赖大,日志格式发生变动则同步程序需要进行较大改动。
  • 6.
    Replication 同步方案 MySQL自带 Replication 复制方案, Oracle 也有基于块复制的 Stanf by 方案。 MySQL 通过将执行的增删改 SQL 记录到日志,传输到备机再执行一遍保证最终一致性。可以设置日志格式为 ROW (按行记录), Statement (按 SQL 记录), MIXED (混合式,让 MySQL 决定每次记录用哪个格式), DDL 全部通过 Statement 方式记录。 优点: MySQL 自带,无需第三方工具,部署方便, MySQL 自带丰富的参数可以实现各种复制方案,包括双 Master ,级联 Slave 等。 缺点:无法实现多源复制,复制位置丢失很难恢复复制。
  • 7.
    MySQL 与应用程序的优化 预处理与绑定变量连接池设置及影响 应用程序实现 JOIN
  • 8.
    预处理与绑定变量 PREPARE 语句: SET@sql1=‘xxx’; PREPARE stmt1 FROM @sql1; 变量用问号代替(绑定变量)。 作用:将 SQL 预先解析,在一个 Session 内再次使用此语句时不再重新解析。 EXECUTE 语句 : EXECUTE stmt1 USING @val1,@val2; 作用:将绑定变量赋予具体的值并且执行。 DEALLOCATE 语句 : DEALLOCATE PREPARE stmt1; 作用:销毁一个预解析 SQL ,释放资源。 为何使用绑定绑定变量? 因为绑定变量比直接传值更安全,尤其是拼接 SQL 非常容易被注入攻击。同时绑定变量也可以提高一点效率。 为何使用预处理,尤其在存储过程? 因为预处理可以避免 SQL 的反复解析,尤其是执行速度快的小 SQL ,解析时间甚至可能超过执行时间,采用预处理可以显著提高性能。
  • 9.
    连接池设置及影响 MySQL 如何处理连接? 每次客户端向数据库服务器请求一个连接,服务器根据用户名密码在已有连接内查找一个相同配置的连接,分配给请求。如果找不到,则数据库分配一个新连接给当前请求。 分配新连接做哪些工作 ? MySQL 新开一个连接,就会创建一个新的 mysql 结构体,其中包括 Join_buffer 、 Sort_buffer 和一个 Session 变量存储数组。 如果连接数过多会怎么样 ? 如果连接 MySQL 的线程太多,那么每个线程分配到的 join_buffer+sort_buffer 总量就会很大,占用大量内存。 如何设置连接池 ? 建议最小值和最大值差距不要太大,避免连接反复的创建和释放,带来 CPU 开销。如果连接数一直比较平稳的应用,则最小值和最大值在平均线附近设置即可。如果连接数长期较高,则最小值也设置大一些。如果连接数长期较低,则最大值偏小设置。
  • 10.
    应用程序实现 JOIN 如果需要跨主机进行JOIN ,跨应用进行 JOIN ,或者数据库不能获得较好的执行计划,都可以自己通过程序来实现 JOIN 。 例如: SELECT a.*,b.* FROM a,b WHERE a.col1=b.col1 AND a.col2> 10 ORDER BY a.col2; 可以利用程序实现,先 SELECT * FROM a WHERE a.col2>10 ORDER BY a.col2;--(1) 利用 (1) 的结果集,做循环, SELECT * FROM b WHERE b.col1=a.col1; 这样可以避免排序,可以在程序里控制执行的速度,有效降低数据库压力,也可以实现跨主机的 JOIN 。 《 内连接实现例子 》 《 外连接实现例子 》
  • 11.
    MySQL 管理基础 HA与海量数据方案 复制搭建方法 简单备份方案 简易故障处理 运维风险点
  • 12.
    HA 与海量数据方案 Heartbeat方案 :利用 Heartbeat 管理 VIP ,利用 crm 管理 MySQL , MySQL 进行双 M 复制。( Linux 系统下没有分库的标准方案) LVS+Keepalived 方案 :利用 Keepalived 管理 LVS 和 VIP , LVS 分发请求到 MySQL , MySQL 进行双 M 复制。( Linux 系统下无分库无事务的方案) Cobar 方案 :利用 Cobar 进行 HA 和分库,应用程序请求 Cobar , Cobar 转发请求道数据库。(有分库的标准方案, Unix 下唯一方案)
  • 13.
    复制搭建方法 搭建复制的必备条件:复制的机器之间网络通畅, Master打开了 binlog 。 搭建复制步骤 : 1. 创建复制账户: GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY‘xxx'; 2. SHOW MASTER STATUS; 记录下 File 和 Postion 。 3. 在 Slave 上 CHANGE MASTER TO master_host=‘IP‘, master_user='repl', master_password=‘xxx’, master_log_file='mysql-bin.00000x', master_log_pos=pos; 4. Slave 上执行 Slave start 开始复制。
  • 14.
    简单备份方案 冷备份: MyISAM:拷贝数据目录下数据库名的目录即可,恢复只要拷贝回来即可。 InnoDB :拷贝全部数据目录。 热备份: MyISAM : Flush Tables With Read Lock; 后可以直接拷贝。 InnoDB : xtrackaup 来实现。 逻辑备份: mysqldump –u 用户 – p 密码 数据库 [ 表 1 表 2…] > db.sql 全库完整备份(带复制 Postion ): mysqldump -uroot -p --all-databases --opt --add-drop-database --add-drop-table --events --triggers --routines --default-character-set=utf8 --master-data=2 --single-transaction --complete-insert --quote-names --log-error=/tmp/mysqldump20100803.log >backup_20100803.sql
  • 15.
    简易故障处理 启动不成功怎么办? 查看error.log ,如果报出 can’t create/write dictory ,那就是权限设置错误。 MySQL 的数据目录要求 MySQL 可以读它的上级目录,可以写数据目录。 复制主键冲突怎么办? STOP SLAVE; SET GLOBAL SQL_SLAVE_skip_counter = 1; START SLAVE; SHOW SLAVE STATUS \G ,原理是跳过出错的行。也可以设置 my.cnf 中的 skip_slave_errors=1062 来批量的跳过复制错误(需要重启)。 死锁怎么办? show innodb status; 查看死锁的事务, kill 掉其中一个即可。 大量 SQL 在 freeing items 怎么办? 数据库所在磁盘已满,请检查磁盘空间。
  • 16.
    运维风险点 主库的任何操作都会复制到备库。 如果需要备库具备容灾能力,那么不要实时开着slave 复制,每隔一段时间 slave start 一次,复制追上后 slave stop 停止,直到下一次复制开始。 同时 DROP/ADD 字段或索引可能导致数据库 Crash 。 已经在 MySQL Bug 库中确认此 Bug ,如果表很大,即使花再多的时间,也不要冒险尝试同时 DROP/ADD 字段或索引,分两次,一次 ADD 一次 DROP 。 HA 切换如果主备主键序列一致可能导致冲突。 如果主键是自增并且主备序列一致,那么切换时可能主库存在记录没有来得及复制到备机,导致备机的序列增长盖过主机,导致复制冲突。解决方案是主备生成不一致的主键序列,例如一个奇数,一个偶数,或者利用第三方主键生成器。
  • 17.
    网站常见故障分析 SQL 执行计划改变导致SQL 占用大量 CPU 。 统计 SQL 在数据量增大后占用大量磁盘 IO 和 CPU 。 SQL 中存在 NULL 条件,导致执行计划走错。 存储过程没有使用预处理和绑定变量,导致解析 SQL 占用大量 SQL 。 大批量修改操作没有 SET AUTOCOMMIT=0 ,导致每条 SQL 均提交,效率低。 SQL 未经审核上线,导致没有建立索引,执行计划为全表扫描。
  • 18.