演讲人 : 杨建荣
个人介绍 - 杨建荣 Oracle ACE DBAplus 联合发起人 YEP 成员 Oracle 10g OCP,OCM MySQL OCP 对 shell, Java 有一定的功底 <<Oracle DBA 工作笔记 作者 曾在中国数据库大会,Oracle 嘉年华,QCon 演讲 坚持每天写点东西, 已连续坚持 1200 多天 微信公众号 (jianrong-notes)
入行时难忘的一个坑 MySQL 重启 看似没有技术含量, 危机四伏 Slave 节点宕机 重新搭建 Slave 节点 Master 节点开启 Log_bin 重启 应用连接异常 数据字典异常
学习建议 x$kcbsw 结构包含了 Oracle 处理一个 会话逻辑 I/O 所需的所有命名函数 在 11.2.0.3 版本, 我曾指出有 1164 个命名函数, 但看看运行在 64 位 OEL(Oracle 企业版 Linux 操作系统 ) 上的 12.1.0.1 版本, 这个数字是 1300 这一变化对本书内容来说有多大区别? 对普通 Oracle 专业人士呢? 答案是 没有区别! Jonathan Lewis
懂得权衡 学习 Oracle 时要懂得权衡 大部分时候, 只要大体知道引擎是如何工作的就足够了, 偶尔才需要知道一些世界上只有一小部分人才会知道的精确资料 注意, 不要浪费时间去研究不必要的细节, 而是要找到折中的办法, 使你所掌握的知识足以预判 Oracle 在你没见过的场景中会怎样做
MySQL 被收购后开发团队成员去向
现如今的 MySQL
分享脉络 数据管理 :MySQL 无法创建表的问题 架构设计 : MySQL 中需要注意的字段长度 开发扩展 : 数值类型在 binlog 中需要注意的细节 前瞻 : 关于时间类型的默认值 综合能力 :Oracle 跨平台迁移方案优化
管理 :MySQL 无法创建表的问题 CREATE TABLE `QRTZ_JOB_DETAILS` (`SCHED_NAME` varchar(120) NOT NULL); ERROR 1005 (HY000): Can't create table 'xxx.qrtz_job_details' (errno: 150) 创建 10 多个表, 只有 2 个表创建失败了, 可重现 问题初步原因猜测 : ü 大小写 ü 数据类型 ü 触发器 ü 外键 ü bug
临时解决方案 > create table QRTZ_JOB_DETAILSS(id int); Query OK, 0 rows affected (0.13 sec) > create table qrtz_job_details(id int); Query OK, 0 rows affected (0.13 sec)
第三方工具的神助攻 DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`; Navicat 工具 SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;
架构设计 :MySQL 中需要注意的字段 长度 MySQL 里面的页的单位是 16k, 使用了 IOT 的方式来存储 字符集,latin1,gbk,utf8 使用了 varchar 类型, 如果指定为 gbk, 表里含有一个字段, 可以指定为 32766 字节, 如果再长一些就不行了 gbk 类型, 行长度最大为 65535, 则 varchar 列的最大长度算法就是 (65535-2)/2 =32766.5, 所以此处就是 32766
> create table test_char(v varchar(32766)) charset=gbk; Query OK, 0 rows affected (0.00 sec) > create table test_char1(v varchar(32767)) charset=gbk; ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
> create table test_char1(v varchar(32767)) charset=latin1; Query OK, 0 rows affected (0.01 sec) > create table test_char2(v varchar(65535)) charset=latin1; ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs (65535-2)/3 ~ 21844
> create table test_char2(v varchar(21844)) charset=utf8; Query OK, 0 rows affected (0.00 sec) > create table test_char3(v varchar(21845)) charset=utf8; ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
衍生问题? 如果是 gbk 字符集, 含有下面的几个字段, 则 memo 字段的 varchar 类型最大长度是多少? create table test_char3(id int,name varchar(20),memo varchar(xxxx)) charset=gbk; 数值型 4 个字节, 字符型乘以 2, 含有字符型的长度小于 255, 所以减去 1 即可, 这样下来就是 (65535-1-4-20*2-2) 约等于 32743
开发扩展 : 数值类型在 binlog 中需要 注意的细节 类型名称 有符号数 (signed) 无符号数 (Unsigned) tinyint -129~127 0~255 smallint -32768~32767 0~65535 mediumint -8388608~8388607 0~16777215 int(integer) -2147483648~2147483647 0~4294967295 bigint -9223372036854775808~ 9223372036854775807 0~184467440737095516 15 MySQL 的 binlog 里面是否会区分 signed 还是 unsigned 呢, 如果不区分, 这类问题该怎么应对
进制转换 > select conv(-1,10,2); +------------------------------------------------------------------+ conv(-1,10,2) +------------------------------------------------------------------+ 1111111111111111111111111111111111111111111111111111111111111111 +------------------------------------------------------------------+ > select conv(18446744073709551615,10,2); +------------------------------------------------------------------+ conv(18446744073709551615,10,2) +------------------------------------------------------------------+ 1111111111111111111111111111111111111111111111111111111111111111 +------------------------------------------------------------------+ 从机制转换的结果来看, 两者是没有差别的, 如果是实际的场景中, 这可是天壤之别
上手练习 create table t1 (id int unsigned not null auto_increment primary key, col1 bigint unsigned, col2 bigint signed) engine=innodb; insert into t1 (col1, col2) values (18446744073709551615, - 1); flush logs; > select * from t1; +----+----------------------+------+ id col1 col2 +----+----------------------+------+ 1 18446744073709551615-1 +----+----------------------+------+
解析 binlog mysqlbinlog -vv binlog.000031 ### INSERT INTO test.t1 ### SET ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ ### @2=-1 (18446744073709551615) /* LONGINT meta=0 nullable=1 is_null=0 */ ### @3=-1 (18446744073709551615) /* LONGINT meta=0 nullable=1 is_null=0 */ # at 268 #170519 18:54:47 server id 13386 end_log_pos 295 Xid = 76 COMMIT/*!*/; 对于 binlog 中, 有符号数和无符号数都会按照无符号数来转换 配合 information_schema 来查看
前瞻 : 关于时间类型的默认值 MySQL 5.5 CREATE TABLE `test_user` ( `openid` varchar(64) NOT NULL, `amount` varchar(11) DEFAULT 0, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`openid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ERROR 1067 (42000) at line 1: Invalid default value for 'create_time MySQL 5.6 Query OK, 0 rows affected (0.13 sec)
MySQL 5.5 对于时间类型的测试 >create table test(col1 datetime DEFAULT CURRENT_TIMESTAMP); ERROR 1067 (42000): Invalid default value for 'col1 > create table test(col1 datetime DEFAULT ''); ERROR 1067 (42000): Invalid default value for 'col1 > create table test(col1 datetime DEFAULT 2015-11-23 18:31:25 ); Query OK, 0 rows affected (0.02 sec) -- 奇怪 default 的动态默认值是在 5.6.5 开始支持
datetime 和 timestamp 的存储占用空间不同, datetime 占用 8 个字节,timestamp 占用 4 个字节, timestamp 支持的时间范围要窄一些 范围为 : 1970-01-01 08:00:01 到 2038-01-19 11:14:07 而 datetime 支持的时间范围则要大很多 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 解决方法 : 取消默认值, 修改字段类型改为 timestamp
综合案例 :Oracle 跨平台迁移方案 优化
不断的拆分, 力求可控
人才的评价标准 微软的人才评价标准 1. 迅速掌握新知识的能力 2. 仅需片刻思考即可提出尖锐问题的能力 3. 可以在不同的领域知识中找出它们之间的联系 4. 扫视一眼即可用通俗语言解释软件代码的能力 5. 关注眼前问题的执行力 ( 怎么解决, 解决方法 ) 6. 非常强的集中注意力的能力 7. 对自己过去的工作依然记忆犹新 8. 注重实际的思想观念, 善于表达, 勇于面对挑战 快速反应
积累自己的知识体系
矛盾和困扰并存, 用心掌握