MySQL
MySQL is the world’s most popular open source database.
Data Type
Data Type Rules:
-
The smaller, the better
-
As simple as possible
-
Avoid use NULL
Index
The max limit number of mysql index is —— 16
Index not work case
-
!=
or<>
-
use fun();
-
JOIN, only use index when primary key has the same type with foreign key;
-
LIKE, REGEX only use index when first char is not wildcard.
like '%abc' ×
like 'abc%' √
-
ORDER BY: only use when the where condition is not a expression. It’s not works well when has multi-table.
-
index not works well when one column has many the same value, like (0/1), (y/n)
Full-Text index
The most time consuming sql may like this:
SELECT * FROM `table_name` WHERE `column_name` LIKE '%word%'
- create full-text
CREATE TABLE full_text(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL COMMENT '名称',
`info` VARCHAR(128) NULL DEFAULT '' COMMENT '信息',
PRIMARY KEY (`id`),
FULLTEXT (`name`, `info`) COMMENT '添加全文索引'
) COMMENT = '全文检索' ENGINE = MyISAM;
INSERT INTO full_text (name, info) VALUES
('mark the word', 'you can mark the word'),
('kill the word', 'you can kill the word'),
('like the word', 'you can like the word'),
('miss the word', 'you can miss the word'),
('think the word', 'you can think the word');
- query
SELECT * FROM full_text WHERE MATCH(`name`, `info`) AGAINST ('think like mark') > 0.0001;
SELECT * FROM full_text WHERE MATCH(`name`, `info`) AGAINST ('you word miss') > 0.0001;
Stored Procedure & Trigger (5.0+)
Stored Procedure
- define
DROP FUNCTION IF EXISTS shortLen;
CREATE FUNCTION shortLen(s VARCHAR(255), n INT)
RETURNS VARCHAR(255)
BEGIN
IF ISNULL(s)
THEN
RETURN '';
ELSEIF n < 15
THEN
RETURN LEFT(s, n);
ELSE
IF CHAR_LENGTH(s) <= n
THEN
RETURN s;
ELSE
RETURN CONCAT(LEFT(s, n - 10), '...', RIGHT(s, 5));
END IF;
END IF;
END;
- use
SELECT shortLen('asdfasdfasdfasdfasfdasdgasdgfadghfgdhfgjghj', 15);
- result
asdfa...gjghj
- show functions
SHOW FUNCTION STATUS;
SHOW CREATE FUNCTION shortLen;
自连接查询
$ vi ~/.base_profile
alias mysql=/usr/local/mysql/bin/mysql
$ source ~/.base_profile
- Create table
DROP TABLE IF EXISTS `t_score`;
CREATE TABLE `t_score`(
id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
score INT(11) NOT NULL DEFAULT 0,
student_id BIGINT(20) NOT NULL,
type INT(11) NOT NULL COMMENT '类型, 0->语文, 1->数学'
) COMMENT '分数表';
INSERT INTO t_score (score, student_id, type) VALUES
(50, 1, 0),
(60, 1, 1),
(78, 2, 0),
(99, 2, 1)
;
- Query all
mysql> SELECT * FROM t_score;
+----+-------+------------+------+
| id | score | student_id | type |
+----+-------+------------+------+
| 1 | 50 | 1 | 0 |
| 2 | 60 | 1 | 1 |
| 3 | 78 | 2 | 0 |
| 4 | 99 | 2 | 1 |
+----+-------+------------+------+
4 rows in set (0.00 sec)
- Query student’s math and chinese score
mysql> SELECT cs.score, ms.score, cs.student_id
-> FROM t_score AS cs, t_score AS ms
-> WHERE cs.student_id=ms.student_id
-> AND cs.type=0 AND ms.type=1;
+-------+-------+------------+
| score | score | student_id |
+-------+-------+------------+
| 50 | 60 | 1 |
| 78 | 99 | 2 |
+-------+-------+------------+
2 rows in set (0.00 sec)
并发控制
读写锁
- 读锁
共享锁, 多个客户之间读取资源互不干扰。
- 写锁
排他锁, 会阻塞其他的读锁和写锁。
锁粒度
- Table Lock
消耗最小。一个用户进行更新、删除、创建时,获取写锁,阻塞其他用户的读写。无写锁时,读锁互不影响。
- Row Lock
最大程度支持并发。开销较大。
Transaction
- Create table for test
CREATE TABLE `t_test`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`info` VARCHAR(100) DEFAULT NULL,
`create_time` TIMESTAMP NULL DEFAULT NULL
) COMMENT 'test table';
- Begin transaction
START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}
session_1 | session_2 |
---|---|
start transaction; Query OK, 0 rows affected (0.00 sec) | |
insert into t_test (info, create_time) VALUES ('1 insert', NOW()); Query OK, 1 row affected (0.00 sec) | |
select * from t_test; Empty set (0.00 sec) | |
commit; Query OK, 0 rows affected (0.00 sec) | |
mysql> select * from t_test; +----+----------+---------------------+ | id | info | create_time | +----+----------+---------------------+ | 1 | 1 insert | 2016-10-17 22:59:05 | +----+----------+---------------------+ 1 row in set (0.00 sec)| |
事务是一组原子性的SQL查询,内部的操作,要么全部成功,要么全部失败。
- Atomicity
不可再分
- Consistency
从一种一致性状态到另一种一致性状态
- Isolation
事务在最终提交之前,所有的修改操作对其他事务都是不可见的
- Durability
事务一旦提交,修改将会在数据库持久生效
Isolation level
Isolation Level | dirty read | non-repeatable read | phantom read | add lock read |
---|---|---|---|---|
uncommitted read | yes | yes | yes | no |
committed read | no | yes | yes | no |
repeatable read | no | no | yes | no |
serializable | no | no | no | yes |
Dead Lock
当两个或者两个以上事务在同一资源上相互占用,并请求锁定占用对方的资源,会造成死锁。
如 Innodb 引擎,会检测死锁,并立刻返回错误。
Config MySQL
-
降低初始化占用内存
-
Edit
my.cnf
file in/etc/mysql
performance_schema_max_table_instances=600
table_definition_cache=400
table_open_cache=256
- timestamp
CREATE TABLE test(
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
COMMENT '创建时,默认为系统当前时间。以后不再刷新',
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
COMMENT '创建/修改时刷新时间,同TIMESTAMP'
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='test';
MySQL Remote Connection
- Link to localhost
$ mysql -h localhost -u root -p
- Link to remote
houbinbindeMacBook-Pro:~ houbinbin$ mysql -h remote -uroot -p
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on 'remote' (61)
make remote access enable
- Login Remote MySQL
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select Host,User from user;
+-------------------------+------------------+
| Host | User |
+-------------------------+------------------+
| 127.0.0.1 | root |
| ::1 | root |
| izuf60ahcky4k4nfv470juz | root |
| localhost | debian-sys-maint |
| localhost | root |
+-------------------------+------------------+
5 rows in set (0.00 sec)
- Update
mysql
.user
run this sql:
UPDATE `user` SET Host='%' WHERE User ='root' LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
after update:
mysql> select Host,User from user;
+-------------------------+------------------+
| Host | User |
+-------------------------+------------------+
| % | root |
| 127.0.0.1 | root |
| ::1 | root |
| izuf60ahcky4k4nfv470juz | root |
| localhost | debian-sys-maint |
+-------------------------+------------------+
5 rows in set (0.00 sec)
use flush privileges;
to flush.
- Edit
my.cnf
file in/etc/mysql
comment the line of bind-address
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
# bind-address = 127.0.0.1
use command to restart mysql
root@iZuf60ahcky4k4nfv470juZ:~# service mysql restart
mysql stop/waiting
mysql start/running, process 2493
table name sensitive
Table name in ubuntu is case-sensitive, so. If you want it works like in windows. Just:
add the content under [mysqld]
, and restart mysql.
vi /etc/mysql/my.cnf
lower_case_table_names = 1
and then use show variables like 'lower_%'
test it:
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| lower_case_file_system | OFF |
| lower_case_table_names | 1 |
+------------------------+-------+
mysql开启日志功能
- 查看是否开启
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | OFF |
+---------------+-------+
1 row in set (0.00 sec)
- 查看当前日志
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | OFF |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show master status;
Empty set (0.00 sec)
- 编辑配置文件
my.cnf
vi /etc/mysql/my.cnf
开启日志:
log-bin = /var/mysqllog/logbin.log
- 查看状态
service mysql restart
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 107 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
备份还原
1、备份一个数据库
mysqldump基本语法:
mysqldump -u username -p dbname table1 table2 ...-> BackupName.sql
其中:
dbname参数表示数据库的名称;
table1和table2参数表示需要备份的表的名称,为空则整个数据库备份;
BackupName.sql
参数表设计备份文件的名称,文件名前面可以加上一个绝对路径。通常将数据库被分成一个后缀名为sql的文件;
如:
mysqldump -u root -p blog_view > /root/backup/blog_view.sql;
- 备份多个数据库
mysqldump -u username -p --databases dbname2 dbname2 > Backup.sql
- 备份所有数据库
mysqldump -u username -p --all-databases > BackupName.sql
2、还原一个数据库
mysql -u root -p [dbname] < backup.sq
定时备份
- 创建定时备份脚本:
vi backup_blog_view.sh
- 添加内容如下:
#!/bin/bash
mysqldump -uroot -p123456 blog_view > /root/backup/blog_view_$(date +%Y%m%d_%H%M%S).sql
- 进行备份压缩:
#!/bin/bash
mysqldump -uroot -p123456 blog_view | gzip > /root/backup/blog_view_$(date +%Y%m%d_%H%M%S).sql.gz
- 添加权限,执行测试:
chmod +x backup_blog_view.sh
./backup_blog_view.sh
- 定时运行
ubuntu 下使用 crontab
$ ~# crontab -e
添加内容如下:
0 2 * * * /root/shell/backup_blog_view.sh
意思为凌晨2点执行备份脚本。
- 重启 CRON 进程:
~# /etc/init.d/cron restart
Dead lock
- mysql 更新,根据普通索引。会首先锁定普通索引, 在锁定主索引
- mysql 根据主键更新会直接锁定主索引
二者同时使用,会造成锁争用——死锁。
最佳实践:
每次更新或者删除,根据索引条件查询出记录。再根据主键进行删除或更新。
备份实战
切换至root.
Ubuntu14.04 默认mysql5.5.53
,现在将其升级到 5.6
Prepare
- reboot
$ sudo reboot
- backup
$ pwd
/home/hbb/backup
$ mysqldump -uroot -p123456 --all-databases > backup_all_20170101.sql
- stop mysql
$ sudo /etc/init.d/mysql stop
remove mysql
apt-get remove mysql-server
apt-get --purge remove mysql-server
apt-get autoremove
- update and upgrade apt-get
apt-get update
apt-get upgrade
upgrade会更新很多东西,可以跳过不执行。
- install mysql-server-5.6
apt-get install mysql-server-5.6
- re-back
mysql -uroot -p123456 < backup_all_20170101.sql
- version
$ mysql --version;
mysql Ver 14.14 Distrib 5.6.33, for debian-linux-gnu (x86_64) using EditLine wrapperv