mysql一些使用点的探讨

Posted willwillie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql一些使用点的探讨相关的知识,希望对你有一定的参考价值。

注:mysql是一个支持插件式存储引擎的数据库系统,下文探讨的针对的存储引擎都是innodb的。

1.大数据的删除,比如一亿行数据的表中删除或者更新一千万行数据?

mysql提供了几种数据删除的方法,有truncate,drop和delete。

1.truncate和不带where子句的delete、以及drop都会删除表内的数据。
2.drop、truncate都是DDL语句(数据定义语言),执行后会自动提交。

首先来看看truncate命令的用法是怎样的。
它用于删除整个数据表,truncate命令和drop命令的用法很相似,也可以使用 DROP TABLE 命令来删除整个数据表,不过 DROP TABLE 命令不但会删除表中所有数据,还会将整个表结构从数据库中移除。如果想要重新向表中存储数据的话,必须重建该数据表。

那么什么是DDL语句是什么呢?

DDL也就是data definition language的缩写,主要的DDL命令有CREATE、ALTER、DROP等,主要用在定义表或者改变表的结构。
而SQL的DML是指data manipulation language的缩写,是select、update、insert、delete这类的对数据库里的数据进行操作的语言。

而delete 语句是数据库操作语言(dml),这个操作会放到 rollback segement 中,事务提交之后才生效,具体有多大的开销会在下面进行分析;

个人觉得,大数据的删除还是采用trucate或者drop table比较好。使用delete会造成太大的事务开销。

2.事务的开销和回滚?

上面提到了mysql的rollback,那么需要提及mysql的MVCC是什么,是怎么实现的。
MVCC (Multiversion Concurrency Control),即多版本并发控制技术,不只是单纯的使用行锁来进行数据库的并发控制,取而代之的是把数据库的行锁与行的多个版本结合起来。(也就是说用到了行锁和快照机制)

在Mysql中MVCC是在Innodb存储引擎中得到支持的,Innodb为每行记录都实现了三个隐藏字段:6字节的事务ID(DB_TRX_ID )、7字节的回滚指针(DB_ROLL_PTR)和隐藏的ID。
一些概念如下:
redo log又叫重做日志,每当有操作执行时,将数据真正更改时,先前相关操作写入重做日志。这样当断电,或者一些意外,导致后续任务无法完成时,系统恢复后,可以继续完成这些更改
undo log撤消日志:当一些更改在执行一半时,发生意外,而无法完成,则可以根据撤消日志恢复到更改之前的壮态
rollback segment:回滚段这个概念来自Oracle的事物模型,在Innodb中,undo log被划分为多个段,具体某行的undo log就保存在某个段中,称为回滚段。可以认为undo log和回滚段是同一意思。
锁:Innodb提供了基于行的锁,如果行的数量非常大,则在高并发下锁的数量也可能会比较大。

redo日志写入方式:
1.ib_logfile写入当前事务更新数据,并标上事务准备trx_prepare
2.写入bin-log
3.ib_logfile当前事务提交提交trx_commit
恢复方式:
如果ib_logfile已经写入事务准备,那么在恢复过程中,会依据bin-log中该事务是否存在恢复数据。
假设:
1)结束后异常,因没有写入bin-log,从库不会同步这个事务,主库上,重启时,在恢复日志中这个
事务没有commit,即rollback这个事务.
2)结束后异常,这会bin-log已经写入,从库会同步这个事务。主库依据恢复日志和bin-log,也正常恢复此事务
综上描述:bin-log写入完成,主从会正常完成事务;bin-log没有写入,主从库rollback事务;不会出现主从库不一致问题.
相关参数(全局&静态):
innodb_log_buffer_size
innodb_log_file_size
innodb_log_files_in_group
innodb_log_group_home_dir
innodb_flush_log_at_trx_commit
innodb_log_buffer_size:事务日志缓存区,可设置1M~8M,默认8M,延迟事务日志写入磁盘,
把事务日志缓存区想象形如"漏斗"状,会不停向磁盘记录缓存的日志记录,而何时写入通过参数
innodb_flush_log_at_trx_commit控制,稍后解释,启用大的事务日志缓存,可以将完整运行大事
务日志,暂时存放在事务缓存区中,不必(事务提交前)写入磁盘保存,同时也起到节约磁盘空间占用;
innodb_log_file_size:控制事务日志ib_logfile的大小,范围5MB~4G;所有事务日志ib_logfile0+
ib_logfile1+..累加大小不能超过4G,事务日志大,checkpoint会少,节省磁盘IO,但是大的事务日
志意味着数据库crash时,恢复起来较慢.
引入问题:修改该参数大小,导致ib_logfile文件的大小和之前存在的文件大小不匹配
解决方式:在干净关闭数据库情况下,删除ib_logfile,而后重启数据库,会自行创建该文件;
innodb_log_files_in_group:DB中设置几组事务日志,默认是2;
innodb_log_group_home_dir:事务日志存放目录,不设置,ib_logfile0...存在在数据文件目录下
innodb_flush_log_at_trx_commit:控制事务日志何时写盘和刷盘,安全递增:0,2,1
事务缓存区:log_buffer;
0:每秒一次事务缓存区刷新到文件系统,同时文件系统到磁盘同步,但是事务提交时,不会触发log_buffer到文件系统同步;
2:每次事务提交时,会把事务缓存区日志刷新到文件系统中去,且每秒文件系统到磁盘同步;
1:每次事务提交时刷新到磁盘,最安全;
适用环境:
0:磁盘IO能力有限,安全方便较差,无复制或复制延迟可以接受,如日志性业务,mysql损坏丢失1s事务数据;
2:数据安全性有要求,可以丢失一点事务日志,复制延迟也可以接受,OS损坏时才可能丢失数据;
1:数据安全性要求非常高,且磁盘IO能力足够支持业务,如充值消费,敏感业务;

