MySQL记录概要
时间函数
- curdate() : yyyy-MM-dd
- curtime() : HH:mm:ss
- now() : yyyy-MM-dd HH:mm:ss
- from_unixtime() : 返回时间戳的日期值
- unix_timestamp(date) : 时间戳
- date_format(date,fmt) : fmt格式化日期
- fmt: %Y-%m-%d %H:%i:%s
- date_add(date,interval expr type):当前日期加上一定时间间隔
- expr type: HOUR(hh)、MINUTE(mm)、SECOND(ss)、YEAR(YY)、MONTH(MM)、DAY(DD)、YEAR_MONTH(YY-MM)、DAY_HOUR(DD hh)、DAY_MINUTE(DD hh:mm)、DAY_SECOND(DD hh:mm:ss)、HOUR_MINUTE(hh:mm)、HOUR_SECOND(hh:ss)、MINUTE_SECOND(mm:ss)
- datediff(startDate,endDate):返回两个日期之间的天数
- 其余日期
- week、year、hour、minutes、monthname
流程函数
- IF(value,true,false)
- IFNULL(value,replaceValue)
- CASE [expr] WHEN [value] THEN [result] ELSE [defalut] END
字符串函数
- CANCAT(str1,str2,…strn) 连接字符串
- INSERT(str,x,y,instr) 字符串str在(x,y)位置替换instr
- LOWER(str) 小写
- UPPER(str) 大写
- LEFT(str,x) 最左边的x个字符
- RIGHT(str,x) 最右边的x个字符
- LTRIM(str)/RTRIM(str) 去掉左右空格
- REPLACE(str,a,b) b替换str中出现的a
- SUBSTRING(str,x,y) 返回(x,y)长度的字符串
数值函数
- ABS(x) 返回x的绝对值
- CEIL(x) 返回大于x的最大整数值
- FLOOR(x) 返回小于x的最大整数值
- MOD(x,y) x/y的模
- RAND() 0~1内的随机值
- ROUND(x,y) 四舍五入
- TRUNCATE(x,y) 截断小数位结果
其他函数
- DATABASE() 数据库
- VERSION() 版本
- USER() 当前用户
- PASSWORD() 加密方式
- MD5() MD5字符串
- INET_ATON(IP) 返回IP的数字表示
- INET_NTOA(num) 返回数字代表的IP地址
MYSQL工具
- MySQL Administrator 管理工具
- MySQLdump 备份工具
- Catalogs 控制台提供的管理表、索引、视图和过程的工具
- MySQL Query Brower 可视化界面的mysql管理工具
- phpMyAdmin 通过web控制操作数据的工具
- mysqlbinlog 查看binlog
备份
- InnoDB Online Backup 保障InnoDB数据一致性
- Lock all tables 确保MyISAM数据一致性
- Online with binlog pos 实现InnoDB Backup功能,科记录Binlog位置,便于恢复
- Normal backup 只有备份每个表时才锁定单表,表间一致性无法保障
- Complete backup 数据库全备份
MySQL存储引擎
查看Mysql支持的存储引擎
show ENGINE \G
设置表的存储引擎
create table table_name() ENGINE=InnoDB CHARSET=utf-8
修改表的存储引擎
alter table_name ENGINE MyISAM
如何选择引擎
- MyISAM:默认的MySQL引擎,对数据一致性要求、完整性和并发性不是很高的插入/查询操作,很少更新删除操作
- InnoDB:支持事务、外键,在并发条件保证数据一致性。对数据准确性较为精确
- MEMORY:数据存储在内存中,访问速度快。适用于快速定位记录。但是对表大小有限制,确保数据可以恢复,用于更新不太频繁的小表
- MERGE:一系列等同的MyISAM表以逻辑方式组合,作为对象引用它们。优点是突破对单个MyISAM表大小限制
索引
创建索引语法
create [UNIQUE|FULLTEXT|SPATIAL] INDEX idx_name
[USING index_type]
ON table_name(idx_col_name)
设置索引原则
- 搜索的索引列。最适合索引的列是出现在where子句中的列,或连接子句中指定的列
- 使用唯一索引。考虑某列中值分布,索引列基数越大,索引效果越好
- 使用短索引。对字符串进行索引,应该指定一个前缀长度。
- 最左前缀。在创建一个n列索引,实际上是创建mysql可利用的n个索引,多列索引可起几个索引的作用,可利用索引最左边的列集匹配行
- 不要过度索引。每个额外的索引都要占据额外的磁盘空间,降低写操作性能。在修改表内容时,索引必须进行更新,花的时间更长。
- 对于InnoDB的表,默认会按照一定顺序排好,若定义了主键,按照主键顺序保存,没有主键,但是有唯一索引,按照唯一索引顺序保存。如果既没有主键,有没有唯一索引,那么表会自动生成一个内部列,按照这个列的顺序保存。主键尽可能选择较短的数据类型,有效的减少索引的磁盘占用,提高索引的缓存效果
BTree索引和Hash索引
MEMORY存储引擎时可以使用
HASH重要特征
- 只用于=或<=>操作符之间的比较
- 优化器不能使用hash索引加速orderby
- mysql不能确定在两个值之间大约有多少行。如果将MyISAM改为HASH索引的MEMORY表,将会影响查询效率
- 只能使用整个关键字搜索一行
BTree特征
- 对于<、>、!=、<>、between或者like ‘pattern’时。都可以使用
适用于Hash和BTree索引
select * from table_name where key_col = 1 or key_col in (1,2,3);
只适用于btree索引
select * from table_name where key_col > 1 and key_col < 10;
select * from table_name where key_col like 'ab%' or key_col between 'a' and 'b';
HASH索引实际是全表扫描的
分布式事务
语法
启动XA事务
XA {START|BEGIN} xid [JOIN|RESUME]
XA START xid 用于启动一个带给定xid值的XA事务。每个XA事务必须有一个唯一的xid值
xid是一个XA事务标识符,用来标识一个分布式事务。xid值由客户端提供,MySQL服务器生成
xid包含三个部分
xid: gtrid [, bqual [, formatID ]]
- gtrid:分布式事务标识符,相同的分布式事务应该使用相同的gtrid,可以明确xa事务属于哪个分布式
- bqual:分支限定符,默认值为空串。对于一个分布式事务中的每个分支事务必须是唯一的
- formatID:数字。用于标识由gtrid和bqual值使用的格式,默认为1
进入PREPARE状态(两阶段提交的第一阶段)
XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
提交/回滚具体的分支事务 (两阶段提交的第二阶段)
XA COMIT xid [ONE PHASE]
XA ROLLBACK xid
返回当前数据库处于PREPARE状态的分支事务的详细信息
XA RECOVER
分布式关键在于如何确保分布式事务的完整性,以及在某个分支出现问题时的故障解决。
XA的相关命令就是提供给应用如何在多个独立的数据库之间进行分布式事务的管理,包括启动一个分支事务、使事务进入准备阶段以及事务的实际提交回滚操作等
举例:在DB1中插入一条记录,同时在DB2更新一条记录,两个操作作为同一事务提交或回滚
在数据库DB1中启动一个分布式事务和分支事务,xid的gtrid为”test”,bqual为”db1”
mysql> xa start 'test','db1'; mysql> insert into t_products values(5,2,'测试商品',50,'分布式测试'); mysql> xa end 'test','db1'; mysql> xa prepare 'test','db1'; mysql> xa recover; *************************** 1. row *************************** formatID: 1 gtrid_length: 4 bqual_length: 3 data: testdb1
在数据库DB2中启动一个分布式事务和分支事务,xid的gtrid为”test”,bqual为”db2”
mysql> xa start 'test','db2'; mysql> insert into producttype values(MD5('77'),now(),now(),'分布式测试'); mysql> xa end 'test','db2'; mysql> xa prepare 'test','db2'; mysql> xa recover; *************************** 1. row *************************** formatID: 1 gtrid_length: 4 bqual_length: 3 data: testdb2
提交分支事务
mysql> xa commit 'test','db1'; mysql> xa commit 'test','db2';
注意:两个事务都达到准备提交阶段后,一旦开始进行提交操作,需要确保全部分支提交成功
存在的问题
1.如果分支事务达到prepare状态,数据库异常重新启动,服务器重新启动后,可以继续对分支事务进行提交或者回滚操作,但是提交的事务没有写binlog,存在一定隐患。可能导致binlog恢复丢失部分数据。
2.如果存在复制的数据库,则有可能导致主从数据不一致。因为复制和灾难恢复都依赖于binlog
SQL安全
SQL注入
SQL注入攻击者可以利用它读取,修改或者删除数据库内的数据。一般的防火墙无法进行Sql注入拦截
“/*”或者”#”可以将后面的语句注释掉
应对措施
PrepareStatement + Bind-variable
对于JSP、Java开发的应用来防止SQL注入
String sql = "select userName from userName = ? and userPassword = ?";
PrepareStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,name);
pstmt.setString(2,pwd);
ResultSet rs = pstmt.executeQuery();
SQL Mode
SQL Mode定义MySql应该支持的SQL语法、数据校验等
SQL Mode 常用来解决
- 通过设置SQL Mode,可以完成不同严格程度的数据校验,保障数据准确性
- 通过设置SQL Mode为ANSI模式,保证大多数SQL符合标准SQL语法(确保进行不同数据库迁移时,不需要对业务SQL进行较大的修改)
不同数据库迁移之前,通过SQL Mode可以使MySQL上的数据更方便迁移到目标数据库中
mysql> select @@sql_mode; +----------------------------------------------------------------+ | @@sql_mode | +----------------------------------------------------------------+ | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +----------------------------------------------------------------+
set [session/global] sql_mode = ‘STRICT_TRANS_TABLES’ : 设置严格模式。当记录插入失败,直接失败。返回ERROR
RAND提取随机行
-- 按照数据随机排序,并选择前10
select * from table_name order by rand() limit 10;
按照随机顺序检索数据行
GROUP BY 的 WITH ROLLUP 做统计
可以检索出更多的分组聚合信息。with rollup反映的是一种OLAP思想
注意:
1.当使用ROLLUP时,不能同时使用ORDER BY
2.LIMIT用在WITH ROLLUP的后面
SQL 优化
通过show status了解各种SQL执行频率
show status like 'Com_%';
- Com_select: 查询操作次数
- Com_insert: 新增操作次数
- Com_delete: 删除操作次数
- Com_update: 修改操作次数
查看事务提交回滚情况
- Com_commit
- Com_rollback
show status like 'Innodb_%';
- Innodb_rows_read: select返回的行数
- Innodb_rows_inserted: 执行insert插入的行数
- Innodb_rows_updated: 执行update更新行数
- Innodb_rows_deleted: 执行delete删除行数
对于回滚操作非常频繁的数据库,可能以为编写存在问题
- Connections 试图连接MySql服务器的次数
- Uptime:服务器工作时间
- Slow_queries: 慢查询次数
定位执行效率较低的SQL语句
- 通过慢查询日志定位
- 用log-slow-queries[=file_name]启动时,mysqlId写一个包含所有执行时间超过long_query_time秒的SQL语句的日志文件
- 慢查询日志在查询结束后记录,只能反应效率不能定位问题
- 使用show processlist查看MySQL进行中的线程(包括线程状态、是否锁表等)、实时查看SQL执行情况
通过EXPLAIN/DESC分析低效SQL执行计划
- select_type
- SIMPLE:单表
- PRIMARY:外层查询(主查询)
- UNION:union中第二个或者后面的查询语句
- SUBQUERY:子查询中的第一个select
- table: 输出结果集的表
- type:表的连接类型
- 性能由好到差:system>const>eq_ref>ref_or_null>index_subquery>unique_subquery>index_subquery>range>index>all
- 表中仅有一行(常量表)>单表中最多一个匹配行pk和uq_idx>多表连接中使用pk和uq_idx>使用普通索引>与ref类似包含对NULL的查询>索引合并优化>一个查询主键字段的子查询>非唯一索引字段的子查询>单表中范围查询>对于前面的每一行通过查询索引得到的数据>全表查询
- possible_key:可能使用的索引
- key:实际使用的索引
- key_len:索引字段的长度
- rows:扫描行数量
extra:执行情况的说明和描述
id: 1 select_type: SIMPLE table: region partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 3524 filtered: 100.00 Extra: NULL
索引存储分类
MySQL支持的存储类型
- Hash(MEMORY和HEAP两者都可以使用)
- BTree(MyISAM和InnoDB)
- 不支持函数索引(根据文本字符长度进行索引)
使用索引
索引用于快速找出在某个列中有一特定值的行。
**使用索引的主要条件是查询条件中需要使用索引关键字,如果是多列索引,需要满足最左前缀原则,才可使用,否则不能使用索引
索引有效/失效
- 假设有一个复合索引idx_test(col_1,col_2)。where条件只跟col_1都能匹配到索引,如果where后面只跟col_2则不能匹配
- 对于like查询,%如果在第一个字符,索引则失效
- 对于大文本搜索,使用全文索引,而不是使用like ‘%..%’
- 如果列名是索引,使用col_name is null条件,索引有效
- 索引比全表扫描满,则不使用索引。
- 如果使用MEMORY/HEAP表并且where条件不适用=进行索引列,则不会使用
- 用or分隔开的条件,如果or前的条件中列有索引,而后面没有索引,则涉及的索引失效
- 列类型为字符串,在where条件中的字符常量值通过引号。否则索引失效
查看索引使用情况
mysql> show status like 'Handler_read%'
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 0 |
| Handler_read_key | 0 |
| Handler_read_last | 0 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 0 |
+-----------------------+-------+
- Handler_read_key : 代表行被索引值读次数。值越高说明索引使用频率越多
- Handler_read_rnd_next: 数据文件读取下一行请求数。值越高查询越低下,应该建立索引补救(通常代表索引不正确或没有利用索引)
优化
定期分析表和检查表
ANALYZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE table_name [,table_name_2,...]
定期优化表
OPTIMizE [LOCAL|NO_WRITE_TO_BINLOG] TABLE table_name [,table_name_2,...]
注意:ANALYZE、CHECK、OPTIMIZE执行期间会对表进行锁定
常用SQL优化
1.大批量导入数据
当用load命令导入数据时,适当设置提高导入速度
对于MyISAM引擎表,设置如下
alter table table_name DISABLE KEYS; loading the data alter table table_name ENABLE KEYS;
DISABLE/ENABLE:打开/关闭MyISAM非唯一索引的更新
load data infile 'path' into table table_name;
对于InnoDB引擎表,设置如下
set unique_checks = 0 --导入数据前,关闭唯一性校验 set unique_checks = 1 --导入结束后,恢复唯一性校验
如果使用自动提交方式
set autocommit = 0 --关闭自动提交 set autocommit = 1 --打开自动提交
2.优化insert
同一用户插入很多行,尽量使用多个值表的insert语句。缩减客户端与数据库之间的连接/关闭消耗
insert into table_name values(),(),()...
不同用户插入很多行,使用insert delayed得到更高的速度
- delayed让insert语句马上执行,其实是放在内存都列中,并没有写入磁盘。比每条语句插入快。LOW_PRIORITY相反,在所有其他用户对表的读写完后才进行插入
- 索引文件和数据文件分别放在不同的磁盘
- 如果进行批量插入,增加bulk_insert_buffer_size提高速度,只对MyISAM使用
- 当从一个文本文件加载一个表时,使用load data infile。比insert快
3.优化GROUP BY
- order by null : 禁止排序。避免排序结果消耗
4.优化ORDER BY
- 在某些情况,使用一个索引满足order by而不需要额外排序。where和order by使用的是相同索引。
- 混用DESC、ASC索引不生效
- 查询行的关键字与ORDER BY中不一致
5.优化嵌套查询(子查询)
- 通过子查询创建一个单列的查询结果,然后把这个结果作为过滤条件在另外一个条件中。使用子查询避免事务或者表锁死。某些情况下子查询被更有效率的JOIN替代
6.优化OR条件
OR之间的每个条件列都必须用到索引
show index from table_name --查看某表上索引
7.使用SQL提示
- SQL中加入一些人为提示达到优化操作的目的
8.use index
查询语句表名后面,添加use index提供希望mysql参考的索引列表
select * from table_name use index (idx_test_id) where ...
9,ignore index
- 忽略一个或者多个索引
10.force index
- 强制使用一个特定索引
11.字符串索引
- 只是用字符串的最左边n个字符建立索引,推荐n<=10;比如index left(column,8),但是需要知道前缀索引不能在order by中使用,也不能用在索引覆盖上。
- 对字符串使用hash方法将字符串转化为整数,column_key=hashToInt(column),对column_key建立索引
优化数据库对象
1.优化表的数据类型
PROCEDURE ANALYSE() 对当前表进行分析
select * from table_name PROCEDURE ANALYSE()
2.通过拆分提高表的访问效率
- 垂直拆分:eg.OrderMain和OrderDetail
- 优点:数据行变小,数据页存放更多数据,查询时减少I/O次数
- 缺点:管理冗余列。查询时需要JOIN操作
- 水平拆分:将一列或多列数据值放到两个独立表中
- 表很大,分割后降低在查询时需要读的数据和索引页数。降低索引层数
- 数据独立性
- 数据存放在多个介质中
- 缺点:增加复杂度
3.逆规范化
适当考虑表的冗余字段,不需要在做关联查询,而让查询有更好的性能。
逆规范的好处是降低连接操作的需求和索引数目。甚至可能减少表数目。但是可能影响数据完整性。
- 增加冗余列
- 增加派生列
- 重新组表
- 分割表
4.使用中间表提高统计查询速度
锁问题
MySQL在不同存储引擎下支持不同的锁机制
- 表级锁:MyISAM和MEMORY
- 页面锁:BOBO
- 行级锁:InnoDB(也支持表级锁)
3种锁的特性
- 表级锁:开销小,加锁快。不会出现死锁;锁定粒度大,发生锁冲突频率最高,并发度最低
- 行级锁:开销大,加锁慢,会出现死锁;锁定粒度小;发生锁冲突概率最低,并发度最高
- 页面锁:开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁行锁之间。并发程度一般
MyISAM表锁
查询表争用情况
show status like 'table%';
- Table_locks_waited:值越高,则说明存在严重的表级锁争用
- MyISAM读锁不会其他用户对同一个表的请求,但会阻塞同一个表的写请求。一个线程获得表的写锁后。只有持有锁的线程对表进行更新操作。其他的读线程等待。直到被释放。
显式加锁
Lock tables table_name_1 read local, table_name_2 read local
... --sql语句
Unlock tables
获取锁
lock table table_name as alias read;
并发插入
MyISAM的读写串行,在一定条件下,MyISAM表也支持查询和插入操作的并发进行
concurrent_insert --控制其并发插入的行为
- concurrent_insert=0 不允许并发插入
- concurrent_insert=1 MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录(默认设置)
- concurrent_insert=2 都允许在表尾并发插入记录
MyISAM锁调度
写进程获取锁,读请求先到锁等待队列,写请求厚道,写锁会插入到读锁请求之前。(由于一特性,myISAM不适合大量更新和查询操作。大量更新操作会造成查询操作很难获得锁,从而一直阻塞。)
- 指定启动参数low-priority-updates:默认给予都请求优先
- set low_priority_updates = 1 使该连接发出的更新请求优先级降低
- 指定insert、update、delete的low_priority属性,降低该语句优先级
InnoDB行锁
MyISAM与InnoDB最大不同:支持事务、采用行级锁。
事务ACID属性
- 原子性 (要么全部执行,要么全部失败)
- 一致性 (事务开始和完成,数据必须保持一致状态,保持数据完整性)
- 隔离性 (保证事务不受外部并发操作影响)
- 持久性:事务一旦提交。对于数据修改是永久的)
并发事务处理带来的问题
- 更新丢失:2个或多个事务更新同一行,但是每个事务都不知道彼此的存在,会发生丢失更新问题
- 脏读:一个事务正在对一条记录进行修改,但是并未提交。数据处于不一致状态;另一个事务读取同一条记录,如果不加控制。就会读取到脏数据,产生未提交数据依赖关系
- 不可重复读:一个事务在读取数据后某个时间按,再次读取以前读果的数据,发生了改变(或者已经删除)
- 幻读:一个事务按相同的查询条件重新读取以前检索过的额数据,发现其他事务插入了满足其查询条件的新数据
事务隔离级别
- 读取数据前,对其加锁,阻止其他事务对其数据进行修改
- 不加任何锁,通过一定机制生成一个数据请求时间点一致性数据快照,并用这个快照提供一定级别的一致性读取(这种叫做数据库多版本并发控制,称为MVCC)
事务隔离越严格,并发副作用越小,旦代价越大;事务隔离实质就是使事务在一定程度上”串行化”进行
- 未提交读
- 已提交读
- 可重复读
- 可序列化
获取InnoDB锁争用情况
show status like 'innodb_row_lock%'
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 0 |
| Innodb_row_lock_time_avg | 0 |
| Innodb_row_lock_time_max | 0 |
| Innodb_row_lock_waits | 0 |
+-------------------------------+-------+
如果锁争用的情况比较严重。还可以设置Innodb Monitors进一步观察锁冲突、数据行。具体分析原因
InnoDB行锁模式以及加锁方法
- 共享锁S:允许一个事务读取一行,阻止其他事务获得相同数据集的排它锁
- 排它锁X:允许获得排它锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁
- 意向共享锁IS:事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须取得该表的IS锁
意向排它锁IX:事务打算给数据行加排它锁,事务在给定一个数据行加排它锁前必须取得该表的IX锁
– 共享锁
select * from table_name where … LOCK IN SHARE MODE
– 排它锁
select * from table_name where … FOR UPDATELOCK IN SHARE MODE:从数据依存关系确认某行记录是否存在,并确保没有人对这个记录进行update或者insert操作。但如果当前事务需要对该记录进行更新操作,可能会造成死锁‘
- FOR UPDATE : 对于锁定行需要进行更新的记录,使用排他锁
InnoDB行锁实现方式
- InnoDB通过给索引上的索引项加锁实现。只有通过索引条件检索数据,InnoDB才使用行级锁,否则,使用表锁。
- 当表游多个索引,不同事务使用不同索引锁定不同的行
- 分析锁冲突,需要检查sql执行计划(explain)
间隙锁(Next-Key)
通过范围条件而不是相等条件检索数据,并请求共享排它锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录,叫做间隙。InnoDB对这个间隙加锁
select * from table_name from col_1 > 100 for update
使用间隙的目的
1.防止幻读,满足相关隔离级别
2.满足恢复和复制
select @@tx_isolation;
复制本质:在SlaveMysql不断做基于binlog的复制
恢复机制:在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录(不允许幻读)。无论在ReadCommited或者RepeatableRead隔离级别下,InnoDB都要使用间隙锁
优化MySQL
show variables --服务器静态参数值
show status --动态运行状态
show warnings
相关参数
- key_buffer_size
- table_cache
- innodb_buffer_pool_size
- innodb_flush_at_trx_commit
- innodb_additional_mem_pool_size
- innodb_lock_wait_timeout
- innodb_support_xa
- innodb_log_buffer_size
- innodb_log_file_size
磁盘阵列(RAID)
RAID级别
RAID 0:
- 特性:条带化。按一定的条带大小将数据依次分布到各个盘中,无数据冗余。
- 优点:并发读写快。无额外磁盘空间开销
- 缺点:数据无冗余保护,可靠性差
RAID 1:
- 特性:磁盘镜像,两个磁盘一组,所有数据同时写入两个磁盘。读取任一磁盘即可
- 优点:有冗余保护。只要不出现两块磁盘同时损坏。提高并发读写性能
- 缺点:容量一定的情况,磁盘空间占用大
RAID 10
- 特性:RAID 0 和 RAID 10 结合。先对磁盘做镜像,在条带化
- 优点:可靠性高。并发读写性能优良
- 缺点:容量一定的情况,磁盘空间占用大
RAID 4
- 特性:如RAID 0一样对磁盘组条带化,不同的时:需要额外增加一个磁盘。写各Stripe(条带)的校验纠错数据
- 优点:RAID中一个磁盘损坏可以通过校验纠错数据计算,保障容错信息;读取数据快
- 缺点:每个Stripe写校验纠错块,性能有影响。所有纠错数据在同一磁盘,风险大,容易形成性能瓶颈。出现坏盘,性能下降
RAID 5
- 特性:对RAID 4的改进,将每个条带的校验纠错数据分布写到各个磁盘,而不是写入特定磁盘
- 优点:性能和数据保护能力强于RAID 4
- 缺点:写性能不及RAID 0、RAID 1和RAID 10;容错能力不及RAID 1
如何选择RAID级别
- 数据读写很频繁,可靠性较高,最好选择RAID 10
- 数据读频繁,写较少,对可靠性有一定要求,可选RAID 5
- 数据读写都很频繁,可靠性要求不高,可选RAID 0
使用Symbolic Links分布I/O
禁止操作系统更新文件的atime属性
应用优化
1.使用连接池
2.减少对MySQL的访问
2.1. 避免对同一数据进行重复检索
2.2. 使用查询缓存
show variables like '%query_cache%'
2.3. 增加Cache层
3.负载均衡
2.2. 利用MySQL复制分流查询操作
- MySQL主从复制有效的分流更新操作和查询操作
- 具体实现:主服务器承担更新操作,多台服务器承担查询操作;主从之间通过复制进行数据同步;多台从服务器确保可用性;另一方面可以通过不同索引满足不同需要
- 缺点:当主数据库更新频繁或者网络出现问题时,主从之间的数据存在比较大的延迟更新造成查询结果和主数据库上有所差异
2.3. 采用分布式数据库结构
- 注:如果使用分布式架构数据库,必须采用InnoDBZ
4.其他优化
- 对于没有删除行操作的MyISAM表,插入和查询可以并行进行,没有删除操作的表查询期间不会阻塞插入操作。对于需要执行删除操作的表,尽量在空闲时间执行批量删除,并在删除操作后进行optimize。避免将来更新阻塞其他操作
- 充分利用默认值
- 表尽量不适用自增长字段