高性能推荐的MySQL分支版本:
mariaDB、percona server
对于非严格苛刻交易型的数据表,建议用 MariaDB,这个版本目前在开源界很盛行,评价很高,percona 版本也值得推荐,percona 有很多辅助的运维工具。
有意思的函数
in用group_concat()函数,@@GROUP_CONCAT_MAX_LEN表示分组的最大长度
convert()/cast()函数
least(...)、greatest(...):如果有空则返回空,否则找到最大最小值
ISNULL()、NULLIF()、IF()
COALESCE(...):找到第一个非空值
select sleep(1000);让select阻塞
select get_lock()、select release_lock()、select connection_id()
事务
隔离级别:
- serializable
- repeatable read(理论会发生幻读,但是mysql通过mvcc避免)
- read committed(不可重复读)
- read uncommitted(脏读)
查看:select @@global.tx_isolation, @@session.tx_isolation;
设置:
set sesion transaction isolation level serializable
set @@session.tx_isolation=default;
锁
表锁:是共享锁,读加共享锁(支持并发insert)、写加排他锁(写的时候其他事务不能读不能写)
死锁:innodb将持有最少行排他锁的事务回滚来解决死锁问题
原理:用两阶段锁定协议
在非事务引擎(MyISAM)执行事务回滚不会起任何作用,所在事务中既有事务表又有非事务表将导致数据的不一致
MVCC:innodb采用MVCC来支持高并发,只在Repeatable read和read committed两个隔离级别下工作,因为read uncommited总是读最新的行,而serializable则会对所有的读取加锁
优化
字段类型
字段越小越好,用日期类型不用字符串;用整形存储ip;尽量设计列不为null,这样可以避免全表扫描;
integer、bool、numeric都是别名,用show create table显示的是基本类型,不是别名
比如int(1)、int(20),后面这个长度只是让客户端这列显示的长度,真实存储的都是32位
float、double都是存储的是近似值,decimal存储的是精确值,然而计算的时候float、decimal还是会转为double
字符串可以指定字符集、排序规则、校验规则
枚举类型enum,比如性别,排序是按照索引值排序,而不是显示值,小心使用
避免使用set、bit
热备份
只有innodb支持热备,其他引擎不支持,工具包括:Mysql enterprise backup、xtrabackup
存储引擎
Innodb
唯一支持事务、行锁、外键的存储引擎;采用双写算法,可以避免数据损坏,并发修改性能最好,首选引擎
MyISAM
不支持事务、锁、外键,采用前缀压缩索引,所以回滚事务对myisam不起作用,另外myisam数据不安全可能会损坏,读多少写很适合
archive
只支持insert和select,支持行锁,不是一个事务性引擎,而是一个针对高速插入和压缩做了优化的简单引擎
Blackhole
不保存数据,只记录日志,可以用在复制架构、日志审核,不推荐使用
CSV
用csv文件作为mysql的表来处理,复制一个文件来就可以用,常用来做数据交换,非常有用
Memory
数据存内存,重启丢失。表锁,所以并发insert性能不好,mysql需要使用临时表时,默认就是用的memory引擎,当内存不够,或者包含blob、text则转换为MyISAM引擎,可以用substring()避免,另外char、varchar在memory引擎里面是一样的
极限
单表1千万
单库5TB
基准测试
性能其实就是响应时间长短
构建高可扩展性系统:避免串行化和系统间交互
测试方向
- 吞吐量TPS
- 响应时间或延迟
- 并发性:通过sysbench指定32、64、128线程测试,观察Threads_running状态值
- 可扩展性:增加资源,吞吐量、并发性是否线性增加
工具
xhprof、new relic、xdebug、valgrind、cachegrind、strace、user_statistics、pt-query-advisor、innotop、pt-query-digest(加热缓存数据)、
mysqlbinlog、pt-archiver、pt-heartbeat(检测备库延迟多久)、pt-table-checksum(检测主备是否一致)、pt-table-sync(发现主备不一致,同步主库的工具)、mysqlbinlog、pt-slave-delay、pt-slave-start
监控
show [global] status;
show [global] variables;
启动时间长度:show [global] status like 'uptime'(秒)
查看指令的执行次数:show [global] status like 'Com_select'、show [global] status like 'Com_insert'、show [global] status like 'Com_update'、show [global] status like 'Com_delete'
查看连接数:show [global] status like 'connections'
显示慢查询:show [global] status like 'slow_queries'
定位慢查询:show variables like 'long_query_time'
设置慢查询时间:set long_query_time=1,set long_query_time=0捕获所有查询
慢查询剖析报告工具:pt-query-digest
select
@@profiling;
set profiling=1; --开启统计
show profile; --查看最近一条统计
show profiles; --查看所有统计
show profile for query 1; --查看指定的统计
常用命令
alter table允许alter column、modify column、change column语句修改列,三种操作都不一样
flush tables with read lock;关闭所有正在使用的表,并禁止任何表的打开,用unlock tables;解锁
alter table tableName disable keys;//禁用非唯一索引;alter table tableName enable keys;//开启索引
check table;检查表 optimize table重新组织表;analyze table重新生成表的统计信息;repair table
关闭状态myisam修复表可以用:myisamchk命令行
show index from tableName;中Cardinnality字段就是估计该索引有多少种值
show processlist;查看连接线程
KILL
[CONNECTION | QUERY]
thread_id:杀死指定processlist的线程
外键
innodb是唯一支持外键的存储引擎,外键在每次修改数据时都要在外键表执行一次查找操作,增加了开销
mysql强制要求外键使用索引
高性能系统一般不用外键,而是通过应用程序维护
索引
优点
- 大大减少需要扫描的数据量
- 避免排序和临时表
- 将随机IO变为顺序IO
缺点
增加修改数据的消耗,TB级别数据可能使用块级别技术代替索引
类型
BTREE:适合全值匹配;最左前缀;列前缀;范围值;精确某一列,模糊另外一列(注意:使用模糊后,后面的索引项将不能再起索引作用);只访问索引的查询;用于order by;group by;缺点:大长度的列导致索引占用空间很大,比如存储url
HASH:只能用于精确匹配,优点是速度快,占用空间小(哈希值),只有MEMORY、NDB引擎支持,MEMORY引擎也支持BTREE引擎
RTREE:空间数据索引,支持并不好,不要使用
全文索引:适用于match against操作,而不是普通的where操作
注意事项
函数放在=号左边,将不能用到索引
索引列不能是表达式的一部分,不能是函数的参数
在多个列上建立单独的单列索引,大部分情况下并不能提高MySQL的查询性能
当explain语句的extra列出现Using union()说明我们设计的索引很糟糕
要设计一个三星索引,这样索引的价值才最大化
innodb的主键是聚簇索引,非主键索引引用的主键的地址,所以需要两次BTREE查找
myisam的主键是非聚簇索引,其他索引也是非聚簇索引
避免随机的聚簇索引,例如用UUID做主键,因为每次插入都将导致叶节点的变动,增加很多IO
当explain语句的extra列出现Using index说明使用了覆盖索引,覆盖索引不用返回真实表数据,只访问索引就行,索引性能得到最大化,可以采用延迟关联技术来使用覆盖索引
当explain语句的type为index,说明使用了索引扫描来做排序
可以使用in等手段,不过滤行,当时启用了组合索引的前缀索引
要经常进行范围查询的列,应该放在组合索引的最后一列
当explain语句的type为range,表示做了范围查询
过滤性不高的列,不用加索引
查询优化
只返回需要的列,不要写select *这样的语句
explain的rows预估需要访问的行
mysql和客户端的通信采用半双工,任意时刻只有一方在发送数据
show processlist的state:
Sleep等待客户端发送数据
Query服务端正在执行查询或者将结果发送给客户端
Locked正在等待表锁,innodb的行锁不会出现这个状态
Analyzing and statistics正在收集存储引擎统计信息,并生成查询计划
Copy to tmp table [on disk]将结果复制到临时表,可能在group by、文件排序、union
Sort result 正在排序结果
Sending data 向客户端发送数据
查询缓存通过大小写哈希查找实现,命中缓存sql不会被解析,不用生成执行计划
mysql不支持全外连接
mysql的临时表是没有索引的
执行explain sql;show warnings;可以看到重构后的查询
explain select straight_join ;严格按照sql顺序执行
show status like '%Last_query_cost%';它是io_cost和cpu_cost的开销总和
mysql如果不能用索引执行排序,如果排序量小于排序缓冲区大小,则直接进行快速排序,否则将数据分块,单独执行快速排序,再合并
表锁是在服务器层实现的
mysql的in子查询会导致外层每查询到一行就执行子查询一次,可以用group_concat()函数或者改成join on优化
最大值最小值如果统计的是索引的列,但是where里面没有使用索引,则可以使用use index(索引名) + limit 1来优化
尽量避免使用select for update和select in share mode
关联查询时如果order by排序的字段全部来自同一张表,mysql先排序然后生成临时表(Using filesort);否则就是直接生成临时表,最后才排序(Using temporary; Using filesort)
insert ignore into可以在批量插入是忽略中间失败的记录直到执行完插入
SQL提示
用法:写道select、insert、update、delete关键词后面
HIGH_PRIORITY和LOW_PRIORITY:可以作用与select、insert、update、delete,高优先级放在队列最前面,低优先级放在队列最后面
DELAYED:对insert、replace有效,延迟插入,先放入缓冲区,导致LAST_INSERT_ID()函数失效
STRAIGHT_JOIN:强制优化器按照join的顺序执行,因为有时优化器优化的顺序不是sql里写的顺序
SQL_SMALL_RESULT和SQL_BIG_RESULT:用于group by和distinct,直接基于内存还是直接磁盘文件排序
SQL_BUFFER__RESULT:强制把结果放到临时表,以尽快释放锁
SQL_CACHE和SQL_NO_CACHE
USE INDEX=FORCE INDEX、IGNORE INDEX:强制使用索引、禁用索引
SELECT
*
FROM
table1
USE
INDEX
(
col1_index
,
col2_index
)
WHERE
col1
=
1
AND
col2
=
2
AND
col3
=
3
;
SELECT
*
FROM
table1
IGNORE
INDEX
(
col3_index
)
WHERE
col1
=
1
AND
col2
=
2
AND
col3
=
3
;
优化类型
count
说明:count(*)是统计总行数,而count(colName)是统计colName不为空的行数,count全表的速度很快
当where条件要扫描很多行数,可以用count(全表) - count(相反条件)的思路优化
在同一个sql中,用count(IF(boolean, yesValue, noValue))来统计出多个值
关联查询
多个关联,前面的表关联后生成临时表,然后临时又和后面的表关联生成临时表,以此类推,当关联时用的是后面表的索引
确保关联条件有用到索引
到A表和B表在c列上关联,如果关联顺序是A、B,则A的c列不用建立索引,因为用的B的索引
order by、group by最好只涉及一个列,这样mysql才能用索引优化
子查询
尽可能用关联查询代替
当查询的列比较少子查询可能比联合查询快
exists的子查询到的时候用select 1,可以减少数据访问
group by和distinct
说明:这两种会使用临时表和文件排序
可以使用SQL_SMALL_RESULT和SQL_BIG_RESULT优化
group by 加with rollup试一下看有没有性能提升
可以使用order by null让不再进行文件排序
limit
当访问大偏移量的行是,会导致要丢弃很多前面的行,可以使用延迟加载+索引覆盖(limit作用于覆盖索引的查询)技术解决,性能提升非常大
union
说明:union始终要把子表的结果缓存到临时表
应该是where、limit、order by等语句写道子查询里面,可以大大减少临时表的数据量
尽量是uion all,没有all将到导致做distinct检查,代价很高
使用自定义变量
注意:
使用变量的查询,无法使用缓存
mysql的变量是动态类型,所以最好在定义的时候赋值:0、0.0、''
使用未定义变量不会报错
赋值符号:=的优先级很低,需要使用括号包住
更新+返回的例子
查询重用
冷热数据分表
select for update
利用connection_id()直接update并记录是谁修改的,然后执行不加锁的select where thread_id=connection_id()
mysql调用外部服务
查询缓存
注意点
mysql是缓存完整select查询,然后跟踪查询涉及的表,如果表发生变化则缓存失效,这种实现简单高效
一模一样的sql才能命中缓存,多一个空格,注释,编码不同都不行
sql中包含函数、存储过程、变量、临时表、系统表都不会被缓存,所以最好换成常量值
查询缓存会增加读写的开销,读要写缓存,写失效缓存,如果缓存占用了大量的内存,失效操作会成为瓶颈
查询缓存是一个全局加锁排他操作
命中率= Qcache_hits / (Qcache_hits + Com_select),如果查询代价很大,就算命中率很低也会带来好处
show status like 'Com_%'; 查看各种类型命令执行次数
如果Com_select和Qcache_insert(缓存生成次数)相当,说明缓存一直被修改操作导致失效,正常情况应该是前者远大于后者
Qcache_hits:Qcache_insert达到3:1以上比较好,最好能够达到10:1
内存不足导致缓存失效会增加Qcache_lowmen_prunes的值
配置
query_cache_size:1024的整数倍,设置为0可以在线关闭缓存
query_cache_type:需要重启
0 (OFF, 不缓存或重新得到结果) ,在线设置并不能影响已存在缓存
1 (ON, 缓存所有的结果,除了 SELECT SQL_NO_CACHE ... 查询)
2 (DEMAND, 仅缓存 SELECT SQL_CACHE ... 查询)
query_cache_min_res_unit:可以取均值(query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
query_cache_wlock_invalidate:默认是OFF,ON会返回被其他链接锁住的表的数据,关闭会增加锁等待
flush query cache 整理缓存命令,会导致服务器僵死
reset query cache 清空查询缓存
flush tables 清除查询缓存
show status like 'Qcache%' 查看缓存状态
使用场景
读很多写很少的场景
汇总查询
join查询
分区
优点
分离热点数据,让其可能单独放在内存中
分表表容易维护数据,优化、检查、修复、删除、备份恢复
避免innodb单个锁的互斥访问
使用where让数据限制在一个分区,而分区列作为函数参数或表达式是不能的
分区不像BTREE,不会带来很多额外的开销
限制
最多1024分区(实践证明100左右分区比较合适)
分区表无法使用外键
分区字段包含主键或者唯一索引,则主键列和唯一索引都要包含进来
分页表达式只能返回一个整数
可能会出现mysql进程超过文件描述符的问题
类型
range
range columns
key
hash
list
sub
特殊说明
第一个分区是特殊分区,存放null,可以用第一个空分区来减少扫描代价
explain partition可以观察优化器是否做了分区过滤
分布式XA事务
关闭二进制日志:innodb_support_xa=0
一般mysql不用XA事务,用复制高效稳定很多
配置
服务器端的配置都在mysqld里面,client里面包含客户端的一些通用配置
配置key的单词之间用下划线或横线都可以,配置项都是小写
set [global] @@[session|global]var=default,可以session变量设置回全局变量的值,但是最好别用在全局变量
set命令不能带单位如1M,而配置文件可以
mysqladmin extended-status -ri60
init_file选项可以启动后执行的文件,每行一条SQL
内存使用配置
32位系统允许单进程最大分配2.5~2.7G内存
glibc可能也限制单次内存分配的大小为2G,那么innodb_buffer_pool不能大于2G
table_cache_size:如果大于缓存的表数量,则新打开的表加入缓存,否则删除不常用的表,缓存.frm文件,Open_tables可以查看实时情况
thread_cache_size:最大缓存线程数量,查看Threads_connected、Threads_cached、Slow_launch_threads
read_buffer_size:查询时一次性配置配置的大小的缓存
read_rnd_buffer_size:最大的查询缓存
sort_buffer_size:当查询需要排序时,一次性分配这个大小
innodb_buffer_pool:不仅缓存索引,他还缓存行的数据、自适应哈希索引、插入缓冲、锁等等,innodb严重依赖缓冲池,所以这个必须大,innodb最重要的配置
key_buffer_size:myisam最重要的配置,不是越大越好,剩余内存的25%~50%,用于存放myisam索引的内存、mysql某些系统表采用的MyISAM引擎、group by默认临时表采用MyISAM,另外Myisam的数据文件是使用操作系统的缓存;使用率等于Key_blocks_used * key_cache_block_size * 100 / key_buffer_size
innodb_stats_on_metadata:关闭可以避免耗时的表统计信息刷新
innodb_file_per_table:多个表单独做fsync()操作,不能合并到一个IO操作,为每个表使用一个文件,表名.ibd
innodb_open_files:设置的足够大让mysql保持所有的.ibd文件同时打开
缓存重要性排列
InnodbDB缓冲池
Innodb日志缓存和Myisam数据的操作系统缓存
Myisam键缓存
查询缓存
无法手工分配的缓存
IO行为配置
事务日志把数据文件的随机IO转换几乎顺序的日志文件IO和数据文件IO,并且缓和查询高峰的IO压力
innodb_log_file_size和innodb_log_files_in_group高性能的mysql需要至少几百M甚至上G,默认只有10M
innodb_log_buffer_size:日志缓冲大小,可以明显的减少IO,不要设置的太大,1M~8M
inbodb_flush_log_at_trx_commit:当不担心数据丢失时可以设置为0和2,做多丢失1秒的数据,默认1表示每提交事务都要刷新到磁盘;高性能的事务需要把inbodb_flush_log_at_trx_commit设置为1,并且放到一个有电池保护的写缓冲RAID卷中
innodb_flush_method:刷新日志和数据文件的方式
unix系统默认fdatasync,但是真实用的fsync()
O_DIRECT:禁用双缓冲
O_DSYNC:日志写同步,也就是写到磁盘才返回,不影响数据文件
innodb_data_home_dir:表空间存在的目录,表空间是innodb用多个文件虚拟的文件系统
innodb_data_file_path=/disk1/ibddata1:1G;/disk2/ibddata2:1G:autoextend:配置哪些文件组成表空间
innodb_doublewrite=0:禁用双写缓冲:写的数据会先写到缓冲,保证写入的数据没有损坏,才写入到数据区
sync_binlog=1:0代表有操作系统管理什么时候把二进制日志文件刷新到磁盘,大于0表示间隔多少次事务刷新到磁盘,用于复制用,这个写刷新比innodb日志文件的写刷新对性能的损害大得多
delay_key_write=[OFF|ON|ALL]:当写数据时,延迟索引的写入,先lock table,然后unlock tables时才写到磁盘
myisam_recover=[default|backup|force|quick]:修复策略,一般quick比较好,对于小表适合开启这个配置,大表还是用check table和repair table比较好
myisam_use_map:直接通过操作系统的页面缓存访问.MYD文件
并发配置
innodb_thread_concurrency:限制一次性有多少线程进入内核,0表示不限制,理论上=cpu*磁盘*2比较好,有时并发限制本身就成了并发的瓶颈,所有有时需要关闭有时却需要打开
innodb_thread_sleep_delay:当达到并发数,则新来的休眠x微妙,如果依然不行就到线程队列由操作系统调度
innodb_concurrency_ticketes:
innodb_commit_concurrency:多时并发提交的最大数
courrency_insert:myisam的配置,0不允许并发插入;1默认值,只要表中没有空洞就并发插入;2有并发则插到末尾,否则插到空洞;myisam删除不会真是删除,只是做标记
low_priority_updates:让myisam的查询有更好的并发性,有限执行查询
tempdir:临时文件目录可以用tmpfs内存文件系统,加快文件排序
排序字段总大小超过max_length_for_sort_data或查询字段中包括(就算没有在order by也一样)blob和text就会采用two-pass算法,否则用single-pass算法
max_sort_length:指定blob和text参与排序的前缀长度
tmp_table_size和max_heap_table_size:指定memory引擎能使用的最大内存,如果大于则会转换为磁盘myisam,最好设置为一样大,查看状态Created_tmp_disk_tables和Created_tmp_tables查看临时数量
max_connections:最大连接数,使用Max_used_connections的值
expire_logs_days:二进制日志过期天数
max_allowed_packet:mysql允许接收和发送最大的包大小
read_only:在备库很推荐配置上这个,不允许应用修改数据,值接收日志修改
skip_slave_start
slave_net_timeout
sync_master_info、sync_relay_log、sync_relay_log_info
复制
复制不仅是有利于构建高性能应用,也是高可用性、可扩展性、灾难恢复、备份归档、分流到开发测试、数据库升级以及数据仓库的工作的基础。
备库也可能是另外一个服务器的主库
mysql支持基于行、基于语句两中复制方式
复制对主库开销很小,只用记录二进制日志
对于小查询,复制的延迟一般小于0.3毫秒,也就是0.0003秒
原理详解
基本原理:通过重放主库的二进制日志实现。第一步、主库按事务提交顺序而非语句执行顺序记录日志,记录日志后通知备库;第二步、备库把二进制日志复制到本地的中继日志,启动一个IO线程、一个二进制转存线程,如果追赶上主库则睡眠,等待主库通知;第三步、启动SQL线程执行读取事件。
基于语句的复制:实现简单,可以允许表结构不一样只要类型兼容就行,但是会造成入获取当前时间、当前用户等信息错误,存储引擎和触发器也会造成主备不一致;但是当sql简单但是影响的结果集大会比较高效
基于行的复制:记录数据变更写到日志文件,最大的有点是不会造成主备数据不一致,当做一些汇总操作会比较高效;但无法处理诸如备库修改表schema的情况
可以在两种模式之间动态切换,默认是基于语句的
配置
server-id:指定服务器id,避免主主复制的循环
log-bin=mysql-bin 记录二进制日志
log-bin-index
relay-log=/var/lib/mysql/mysql-relay-bin 备库指定中继日志的位置和命名
log-slave-updates=1 备库重放日志也写到自己的日志中,成为其他备库的主库,默认是打开的
expire-logs-days:过期日志保存天数
sync-binlog:提交事务就记录日志,但是myisam还是可能丢失数据
innodb-flush-log-at-trx-commit=1:这样可以保证innodb不丢数据
命令
grant replication slave, replication client on *.* to repl@'%' identified by '111111';
show master status;
change master to master_host='192.168.142.129',master_user='repl',master_password='111111',
master_log_file='mysql-bin.000002',master_log_pos=154;
show slave status; //Seconds_behind_master显示落后主库多少秒
start slave;
stop slave;
reset slave;
set binlog_format=‘ROW | STATEMENT’ 设置复制模式
show master logs;
purge master logs;
show binlog events;
flush logs;
复制过滤
经常可能发生问题,最好保持默认
复制拓扑
一主多备:很有用
双主动主主复制:太难控制,不推荐
主动被动的主主复制:方便切换主备关系,高可用首选,方便执行维护、优化表、升级
环型:很脆弱,不推荐
主库、分发库、备库:让分发库单独提取binlog,减轻主库的压力,分发库使用blockhole引擎,设置分发库storage_engine=blackhole,但只能影响没指定引擎的create table,另外innodb可以配置为禁用,但是无法禁用myisam和memory
选择性复制:每个备库是复制一部分数据,既减轻主库的压力,也让备库专业化承担读的压力,备库读不到就到主库上找
改变主库
一般情况
- 停止老主库写入(flush tables with read lock或者set gloabl read_only=on(对root无效))
- 让备库追上老主库(可选)(执行完中继日志,stop slave)
- 将一台备库设置为新主库(开启binlog)
- 将备库指向新主库,然后开启新主库的写入(show master status;change master to;reset slave;)
意外情况
- 执行show slave status,选择Master_Log_File/Read_Master_Log_Pos的值最新的那个成为主库
- 如果mysqlbinlog工具把备库的最后一个事件在新主库上找到位置坐标,然后change master to
- 如果老主库的磁盘没损坏,依然可以用mysqlbinlog工具找到丢失的事件
主主复制
- 停止主动服务器的写入(set global read_only=1再配置在文件里面,或者flush tables with read lock)
- 主动服务器上show master status得到日志坐标,在被动服务器上执行select master_pos_with(),改语句将阻塞住被动服务器,直到跟上主动服务器;
- 被动服务器执行set global read_only=0,切换为主动
复制常见问题及解决方案
#表示跳过一步错误,后面的数字可变
stop slave;
set global sql_slave_skip_counter =1;
start slave;
怎么扩展mysql
数据分片
最好是一个分片一个数据库,并且库名表名都带上分片号
固定分配:比如hash、取模,简单可以直接硬编码,但是修改分配策略会导致大量数据跨分片迁移
动态分配:在行上加分片id,获取用一个目录表存储映射关系,方便改变策略,而且可以让数据分组从而让数据具有亲和性,偏向性
聚合表,定时汇总
全局唯一ID生成策略
mysql的auto_increment_increment(增量值)和auto_increment_offset(起始值)
redis的incre函数
分批分配数字,用完后再申请
分片框架
hibernate shards
hiveDB
不需要的数据归档清理
分表
分区
基于时间分区
负载均衡
算法
随机
轮询
最少连接数
最快响应时间
哈希:ip哈希有会话粘连性
权重
读写分离
需要及时数据的读任然在主库上读;
基于用户分离,要看到自己最新,不用看到别人最新的;
大多数读写分离解决方案都需要监控复制延迟来解决读查询的分配
修改DNS名,如果备库是最新的,DNS名指向备库,否则指向主库(修改/etc/hosts更有效)
转移IP,很有效pacemaker,或者lvs、wackamole
haproxy,非常成熟,推荐使用
mysql-proxy不成熟,生产环境谨慎使用
mycat