如果删除非常大的数据,比如3000万行数据(猜想也许是10G的数据),然后mysql引擎在把数据删除的时候旧路的undo log和redo log的量过大,然后还要给每一行数据上锁,系统可能根本就没有那么大的内存了,然后可能会卡在那里,然后这个过程就会很慢,你就可能会选择回滚,然后就会根据undo log记录的内容来回滚,同样这样一个恢复的过程也会很慢。

mysql的隔离级别是怎样的?

隔离级别transaction isolation level用来限制事务直接的交互程度,主要有四种类型:
repeatable read 是InnoDb的默认的isolation level…
这种情况下,同一个read事务中的一致性读请求(相同的读请求)最后读的都是同一个读的快照(第一次读的时候创建的)(当然创建这样一个快照是会带来一些性能上的损失,尤其是当表的大小比较大的时候,这个损失就会比较大),这就意味着当同一个事务中有多个读请求,这些读请求获得的结果是一致的。(通过损失一些性能换来了较好的一致性。)

针对当前读,Repeatable Read (RR)RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

回到说isolation level这个概念,那么什么是isolation level呢?其实isolation level就是一些基于性能,可靠性,一致性和可再生性的一些微调的设置
mysql给使用者提供了四个级别的isolation level,分别是repeatable read ,committed read,uncommitted read,以及serilizable。上面提到了repeatable read,通过使用快照牺牲部分性能来获得了较好的一致性,当然可靠性和可再生性这两个方面还是没得说的。

比如我常常在实际的业务场景张,会用到一些事务:我往某个表中去insert一行数据,这一行对应唯一的id,当我insert完,我能够获取到这个唯一id,但是如果我仍然要在这个事务中把这行数据通过id这个where条件读出来却不可能,因为读请求使用的快照还是insert之前的这个表的内容。

mysql的binlog指的是什么?
binlog日志用于记录所有更新了数据或者已经潜在更新了数据(例如,没有匹配任何行的一个DELETE)的所有语句。语句以“事件”的形式保存,它描述数据更改。因为有了数据更新的binlog,所以可以用于实时备份,与master/slave复制。

redo log和binlog的关系?
这两者是不一样的,前者是innodb记录事务的,后者是mysql本身的功能。首先,binlog会记录所有与MySQL数据库有关的日志记录,包括InnoDB、MyISAM、Heap等其他存储引擎的日志。
而InnoDB存储引擎的重做日志只记录有关该引擎本身的事务日志。

InnoDb的记录锁是什么?gap锁又是什么?
数据库使用锁是为了支持更好的并发,保证数据一致性。InnoDb是一个支持行锁的存储引擎,锁的类型一般包括共享锁和排他锁(这也是操作系统或任何资源为了保证资源共享和竞争的锁机制)。在这种锁机制的情况下,读一行数据的时候所有的读者都可以读,但是写者不能写。但是innodb不是这么多的,为了提供更好的并发,innodb使用了非锁定读,也就是说读的时候不上锁,对于上锁了的数据也可以读;因为读请求不需要等待访问行上的锁释放,直接读取行的一个快照。
innodb的record lock:单个行记录上的锁。
innodb的gap lock:间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。
Next-Key Lock:1+2,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。

