mysql summary

1.設計數據庫時盡量避免冗餘,除非為了速度,並且數據不常改動

2.比起update一條record,不如增加一條record更新數據,這樣不用加鎖

3.mysql master-slave + ha

https://www.slideshare.net/matsunobu/automated-master-failover

4.組合索引

4.1用作index的每個field佔用空間應該盡量小,為了裝下更多data,reduce b+tree’s height

4.2最左前缀匹配原则,mysql会一直向右匹配直到遇到范围查询(>、<,between、like),所以範圍查詢的field放到index最後面

4.3sql中的=和in可以打亂順序,優化器會優化sql,保證會用上index

4.4尽量选择区分度高的field作为index

5.explain slow query,make sure using the right index.

5.1 type

(1)system: the table has only zero or one row,special case of const.
example:explain select * from (select * from t3 where id=3952602) a

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY system NULL NULL NULL NULL 1
2 DERIVED t3 const PRIMARY,idx_t3_id PRIMARY 4 1

(2)const:the table has only one matching row which is indexed. example:select * from t3 where id=3952602;

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 const PRIMARY,idx_t3_id PRIMARY 4  const 1

(3) eq_ref:all parts of an index are used by the join and the index is PRIMARY KEY or UNIQUE NOT NULL.
example: explain select * from t3,t4 where t3.id=t4.accountid;

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 1000
2 SIMPLE t3 eq_ref PRIMARY,idx_t3_id idx_t3_id 4 db.accountid 1

(4) ref:all of the matching rows of an indexed column are read for each combination of rows from the previous table.(index not unique)
example:explain select * from t3,t4 where t3.id=t4.accountid;

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 1000
2 SIMPLE t3 ref PRIMARY,idx_t3_id idx_t3_id 4 db.accountid 1

(5) ref_or_null: same as ref but include null

(6) index_merge: the join uses a list of indexes to produce the result set

(7) unique_subquery: an IN subquery returns only one result from the table and makes use of the primary key.
example:value IN (SELECT primary_key FROM single_table WHERE some_expr)

(8) index_subquery: the same as unique_subquery but returns more than one result row.

(9) range: an index is used to find matching rows in a specific range, typically when the key column is compared to a constant using operators like BETWEEN, IN, >, >=, etc.
example:explain select * from t3 where id=3952602 or id=3952603;

(10) index:the entire index tree is scanned to find matching rows

(11) all: the entire table is scanned to find matching rows for the join

5.2 key: 实际使用的index

6.innoDB support transacation, foreign key and row lock.

7.水平sharding
https://medium.com/@Pinterest_Engineering/sharding-pinterest-how-we-scaled-our-mysql-fleet-3f341e96ca6f

8.use utf8mb4 https://mathiasbynens.be/notes/mysql-utf8mb4

9.常用優化skill

9.1 where xxx in (subquery) => select * from a join (subquery) as b on a.xxx = b.xxx (using index xxx)
9.2 只要一行record就limit 1,mysql找到一條record就會停止search
9.3 只select需要的field
9.4 where a or b => a union all b

mysql replication

MySQL 复制的基本过程如下:
1.Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容
2. Master 接收到来自 Slave 的 IO 线程的请求后,通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置
3. Slave 的 IO 线程接收到信息后,将接收到的日志内容依次写入到 Slave 端的Relay Log文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master- info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”
4. Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后,会马上解析该 Log 文件中的内容成为在 Master 端真实执行时候的那些可执行的 Query 语句,并在自身执行这些 Query。这样,实际上就是在 Master 端和 Slave 端执行了同样的 Query,所以两端的数据是完全一样的

Mysql的半同步模式(Semisynchronous Replication)
我们知道在5.5之前,MySQL的复制其实是异步操作,而不是同步,也就意味着允许主从之间的数据存在一定的延迟,mysql当初这样设计的目的可能也是基于可用性的考虑,为了保证master不受slave的影响,并且异步复制使得master处于一种性能最优的状态:写完binlog后即可提交而不需要等待slave的操作完成。这样存在一个隐患,当你使用slave作为备份时,如果master挂掉,那么会存在部分已提交的事务未能成功传输到slave的可能,这就意味着数据丢失!
在MySQL5.5版本中,引入了半同步复制模式(Semi-synchronous Replication)能够成功(只是相对的)避免上述数据丢失的隐患。在这种模式下:master会等到binlog成功传送并写入至少一个slave的relay log之后才会提交,否则一直等待,直到timeout(默认10s)。当出现timeout的时候,master会自动切换半同步为异步,直到至少有一个slave成功收到并发送Acknowledge,master会再切换回半同步模式。结合这个新功能,我们可以做到,在允许损失一定的事务吞吐量的前提下来保证同步数据的绝对安全,因为当你设置timeout为一个足够大的值的情况下,任何提交的数据都会安全抵达slave。
mysql5.5 版本支持半同步复制功能(Semisynchronous Replication),但还不是原生的支持,是通过plugin来支持的,并且默认是没有安装这个插件的。不论是二进制发布的,还是自己源代码编译的,都会默认生成这个插件,一个是针对master 的一个是针对slave的,在使用之前需要先安装这俩plugins。

Master


#set binary logging (slaves read data from logs)
my.cnf
log-bin=mysql-bin
server-id=1(between 1 and (2^32)−1)

restart mysql

#create a user to replicate
GRANT REPLICATION SLAVE ON *.* TO ‘account’@’ip’ IDENTIFIED BY ‘password’;
FLUSH PRIVILEGES;

#use read lock
FLUSH TABLES WITH READ LOCK;

#fetch master bin log name and position
show master status;
example:
mysql> show master status;
+————-+———-+————–+——————+
| File | Position | Binlog_do_db | Binlog_ignore_db |
+————-+———-+————–+——————+
| bin-log.003 | 4 | adb | mysql |
+————-+———-+————–+——————+

#dump mysql data( small size) or copy the whole database file to slave
/usr/local/mysql-5.6.27/bin/mysqldump -u root -p [-S/tmp/mysql3310.sock] [-P 3310] [ad] > ~/[ad.sql]

#unlock table
UNLOCK TABLES;

Slave


#set relay logging
my.cnf
server-id=2(between 1 and (2^32)−1)
relay-log=mysql-relay-bin
[replicate-wild-ignore-table=db_name.tbl_name] (Patterns can contain the “%” and “_” wildcard characters)

restart mysql

#import data or copy data
/usr/local/mysql-5.6.27/bin/mysql -u root -p [-S/tmp/mysql3310.sock] [-P 3310] [ad] < ~/[ad.sql]

#setup slave’s master
CHANGE MASTER TO MASTER_HOST=’ip’, Master_Port=’port’,MASTER_USER=’account’, MASTER_PASSWORD=’password’, MASTER_LOG_FILE=’bin-log’, MASTER_LOG_POS = position;

#start slave
start slave

#check slave status
show slave status

important index:
Slave_IO_Running: Yes (if connecting ,maybe firewall problem)
Slave_SQL_Running: Yes
Master_Log_File: bin-log.003
Relay_Master_Log_File: bin-log.003
Read_Master_Log_Pos: 4
Exec_master_log_pos: 4
Seconds_Behind_Master: 0

reference:
http://wangwei007.blog.51cto.com/68019/965575