Mysql 使用总结
字段类型选择
整数: TINYINT(1字节), MEDIUMINT(2字节), INT(4字节) BIGINT(8字节)。如果确定是正整数,使用unsigned
注意: INT(11): 只是客户端用来显示的长度,并不会改变INT的字节数
字符串:VARCHAR 和CHAR。 VARCHAR类型用于存储可变长字符串
枚举:ENUM,在实际开发中,尽量不使用枚举,除非值的选项是确定的(往往业务开发中,选项是不确定的)
时间: DATETIME 和 TIMESTAMP
DATETIME 他把日期和时间封装到格式为(YYMMDDHHMMSS)的整数中,使用8个字节,保存的年份到(1001 - 9999)最后显示的格式为:0000-00-00 00:00:00,和时区有关
TIMESTAMP 他保存的时间为1970-2038, 使用4个字节,和时区有关,默认情况下,插入和更新的时候,不输入时间的话,则使用当前的时间
尽量使用TIMESTAMP,因为他的效率更好
NOT NULL
MySQL中的NULL其实是占用空间的, NULL不利于索引,尽量使用NOT NULL
特殊SQL优化
COUNT 优化
select COUNT(*) from table where id > 5
如果这条语句扫描数据条数过得,可以转化sql为:
select count(*) from table - select count(*) from table where id <= 5
LIMIT 分页优化
LIMIT 10000, 20
的查询会扫描10020条数据,然后只返回最后的20条,前面的10000条数据都会被抛弃,代价非常高。
方案一: 把limit转化为已知的扫描记录
假设LIMIT 10000
是从id=10000开始,则可以转化为
where id >= 10000 and id < 10020
方案二: 使用缓存先去1000条数据,分页每次都从缓存里面读取,这样mysql的数据不会被抛弃
ORDER BY 优化
ORDER BY的字段最好创建索引,在索引字段上排序,可以直接使用索引的顺序
mysql 系列文章
总结:
MySQL InnoDB存储引擎,实现的是基于多版本的并发控制协议
快照读:简单的select操作,属于快照读,不加锁
当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。(select for update, lock in share mode)
- InnoDB与MySQL Server的交互,是一条一条进行的,因此,加锁也是一条一条进行的。先对一条满足条件的记录加锁,返回给MySQL Server,做一些DML操作;然后在读取下一条加锁,直至读取完毕
- 锁操作分为两个阶段:加锁阶段与解锁阶段,并且保证加锁阶段与解锁阶段不相交
- InnoDB 支持事务
- 原子性(Atomicity) 使用undo log保证原子性
持久性(Durability) 使用redo log 保证持久性 mysql执行sql后首先把修改的内容写入到redo log 然后写入到mysql Buffer Pool, mysql异步处理,把Buffer Pool的内容刷到磁盘,然后Buffer Pool的数据没有刷到磁盘,mysql宕机了,此时采用redo log就是恢复
隔离性(Isolation) 两个事务之间相互隔离
- 脏读:事务A可以读取到事务B中未提交的数据
- 不可重复读:事务A两次读同一数据,读到的数据不一样(有另外一个事务B提交改写了某条数据)
- 幻读:事务A两次使用相同的条件查询,查询记录的条数不一样(有另外的事务提交了新数据)
默认隔离级别RR(可重复读),(Read Uncommmit, Read Commit Repeatable Read, Serializable)
RR 解决脏读、不可重复读、幻读(GAP锁)等问题,使用的是 MVCC:MVCC 全称 Multi-Version Concurrency Control,即多版本的并发控制协议
mysql解决方案如下:
- 脏读, 事务A发现某条数据已经被修改,且状态为未提交,则使用undo log进行回滚
不可重复读,事务A第一次读,记录加入版本号,由于数据被其他事务修改,记录版本号变化,事务A第二次读,发现版本号对不上,使用undo log回滚
幻读,使用gap锁
一致性: 指数据结构约束条件完整,比如主键存在且唯一
[数据一致性-分区可用性-性能——多副本强同步数据库系统](http://hedengcheng.com/?p=892