section1:
MariaDB [willietest]> create table t(a int,key idx_a(a))engine =innodb;
Query OK, 0 rows affected (0.16 sec)

MariaDB [willietest]> insert into t values(1),(3),(5),(8),(11);
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

MariaDB [willietest]> select * from t;
+------+
| a    |
+------+
|    1 |
|    3 |
|    5 |
|    8 |
|   11 |
+------+
5 rows in set (0.00 sec)

MariaDB [willietest]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [willietest]> select * from t where a = 8 for update;
+------+
| a    |
+------+
|    8 |
+------+

section 2:
MariaDB [williet
est]> Insert into t values(4);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'nsert into t values(4)' at line 1
MariaDB [willietest]> insert into t values(4);
Query OK, 1 row affected (0.00 sec)

MariaDB [willietest]> insert into t values(6);
^CCtrl-C -- query killed. Continuing normally.
ERROR 1317 (70100): Query execution was interrupted
MariaDB [willietest]> insert into t values(7);
^CCtrl-C -- query killed. Continuing normally.
ERROR 1317 (70100): Query execution was interrupted
MariaDB [willietest]> insert into t values(9);
^CCtrl-C -- query killed. Continuing normally.
ERROR 1317 (70100): Query execution was interrupted
MariaDB [willietest]> insert into t values(10);
^CCtrl-C -- query killed. Continuing normally.
ERROR 1317 (70100): Query execution was interrupted
MariaDB [willietest]> insert into t values(12);
Query OK, 1 row affected (0.00 sec)

因为InnoDB对于行的查询都是采用了Next-Key Lock的算法,锁定的不是单个值,而是一个范围(GAP),可见for update上的锁就是ext-Key Lock。一般情况下不要轻易用。

什么情况下会产生gap锁?
上面如果for update的id是主键就只会产生record锁,而不会产生gap锁,但是如果对应的主键不存在也会产生gap锁。innodb默认的参数innodb_locks_unsafe_for_binlog这个值默认为off,如果将其设置为on,则可以关闭gap lock.

为什么为了防止幻读要加上gap锁?
幻读:也就是其他事务中插入的新数据,出现在当前事务里。
如果使用了gap锁,可以一定程度上防止别的事务出现的新数据。

什么是一致性读?
consistent read:一致性读,在T1时刻发出SELECT查询,不管查询时间多久,返回的值均为查询时刻时间点T1的值。
current read:当前读。读取当前的 data block,最新的 data block。

那么committed read呢?
committed read此级别中,其他事务对数据进行的更改只要一提交,就可以在当前事务中读取到。

Serializable
从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。

Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。
目前mysql的默认transaction isolation level是可重复读,那么为什么要将这个可重复读设置为默认的,而不是read committed呢?
这是因为Binlog是MySQL的逻辑操作日志,广泛应用于复制和恢复,如果使用

有大神的博客,对这方面的内容分析的特别好,http://hedengcheng.com/?p=771#_Toc374698307

后面希望可以分析出死锁原因和避免死锁的经验,比如http://www.cnblogs.com/LBSer/p/5183300.html

4.索引和视图?

索引可以看做是目录,如果数据很大,索引也有可能很大的。
建立索引是通过数学意义上的算法来提升速度的。
可以说数据库必须有索引,没有索引则检索过程变成了顺序查找,O(n)的时间复杂度几乎是不能忍受的。

那么innodb的索引是怎样的呢?
。我们非常容易想象出一个只有单关键字组成的表如何使用B+树进行索引,只要将关键字存储到树的节点即可。当数据库一条记录里包含多个字段时,一棵B+树就只能存储主键,如果检索的是非主键字段,则主键索引失去作用,又变成顺序查找了。这时应该在第二个要检索的列上建立第二套索引。 这个索引由独立的B+树来组织。有两种常见的方法可以解决多个B+树访问同一套表数据的问题,一种叫做聚簇索引(clustered index ),一种叫做非聚簇索引(secondary index)。
innodb对于主键使用了聚簇索引,这是一种数据存储方式,表数据是和主键一起存储,主键索引的叶结点存储行数据。对于普通索引secondary index,其叶子节点存储的是主键值。

索引和锁的关系?
比如gap锁和索引就有比较大的关系。

视图?

我们需要理解,数据库并没有存储视图所关联的数据,存储的只是视图的定义也就是相应的SQL SELECT and JOIN。
那么使用数据库视图到底有哪些优势呢:
视图可以简化你的复杂查询:视图的定义是基于一个查询声明,这个查询声明可能关联了很多底层表。我们可以使用视图向数据库的使用者或者外部程序隐藏复杂的底层表关系。
视图可以限制特定用户的数据访问权:有时我们希望隐藏某些表的一些数据对一些特定用户,这时视图可以很好的帮助我们实现这个功能。
视图可以使用可计算的列:我们知道表的列一般都不支持动态计算,但是视图的列是支持的。假设在有一张order_details表,其中包含product_nums和price_each两列,当我们需要查询order总价时我们就需要查询出结果后在代码中进行计算,如果我们使用视图的话可以在视图中添加一列total_price(product_nums*price_each)。这样就可以直接查询出order的总价。
视图可以帮助我们兼容旧的系统:假设我们拥有一个数据中心,这个数据中心被很多的程序在使用。如果有一天我们决定重新设计这个数据中心以适应一些新的业务需求,可能需要删除一些旧的表,并且创建一些新的表,但是我们并不希望这些变动影响到那些老的程序。那么我们可以创建一些视图用来适配那些老的程序。

SQL执行计划 ?
(主键扫描 vs 唯一键扫描 vs 范围扫描 vs 全表扫描)
要避免在select语句中出现全表扫描,也就是explain的type为all的。而索引扫描的type为ref.

5.分区表大小?

分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘
mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件。。

mysql数据库中的数据是以文件的形式存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放表数据的,一个是myi存表索引的。如果一张表的数据量太大的话,那么myd,myi就会变的很大,查找数据就会变的很慢,这个时候我们可以利用mysql的分区功能,在物理上将这一张表对应的三个文件,分割成许多个小块,这样呢,我们查找一条数据时,就不用全部查找了,只要知道这条数据在哪一块,然后在那一块找就行了。如果表的数据太大,可能一个磁盘放不下,这个时候,我们可以把数据分配到不同的磁盘里面去。
分区的二种方式
1,横向分区
什么是横向分区呢?就是横着来分区了,举例来说明一下,假如有100W条数据,分成十份,前10W条数据放到第一个分区,第二个10W条数据放到第二个分区,依此类推。也就是把表分成了十分,根用merge来分表,有点像哦。取出一条数据的时候,这条数据包含了表结构中的所有字段,也就是说横向分区,并没有改变表的结构。
2,纵向分区
什么是纵向分区呢?就是竖来分区了,举例来说明,在设计用户表的时候,开始的时候没有考虑好,而把个人的所有信息都放到了一张表里面去,这样这个表里面就会有比较大的字段,如个人简介,而这些简介呢,也许不会有好多人去看,所以等到有人要看的时候,在去查找,分表的时候,可以把这样的大字段,分开来。
感觉数据库的分区好像是切苹果,到底是横着切呢,还是竖着切,根据个人喜好了,mysql提供的分区属于第一种,横向分区,并且细分成很多种方式。

统一,数据也存在着分表的必要的:
当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。
所以这个分区分多大,看你能接受的程度和业务场景吧,要顶下一个具体的值也不太对。

6.数据的备份

无论用什么存储,都涉及到数据的备份和恢复,mysql就更是如此了。
目前 MySQL 支持的免费备份工具有:mysqldump、mysqlhotcopy,还可以用 SQL 语法进行备份:BACKUP TABLE 或者 SELECT INTO OUTFILE,又或者备份二进制日志(binlog),还可以是直接拷贝数据文件和相关的配置文件。MyISAM 表是保存成文件的形式,因此相对比较容易备份,上面提到的几种方法都可以使用。Innodb 所有的表都保存在同一个数据文件 ibdata1 中(也可能是多个文件,或者是独立的表空间文件),相对来说比较不好备份,免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump。
mysqldump其实有很丰富的语法,不对对于一般情况下的使用却又非常的简单。
mysqldump 备份出来的文件是一个可以直接倒入的 SQL 脚本,有两种方法可以将数据导入。

直接用 mysql 客户端
例如:

    /usr/local/mysql/bin/mysql -uyejr -pyejr db_name < db_name.sql

用 SOURCE 语法
其实这不是标准的 SQL 语法,而是 mysql 客户端提供的功能,例如:

    SOURCE /tmp/db_name.sql;

这里需要指定文件的绝对路径,并且必须是 mysqld 运行用户(例如 nobody)有权限读取的文件。

backup和mysqlhotcopy我都没用用过,所以这里也就不扩展了。。

7.连接:小表连大表还是大表连小表?

笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用’,’ 如:

SELECT * FROM table1 CROSS JOIN table2
SELECT * FROM table1 JOIN table2
SELECT * FROM table1,table2
由于其返回的结果为被连接的两个数据表的乘积,因此当有WHERE, ON或USING条件的时候一般不建议使用,因为当数据表项目太多的时候,会非常慢。一般使用LEFT [OUTER] JOIN或者RIGHT [OUTER] JOIN。
. MySQL中的外连接,分为左外连接和右连接,即除了返回符合连接条件的结果之外,还要返回左表(左连接)或者右表(右连接)中不符合连接条件的结果,相对应的使用NULL对应。

join的原理:从左表读出一条,选出所有与on匹配的右表纪录(n条)进行连接,形成n条纪录(包括重复的行,如:结果1和结果3),如果右边没有与on条件匹配的表,那连接的字段都是null.然后继续读下一条。

mysql join的时候会做优化吗?
LEFT JOIN条件用于确定如何从表B搜索行。(换句话说,不使用WHERE子句中的任何条件)

主要是两个表联查要怎么优化呢?就像这个问题问的那样是小表连大表还是大表连小表?
网络观点一:一般要使得数据库查询语句性能好点遵循一下原则:在做表与表的连接查询时,大表在前,小表在后。
有的却认为大表在前,小表在后,可是我觉得这些其实可能都是没有什么意义的。

这个问题还有待更新。。

8.安全保障?

mysql主从同步
集群?有哪些做法,各有哪些作用?

9 什么是查询缓存?怎么优化查询缓存?

先弄清楚查询缓存的原理:
缓存SELECT操作或预处理查询的结果集和SQL语句;
那么什么是预处理查询呢?

什么是预处理语句?可以把它看作是想要运行的 SQL 的一种编译过的模板,它可以使用变量参数进行定制。
预处理语句可以带来好处:
1.查询仅需解析(或预处理)一次,但可以用相同或不同的参数执行多次。当查询准备好后,数据库将分析、编译和优化执行该查询的计划。对于复杂的查询,此过程要花费较长的时间,如果需要以不同参数多次重复相同的查询,那么该过程将大大降低应用程序的速度。通过使用预处理语句,可以避免重复分析/编译/优化周期。简言之,预处理语句占用更少的资源,因而运行得更快。
2.提供给预处理语句的参数不需要用引号括起来,驱动程序会自动处理。如果应用程序只使用预处理语句,可以确保不会发生SQL 注入。(然而,如果查询的其他部分是由未转义的输入来构建的,则仍存在 SQL 注入的风险)。

如果使用查询缓存,在进行读写操作时会带来额外的资源消耗,消耗主要体现在以下几个方面
·        查询的时候会检查是否命中缓存,这个消耗相对较小
·        如果没有命中查询缓存,MYSQL会判断该查询是否可以被缓存,而且系统中还没有对应的缓存,则会将其结果写入查询缓存
·        如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使用MERGE表的查询。一个表可以被许多类型的语句更改,例如INSERTUPDATEDELETETRUNCATEALTER TABLEDROP TABLEDROP DATABASE。
对于InnoDB而言,事物的一些特性还会限制查询缓存的使用。当在事物A中修改了B表时,因为在事物提交之前,对B表的修改对其他的事物而言是不可见的。为了保证缓存结果的正确性,InnoDB采取的措施让所有涉及到该B表的查询在事物A提交之前是不可缓存的。如果A事物长时间运行,会严重影响查询缓存的命中率

查询缓存的空间不要设置的太大。
因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况

那么如何检查mysql系统的查询缓存发挥了积极的作用了呢?
检查是否从查询缓存中受益的最简单的办法就是检查缓存命中率,当服务器收到SELECT 语句的时候,Qcache_hits 和Com_select 这两个变量会根据查询缓存的情况进行递增,查询缓存命中率的计算公式是:Qcache_hits/(Qcache_hits + Com_select)。

可是我发现我们的系统的Qcache_hits总是0,这是因为这个值默认没有开启。

  新的SELECT语句或预处理查询语句,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写;
  mysql> SELECT @@query_cache_type;
+——————–+
| @@query_cache_type |
+——————–+
| ON |
+——————–+
//query_cache_type有3个值
0代表关闭查询缓存OFF,
1代表开启ON,
2(DEMAND)代表当sql语句中有SQL_CACHE关键词时才缓存

那么从上面的描述来看,不得不说说mysql查询的分析编译和优化了。

10.分析和编译

(http://blog.csdn.net/nic_r/article/details/7835908)

MySQL、PostgreSQL 等采用 C/C++ 实现的开源数据库采用的是现代的 yacc/lex 组合,也就是 GNU bison/flex。其他比较流行的工具还有 ANTLR、JavaCC 等等。这些工具大多采用扩展的 BNF 语法,并支持很多定制化选项,使得语法比较容易维护和实现。MySQL 语法分析器的入口函数是 MYSQLparse(),词法分析器的入口函数为 MYSQLlex()。不过, MySQL 的词法分析器是手工打造的,并且为了提高关键字的查找效率做了针对性的优化

mysql查询优化器
http://doc.mysql.cn/mysql5/refman-5.1-zh.html-chapter

询优化的一个更加灵活的方法是允许用户控制优化器详尽地搜索最佳查询评估方案。一般思想是优化器调查的方案越少,它编译一个查询所花费的时间越少。另一方面,因为优化器跳过了一些方案,它可能错过一个最佳方案。
优化器关于方案数量评估的行为可以通过两个系统变量来控制:
optimizer_prune_level变量告诉优化器根据对每个表访问的行数的估计跳过某些方案。我们的试验显示该类“有根据的猜测”很少错过最佳方案,并且可以大大降低查询编辑次数。这就是为什么默认情况该选项为on(optimizer_prune_level=1)。然而,如果你认为优化器错过了一个更好的查询方案,则该选项可以关闭(optimizer_prune_level=0),风险是查询编辑花费的时间更长。请注意即使使用该启发,优化器仍然可以探测呈指数数目的方案。
ptimizer_search_depth变量告诉优化器对于每个未完成的“未来的”方案,应查看多深,以评估是否应对它进一步扩大。optimizer_search_depth值较小会使查询编辑次数大大减小。例如,如果optimizer_search_depth接近于查询中表的数量,对12、13或更多表的查询很可能需要几小时甚至几天的时间来编译。同时,如果用optimizer_search_depth等于3或4编辑,对于同一个查询,编译器编译时间可以少于1分钟。如果不能确定合理的optimizer_search_depth值,该变量可以设置为0,告诉优化器自动确定该值。

11.mysql碎片

如果查询缓存碎片率超过20%,可以用FLUSH QUERY CACHE整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话

12.mysql怎么避免被注入攻击的危险?

什么是mysql注入呢?
下面几点是注入中经常会用到的语句
http://blog.sycsec.com/?p=1005
SQL injection is a code injection technique that might destroy your database.

SQL injection is one of the most common web hacking techniques.

SQL injection is the placement of malicious code in SQL statements, via web page input.
If you take user input through a webpage and insert it into a MySQL database, there’s a chance that you have left yourself wide open for a security issue known as SQL Injection

那么like怎么防注入攻击?

13.一些高级语言对访问mysql库的封装

比如clojure-korma,一句话,这个库采用自己的方式来构造sql语句,可以防止sql注入,也支持关系定义。
如果去阅读korma的源码就会发现他是怎么定义api给用户用,然后自己又怎么将这个组装成真正的sql:

(defn ->sql [query]
  (bind-params
   (case (:type query)
     :union (-> query sql-union sql-order)
     :union-all (-> query sql-union-all sql-order)
     :intersect (-> query sql-intersect sql-order)
     :select (-> query
                 sql-select
                 sql-joins
                 sql-where
                 sql-group
                 sql-having
                 sql-order
                 sql-limit-offset)
     :update (-> query
                 sql-update
                 sql-set
                 sql-where)
     :delete (-> query
                 sql-delete
                 sql-where)
     :insert (-> query
                 sql-insert))))

clojure-honeysql组装sql的方式不太一样,实现起来更加简单,废弃了entity的定义,但是依旧采用korma的exec api(底层是jdbc连接mysql),并且支持clojurescript。
—updating—

以上是关于mysql一些使用点的探讨的主要内容,如果未能解决你的问题,请参考以下文章

你可能会忽视的 MySQL 细节

企业检测SQL注入的一些方式探讨

企业检测SQL注入的一些方式探讨

MySQL系统架构

域名到站点的负载均衡技术一览(主要是探讨一台Nginx抵御大并发的解决方案)(转)

阿里二面:怎么解决MySQL死锁问题的?