@[TOC](第二十三章 MYSQL数据库 手册5 索引、并发控制和事务、日志)
目的
索引,并发控制和事务,日志,管理数据库。
前提
linux系统,已安装好数据库。
⽣成⼤数据,百万条记录
7 ~]# vim /etc/my.cnf
[mysqld]
innodb_file_per_table #添加
7 ~]# systemctl start mariadb #重启服务
hellodb_innodb.sql下载 testlog.sql下载
7 ~]# vim testlog.sql
create table testlog (id int auto_increment primary key,name char(10),age int default 20);
delimiter $$
create procedure pro_testlog()
begin
declare i int;
set i = 1;
while i < 100000
do insert into testlog(name,age) values (concat('wang',i),i);
set i = i +1;
end while;
end$$
delimiter ;
将表导⼊hellodb数据库
7 ~]# mysql < hellodb_innodb.sql
7 ~]# mysql hellodb < testlog.sql
执⾏
7 ~]# mysql hellodb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 5.5.60-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [hellodb]> call pro_testlog;
Query OK, 1 row affected (47.67 sec)
⽣成
MariaDB [hellodb]> select count(*) from testlog;
+----------+
| count(*) |
+----------+
| 999999 |
+----------+
1 row in set (0.01 sec)
主键索引
MariaDB [hellodb]> show indexes from testlog\G
*************************** 1. row ***************************
Table: testlog
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 1000544
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec)
命令介绍
1、索引
1.1、索引的定义
索引:是特殊数据结构,定义在查找时作为查找条件的字段,在MySQL又称为键key,索引通过存储引擎实现
优点:
索引可以降低服务需要扫描的数据量,减少了IO次数
索引可以帮助服务器避免排序和使用临时表
索引可以帮助将随机I/O转为顺序I/O
缺点:
占用额外空间,影响插入速度
索引类型:
B+ TREE、HASH、R TREE
聚簇(集)索引、非聚簇索引:数据和索引是否存储在一起
主键索引、二级(辅助)索引
稠密索引、稀疏索引:是否索引了每一个数据项
简单索引、组合索引
左前缀索引:取前面的字符做索引
覆盖索引:从索引中即可取出要查询的数据,性能高
1.2、优化
索引优化建议
只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引
尽量使用短索引,如果可以,应该制定一个前缀长度
对于经常在where子句使用的列,最好设置索引
对于有多个列where或者order by子句,应该建立复合索引
对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引
尽量不要在列上进行运算(函数操作和表达式操作)
尽量不要使用not in和<>操作
SQL语句性能优化
查询时,能不要*就不用*,尽量写全字段名
大部分情况连接效率远大于子查询
多表连接时,尽量小表驱动大表,即小表 join 大表
在有大量记录的表分页时使用limit
对于经常使用的查询,可以开启缓存
多使用explain和profile分析查询语句
查看慢查询日志,找出执行时间长的sql语句优化
1.3、管理索引
创建索引:
CREATE [UNIQUE] INDEX index_name ON tbl_name (index_col_name[(length)],...);
ALTER TABLE tbl_name ADD INDEX index_name(index_col_name);
help CREATE INDEX;
删除索引:
DROP INDEX index_name ON tbl_name;
ALTER TABLE tbl_name DROP INDEX index_name(index_col_name);
查看索引:
SHOW INDEXES FROM [db_name.]tbl_name;
优化表空间:
OPTIMIZE TABLE tb_name;
查看索引的使用
SET GLOBAL userstat=1;
SHOW INDEX_STATISTICS;
【例1】主键索引
MariaDB [hellodb]> desc students;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
MariaDB [hellodb]> show indexes from students\G
*************************** 1. row ***************************
Table: students
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: StuID
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec)
【例2】建⽴索引
MariaDB [hellodb]> create index idx_name on students(name);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [hellodb]> show indexes from students\G
*************************** 1. row ***************************
Table: students
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: StuID
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: students
Non_unique: 1
Key_name: idx_name
Seq_in_index: 1
Column_name: Name
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
2 rows in set (0.00 sec)
1.4、EXPLAIN,分析索引的有效性
EXPLAIN SELECT clause 获取查询执行计划信息,用来查看查询优化器如何执行查询
id: 当前查询语句中,每个SELECT语句的编号
复杂类型的查询有三种:
简单子查询
用于FROM中的子查询
联合查询:UNION
select_type:
简单查询为SIMPLE
复杂查询:
SUBQUERY 简单子查询
PRIMARY 最外面的SELECT
DERIVED 用于FROM中的子查询
UNION UNION语句的第一个之后的SELECT语句
UNION RESULT 匿名临时表
table:SELECT语句关联到的表
type:关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式,以下顺序,性能从低到高
ALL: 全表扫描
index:根据索引的次序进行全表扫描;如果在Extra列出现“Using index”表示了使用覆盖索引,而非全表
扫描
range:有范围限制的根据索引实现范围扫描;扫描位置始于索引中的某一点,结束于另一点
ref: 根据索引返回表中匹配某单个值的所有行
eq_ref:仅返回一个行,但与需要额外与某个参考值做比较
const, system: 直接返回单个行
possible_keys:查询可能会用到的索引
key: 查询中使用到的索引
key_len: 在索引使用的字节数
ref: 在利用key字段所表示的索引完成查询时所用的列或某常量值
rows:MySQL估计为找所有的目标行而需要读取的行数
Extra:额外信息
Using index:MySQL将会使用覆盖索引,以避免访问表
Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤
Using temporary:MySQL对结果排序时会使用临时表
Using filesort:对结果使用一个外部索引排序
【例3】查询主键索引
MariaDB [hellodb]> explain select * from students where stuid=20;
+------+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | students | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
possible_keys可能的索引:PRIMARY主键索引。索引key:PRIMARY主键索引。
没有利⽤索引
MariaDB [hellodb]> explain select * from students where age=20;
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
【例4】只有左前缀能利⽤索引
MariaDB [hellodb]> explain select * from students where name like 'S%';
+------+-------------+----------+-------+---------------+----------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+----------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | idx_name | idx_name | 152 | NULL | 4 | Using index condition |
+------+-------------+----------+-------+---------------+----------+---------+------+------+-----------------------+
1 row in set (0.00 sec)
MariaDB [hellodb]> explain select * from students where name like '%S%';
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
25条记录中有6条记录,系统⾃动不⽤索引。
MariaDB [hellodb]> explain select * from students where name like 'x%';
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | idx_name | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
【例5】对testlog这张⼤表做操作。
MariaDB [hellodb]> select * from testlog where age=90000;
+-------+-----------+-------+
| id | name | age |
+-------+-----------+-------+
| 90000 | wang90000 | 90000 |
+-------+-----------+-------+
1 row in set (0.02 sec)
建⽴索引
MariaDB [hellodb]> create index idx_age on testlog(age);
Query OK, 0 rows affected (0.11 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [hellodb]> select * from testlog where age=90000;
+-------+-----------+-------+
| id | name | age |
+-------+-----------+-------+
| 90000 | wang90000 | 90000 |
+-------+-----------+-------+
1 row in set (0.00 sec)
没有索引,很慢。
MariaDB [hellodb]> select * from testlog where name='wang90000';
+-------+-----------+-------+
| id | name | age |
+-------+-----------+-------+
| 90000 | wang90000 | 90000 |
+-------+-----------+-------+
1 row in set (0.02 sec)
【例6】复合索引,name和age。
MariaDB [hellodb]> desc students;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| StuID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(50) | NO | MUL | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | NO | | NULL | |
| ClassID | tinyint(3) unsigned | YES | | NULL | |
| TeacherID | int(10) unsigned | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
创建复合索引
MariaDB [hellodb]> create index idx_name_age on students(name,age);
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
查看索引,3,4,同⼀个索引的两个字段
MariaDB [hellodb]> show indexes from students \G
*************************** 1. row ***************************
Table: students
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: StuID
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: students
Non_unique: 1
Key_name: idx_name
Seq_in_index: 1
Column_name: Name
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 3. row ***************************
Table: students
Non_unique: 1
Key_name: idx_name_age
Seq_in_index: 1
Column_name: Name
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 4. row ***************************
Table: students
Non_unique: 1
Key_name: idx_name_age
Seq_in_index: 2
Column_name: Age
Collation: A
Cardinality: 25
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
4 rows in set (0.01 sec)
MariaDB [hellodb]> select * from students where name like 's%';
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
4 rows in set (0.00 sec)
可以⽤两个索引,实际⽤了idx_name索引。
MariaDB [hellodb]> explain select * from students where name like 's%';
+------+-------------+----------+-------+-----------------------+----------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+-----------------------+----------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | idx_name,idx_name_age | idx_name | 152 | NULL | 4 | Using index condition |
+------+-------------+----------+-------+-----------------------+----------+---------+------+------+-----------------------+
1 row in set (0.00 sec)
删除多余的索引
MariaDB [hellodb]> drop index idx_name on students;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [hellodb]> explain select * from students where name like 's%';
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
| 1 | SIMPLE | students | range | idx_name_age | idx_name_age | 152 | NULL | 4 | Using index condition |
+------+-------------+----------+-------+---------------+--------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)
复合索引,不能跳过第⼀个索引,直接⽤第⼆个
MariaDB [hellodb]> explain select * from students where age='20';
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
【例7】索引的统计
MariaDB [hellodb]> SHOW INDEX_STATISTICS;
Empty set (0.00 sec)
查看索引的使⽤
MariaDB [hellodb]> SET GLOBAL userstat=1;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show variables like 'userstat';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| userstat | ON |
+---------------+-------+
1 row in set (0.00 sec)
MariaDB [hellodb]> select * from students where name like 's%';
+-------+-------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+-------------+-----+--------+---------+-----------+
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+-------+-------------+-----+--------+---------+-----------+
4 rows in set (0.00 sec)
MariaDB [hellodb]> SHOW INDEX_STATISTICS;
+--------------+------------+--------------+-----------+
| Table_schema | Table_name | Index_name | Rows_read |
+--------------+------------+--------------+-----------+
| hellodb | students | idx_name_age | 4 |
+--------------+------------+--------------+-----------+
1 row in set (0.00 sec)
2、并发控制
2.1、锁
锁粒度:
表级锁
行级锁
锁:
读锁:共享锁,只读不可写(包括当前事务) ,多个读互不阻塞
写锁:独占锁,排它锁,写锁会阻塞其它事务(不包括当前事务)的读和它锁
实现
存储引擎:自行实现其锁策略和锁粒度
服务器级:实现了锁,表级锁,用户可显式请求
分类:
隐式锁:由存储引擎自动施加锁
显式锁:用户手动请求
锁策略:在锁粒度及数据安全性寻求的平衡机制
显式使用锁
LOCK TABLES 加锁
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type: READ , WRITE
UNLOCK TABLES 解锁
FLUSH TABLES [tb_name[,...]] [WITH READ LOCK]
关闭正在打开的表(清除查询缓存),通常在备份前加全局读锁
SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]
查询时加写或读锁
死锁:
两个或多个事务在同一资源相互占用,并请求锁定对方占用的资源的状态
【例8】读锁,在⼀台虚拟机上开两个终端
终端1加锁,⾃⼰删,报错。
MariaDB [hellodb]> lock tables students read;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> delete from students where stuid=25;
ERROR 1099 (HY000): Table 'students' was locked with a READ lock and can't be updated
终端2删不掉,定住了,要等待超过超时时长后退出。
7 ~]# mysql hellodb
MariaDB [hellodb]> delete from students where stuid=25;
终端1,解锁
MariaDB [hellodb]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
终端2可以删除
MariaDB [hellodb]> delete from students where stuid=25;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
24 rows in set (0.00 sec)
【例9】写锁,在⼀台虚拟机上开两个终端
终端1加写锁,⾃⼰依然可以读和写
MariaDB [hellodb]> lock tables students write;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> delete from students where stuid=24;
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
+-------+---------------+-----+--------+---------+-----------+
23 rows in set (0.00 sec)
终端2定住了,不能读也不能写。
MariaDB [hellodb]> select * from students;
终端1解写锁
MariaDB [hellodb]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
终端2能读、能写。
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
+-------+---------------+-----+--------+---------+-----------+
23 rows in set (0.00 sec)
【例10】读全局锁,所有表都不能做操作。
MariaDB [hellodb]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> delete from students where stuid=23;
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
MariaDB [hellodb]> create user test@'%' identified by 'centos';
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
释放锁
MariaDB [hellodb]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
2.2、事务
事务Transactions:一组原子性的SQL语句,或一个独立工作单元
事务日志:记录事务信息,实现undo,redo等故障恢复功能
ACID特性:
A:atomicity原子性;整个事务中的所有操作要么全部成功执行,要么全部失败后回滚
C:consistency一致性;数据库总是从一个一致性状态转换为另一个一致性状态
I:Isolation隔离性;一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,
实现并发
D:durability持久性;一旦事务提交,其所做的修改会永久保存于数据库中
启动事务:
BEGIN
BEGIN WORK
START TRANSACTION
结束事务:
COMMIT:提交
ROLLBACK: 回滚
注意:只有事务型存储引擎中的DML语句方能支持此类操作
自动提交:set autocommit={1|0} 默认为1,为0时设为非自动提交
建议:显式请求和提交事务,而不要使用“自动提交”功能
事务支持保存点:savepoint
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
7 ~]# vim /etc/my.cnf
[mysqld]
autocommit=OFF #默认为1,为0时设为非自动提交
7 ~]# systemctl restart mariadb #重启服务
【例11】脏数据。在⼀台虚拟机上开两个终端。
终端1,事务形式添加数据
7 ~]# mysql hellodb
MariaDB [hellodb]> begin ;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> insert students (name,age,gender)values('a',30,'m');
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> insert students (name,age,gender)values('b',25,'f');
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students; #可以看到刚刚添加的两条记录
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
终端2,⽆法查到
7 ~]# mysql hellodb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.60-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
+-------+---------------+-----+--------+---------+-----------+
23 rows in set (0.00 sec)
终端1,commit提交
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
终端2,可以查到
MariaDB [hellodb]> select * from students; #可以查看到终端1刚刚添加的两条记录
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.00 sec)
【例12】DDL语⾔是直接执⾏的,不能撤销。
MariaDB [hellodb]> SHOW TABLES;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| testlog |
| toc |
+-------------------+
8 rows in set (0.00 sec)
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> drop table toc;
Query OK, 0 rows affected (0.01 sec)
MariaDB [hellodb]> rollback;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from toc;
ERROR 1146 (42S02): Table 'hellodb.toc' doesn't exist
【例13】⾃动提交。
MariaDB [hellodb]> show variables like 'auto%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | ON |
| automatic_sp_privileges | ON |
+--------------------------+-------+
4 rows in set (0.00 sec)
以变量⽅式,改为⾮⾃动提交。
MariaDB [hellodb]> set autocommit=off;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show variables like 'auto%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | OFF |
| automatic_sp_privileges | ON |
+--------------------------+-------+
4 rows in set (0.00 sec)
MariaDB [hellodb]> insert students(name,age,gender)values('tom',20,'M');
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 28 | tom | 20 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
26 rows in set (0.00 sec)
可以回滚,必须提交。
MariaDB [hellodb]> rollback; #回滚
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students; #发现已经回滚、刚刚添加的tom没生效
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
25 rows in set (0.01 sec)
【例14】事务保存点。
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.00 sec)
添加记录
MariaDB [hellodb]> insert students(name,age,gender)values('tom',20,'M');
Query OK, 1 row affected (0.00 sec)
添加保存点
MariaDB [hellodb]> savepoint tom;
Query OK, 0 rows affected (0.00 sec)
添加记录
MariaDB [hellodb]> insert students(name,age,gender)values('jerry',22,'M');
Query OK, 1 row affected (0.00 sec)
添加保存点
MariaDB [hellodb]> savepoint jerry;
Query OK, 0 rows affected (0.00 sec)
添加记录
MariaDB [hellodb]> insert students(name,age,gender)values('xiaoqiang',23,'M');
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 29 | tom | 20 | M | NULL | NULL |
| 30 | jerry | 22 | M | NULL | NULL |
| 31 | xiaoqiang | 23 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
28 rows in set (0.00 sec)
回滚到jerry保存点
MariaDB [hellodb]> rollback to jerry; #发现刚刚的'xiaoqiang'记录没有了
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 25 | a | 30 | M | NULL | NULL |
| 26 | b | 25 | F | NULL | NULL |
| 28 | tom | 20 | M | NULL | NULL |
| 29 | jerry | 22 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
27 rows in set (0.01 sec)
删除Jerry保存点
MariaDB [hellodb]> release savepoint jerry;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> rollback to jerry;
ERROR 1305 (42000): SAVEPOINT jerry does not exist
2.3、事务隔离级别
事务隔离级别:从上至下更加严格
READ UNCOMMITTED 可读取到未提交数据,产生脏读
READ COMMITTED 可读取到提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,
导致每次读取数据不一致
REPEATABLE READ 可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改
数据,仍只能读取到未修改前的旧数据。此为MySQL默认设置
SERIALIZABLE 可串行化,未提交的读事务阻塞修改事务,或者未提交的修改事务阻塞读事务。导致并发性
能差
MVCC: 多版本并发控制,和事务级别相关
指定事务隔离级别:
服务器变量tx_isolation指定,默认为REPEATABLE-READ,可在GLOBAL和SESSION级进行设置
SET tx_isolation=''
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE
服务器选项中指定
vim /etc/my.cnf
[mysqld]
transaction-isolation=SERIALIZABLE
【例15】临时修改事务隔离级别
MariaDB [hellodb]> show variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
作为变量改
MariaDB [hellodb]> set tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show variables like 'tx_isolation';
+---------------+------------------+
| Variable_name | Value |
+---------------+------------------+
| tx_isolation | READ-UNCOMMITTED |
+---------------+------------------+
1 row in set (0.00 sec)
【例16】长久修改事务隔离级别,tx_isolation不是服务选项,要⽤对应的选项。
7 ~]# vim /etc/my.cnf
[mysqld]
tx_isolation='READ-UNCOMMITTED'
7 ~]# systemctl restart mariadb #启动时报错
Job for mariadb.service failed because the control process exited with error code. See "systemctl status mariadb.service" and "journalctl -xe" for details.
启动时报错。
7 ~]# vim /etc/my.cnf
[mysqld]
transaction_isolation='READ-UNCOMMITTED'
#tx_isolation='READ-UNCOMMITTED'
7 ~]# systemctl restart mariadb
【例17】事务隔离级别调整为READ-UNCOMMITTED,第⼆个终端也可以看到脏读了。
终端1
7 ~]# vim /etc/my.cnf
[mysqld]
transaction_isolation='READ-UNCOMMITTED'
7 ~]# systemctl restart mariadb
进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.00 sec)
终端2,进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.00 sec)
终端1
MariaDB [hellodb]> insert students (name,age)values('xiaoming',20);
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students;
...
| 25 | a | 30 | M | NULL | NULL |
| 26 | b | 25 | F | NULL | NULL |
| 27 | xiaoming | 20 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
26 rows in set (0.01 sec)
终端2,可以看到脏读
MariaDB [hellodb]> select * from students;
...
| 25 | a | 30 | M | NULL | NULL |
| 26 | b | 25 | F | NULL | NULL |
| 27 | xiaoming | 20 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
26 rows in set (0.01 sec)
【例18】事务隔离级别调整为READ-COMMITTED,第⼆个终端看不到脏读,必须等待终端⼀提交。产⽣不可重复读,在 ⼀个事务⾥,每次的查看结果不⼀样。
终端1
7 ~]# vim /etc/my.cnf
[mysqld]
transaction_isolation='READ-COMMITTED'
7 ~]# systemctl restart mariadb
终端1,进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.01 sec)
终端2,进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
Query OK, 0 rows affected (0.01 sec)
终端1,添加记录,⾃⼰能看到。
MariaDB [hellodb]> insert students (name,age)values('xiaoming',20);
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students;
...
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
| 29 | xiaoqiang | 23 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
27 rows in set (0.00 sec)
终端2,看不到脏读
MariaDB [hellodb]> select * from students;
...
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
26 rows in set (0.00 sec)
终端1,提交
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.01 sec)
终端2,能够看到了
MariaDB [hellodb]> select * from students;
...
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
| 29 | xiaoqiang | 23 | M | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
27 rows in set (0.00 sec)
终端1,添加记录
MariaDB [hellodb]> insert students (name,age)values('xiaohong',18);
Query OK, 1 row affected (0.00 sec)
终端2,不可重复度
MariaDB [hellodb]> select * from students;
...
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
| 29 | xiaoqiang | 23 | M | NULL | NULL |
| 30 | xiaohong | 18 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
28 rows in set (0.00 sec)
【例19】事务隔离级别调整为REPEATABLE-READ,可重复度产⽣幻读,适合事务⽅式,默认的隔离级别。
终端1
7 ~]# vim /etc/my.cnf
[mysqld]
transaction_isolation='REPEATABLE-READ'
7 ~]# systemctl restart mariadb
进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
终端2,进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
终端1,添加,提交
MariaDB [hellodb]> insert students (name,age)values('xiaochen',38);
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
终端2,依然看不到。如果看到了,可能是缓存问题。看不到‘xiaochen’记录
MariaDB [hellodb]> select * from students;
···
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
| 29 | xiaoqiang | 23 | M | NULL | NULL |
| 30 | xiaohong | 18 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
28 rows in set (0.00 sec)
【例20】事务隔离级别调整为SERIALIZABLE,可串⾏化,安全不冲突,严重影响并发性。未提交的事务阻⽌了读、写操 作。
终端1
7 ~]# vim /etc/my.cnf
[mysqld]
transaction_isolation='SERIALIZABLE'
7 ~]# systemctl restart mariadb
进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb
MariaDB [hellodb]> begin;
终端2,进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb
MariaDB [hellodb]> begin;
终端1,删除操作(再次查看发现'第29条已经删除')
MariaDB [hellodb]> delete from students where stuid=31;
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from students;
...
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
| 29 | xiaoqiang | 23 | M | NULL | NULL |
| 30 | xiaohong | 18 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
28 rows in set (0.00 sec)
终端2,定住了,等待提交
MariaDB [hellodb]> select * from students;
终端1,提交
MariaDB [hellodb]> commit;
Query OK, 0 rows affected (0.00 sec)
终端2,⾃动执⾏了。(16.96 sec)
MariaDB [hellodb]> select * from students;
...
| 26 | a | 30 | M | NULL | NULL |
| 27 | b | 25 | F | NULL | NULL |
| 28 | xiaoming | 20 | F | NULL | NULL |
| 29 | xiaoqiang | 23 | M | NULL | NULL |
| 30 | xiaohong | 18 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
28 rows in set (16.96 sec)
【例21】死锁,发现后,直接杀进程。慎⽤,丢数据。
终端1
7 ~]# vim /etc/my.cnf
[mysqld]
transaction_isolation='SERIALIZABLE'
7 ~]# systemctl restart mariadb
进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
终端2,进⼊数据库mysql;use hellodb;
7 ~]# mysql hellodb;
MariaDB [hellodb]> begin;
终端1,删除操作
MariaDB [hellodb]> delete from students where stuid=30;
Query OK, 1 row affected (0.00 sec)
终端2,定住了,等待提交
MariaDB [hellodb]> select * from students;
终端1,查找进程,杀掉。
MariaDB [hellodb]> show processlist;
+----+------+-----------+---------+---------+------+--------------+------------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+------+-----------+---------+---------+------+--------------+------------------------+----------+
| 4 | root | localhost | hellodb | Query | 4 | Sending data | select * from students | 0.000 |
| 5 | root | localhost | hellodb | Query | 0 | NULL | show processlist | 0.000 |
+----+------+-----------+---------+---------+------+--------------+------------------------+----------+
2 rows in set (0.00 sec)
MariaDB [hellodb]> kill 4;
Query OK, 0 rows affected (0.00 sec)
终端2
MariaDB [hellodb]> select * from students;
ERROR 2013 (HY000): Lost connection to MySQL server during query #查询期间与MySQL服务器的连接中断
3、⽇志
事务日志 transaction log 错误日志 error log 通用日志 general log 慢查询日志 slow query log 二进制日志 binary log 中继日志 reley log
事务日志的写入类型为“追加”,因此其操作为“顺序IO”;通常也被称为:预写式日志 write ahead logging 事务日志文件:ib_logfile0, ib_logfile1
3.1、事务⽇志
事务型存储引擎自行管理和使用,建议和数据文件分开存放
redo log
undo log
Innodb事务日志相关配置:
show variables like '%innodb_log%';
innodb_log_file_size 5242880 每个日志文件大小
innodb_log_files_in_group 2 日志组成员个数
innodb_log_group_home_dir ./ 事务文件路径
innodb_flush_log_at_trx_commit 默认为1
innodb_flush_log_at_trx_commit 决定着什么时候把事务日志的信息写入磁盘。
说明:设置为1,同时sync_binlog = 1表示最高级别的容错
innodb_use_global_flush_log_at_trx_commit的值确定是否可以使用SET语句
重置此变量
1默认情况下,日志缓冲区将写入日志文件,并在每次事务后执行刷新到磁盘。这是完全遵守ACID特性
0提交时没有任何操作; 而是每秒执行一次日志缓冲区写入和刷新。 这样可以提供更好的性能,但服务器崩
溃可以清除最后一秒的事务
2每次提交后都会写入日志缓冲区,但每秒都会进行一次刷新。 性能比0略好一些,但操作系统或停电可能导
致最后一秒的交易丢失
3模拟MariaDB 5.5组提交(每组提交3个同步),此项MariaDB 10.0支持
【例22】事务⽇志,ib_logfile0,ib_logfile1
7 ~]# ll /var/lib/mysql/
total 28700
-rw-rw---- 1 mysql mysql 16384 May 30 16:42 aria_log.00000001
-rw-rw---- 1 mysql mysql 52 May 30 16:42 aria_log_control
drwx------ 2 mysql mysql 150 May 30 01:08 hellodb
-rw-rw---- 1 mysql mysql 18874368 May 30 16:44 ibdata1
-rw-rw---- 1 mysql mysql 5242880 May 30 16:44 ib_logfile0 <--事务⽇志
-rw-rw---- 1 mysql mysql 5242880 May 30 01:05 ib_logfile1 <--事务⽇志
drwx------ 2 mysql mysql 4096 May 30 01:05 mysql
srwxrwxrwx 1 mysql mysql 0 May 30 16:42 mysql.sock
drwx------ 2 mysql mysql 4096 May 30 01:05 performance_schema
drwx------ 2 mysql mysql 6 May 30 01:05 test
MariaDB [(none)]> show variables like '%innodb_log%';
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| innodb_log_block_size | 512 | 块大小'512字节'
| innodb_log_buffer_size | 8388608 | 缓存大小'8M'
| innodb_log_file_size | 5242880 | 每个日志文件大小
| innodb_log_files_in_group | 2 | 日志组成员个数
| innodb_log_group_home_dir | ./ | 事务文件路径
+---------------------------+---------+
5 rows in set (0.00 sec)
【例23】事务⽇志,⾃定义存放地址,放到不同的磁盘上,io效率更⾼。
7 ~]# mkdir -pv /data/mysql
mkdir: created directory ‘/data/mysql’
7 ~]# chown mysql.mysql /data/mysql
7 ~]# ll -d /data/mysql
drwxr-xr-x 2 mysql mysql 6 May 30 18:46 /data/mysql
7 ~]# vim /etc/my.cnf
[mysqld]
innodb_log_group_home_dir=/data/mysql
7 ~]# systemctl restart mariadb
7 ~]# ll /data/mysql/
total 10240
-rw-rw---- 1 mysql mysql 5242880 May 30 18:49 ib_logfile0
-rw-rw---- 1 mysql mysql 5242880 May 30 18:49 ib_logfile1
【例24】选项innodb_flush_log_at_trx_commit ,决定着什么时候把事务⽇志的信息写⼊磁盘。
7 ~]# mysql
MariaDB [(none)]> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
1 row in set (0.00 sec)
3.2、错误⽇志
错误日志
mysqld启动和关闭过程中输出的事件信息
mysqld运行中产生的错误信息
event scheduler运行一个event时产生的日志信息
在主从复制架构中的从服务器上启动从服务器线程时产生的信息
错误日志相关配置 SHOW GLOBAL VARIABLES LIKE 'log_error'
错误文件路径
log_error=/PATH/TO/LOG_ERROR_FILE
是否记录警告信息至错误日志文件
log_warnings=1|0 默认值1
【例25】错误⽇志
MariaDB [(none)]> show global variables like 'log_error';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| log_error | /var/log/mariadb/mariadb.log |
+---------------+------------------------------+
1 row in set (0.00 sec)
MariaDB [(none)]> exit
Bye
7 ~]# ll /var/log/mariadb/mariadb.log
-rw-r----- 1 mysql mysql 25934 May 30 18:50 /var/log/mariadb/mariadb.log
3.3、通⽤⽇志
通用日志:记录对数据库的通用操作,包括错误的SQL语句
文件:file,默认值
表:table
通用日志相关设置
general_log=ON|OFF
general_log_file=HOSTNAME.log
log_output=TABLE|FILE|NONE
【例26】通⽤⽇志
临时启动
7 ~]# mysql
MariaDB [(none)]> show global variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log | OFF |
+---------------+-------+
1 row in set (0.00 sec)
MariaDB [(none)]> set global general_log=on;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> show global variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log | ON |
+---------------+-------+
1 row in set (0.00 sec)
主机名+log
[root@centos7 ~]# ll /var/lib/mysql/
-rw-rw---- 1 mysql mysql 273 May 30 18:55 centos7.log #主机名+log
永久启动
7 ~]# vim /etc/my.cnf
[mysqld]
general_log
7 ~]# systemctl restart mariadb
7 ~]# mysql
MariaDB [(none)]> show global variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log | ON |
+---------------+-------+
1 row in set (0.00 sec)
跟踪通⽤⽇志:每⼀步,操作都有
7 ~]# tail -f /var/lib/mysql/centos7.log
2 Query select @@version_comment limit 1
220530 18:59:31 2 Query show global variables like 'general_log'
【例27】把通⽤⽇志写在表中
7 ~]# vim /etc/my.cnf
[mysqld]
general_log
log_output=TABLE
7 ~]# systemctl restart mariadb
7 ~]# mysql mysql
MariaDB [mysql]> select * from general_log;
+----------------------------+-----------------------------------+-----------+-----------+--------------+---------------------------------------------+
| event_time | user_host | thread_id | server_id | command_type | argument |
+----------------------------+-----------------------------------+-----------+-----------+--------------+---------------------------------------------+
...
| 2022-05-30 19:05:58.800235 | root[root] @ localhost [] | 2 | 0 | Query | select @@version_comment limit 1 |
| 2022-05-30 19:06:16.988863 | root[root] @ localhost [] | 2 | 0 | Query | select * from general_log |
+----------------------------+-----------------------------------+-----------+-----------+--------------+---------------------------------------------+
31 rows in set (0.00 sec)
3.4、慢查询⽇志
慢查询日志:记录执行查询时长超出指定时长的操作
slow_query_log=ON|OFF 开启或关闭慢查询
long_query_time=N 慢查询的阀值,单位秒
slow_query_log_file=HOSTNAME-slow.log 慢查询日志文件
log_slow_filter = admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,
tmp_table_on_disk 上述查询类型且查询时长超过long_query_time,则记录日志
log_queries_not_using_indexes=ON 不使用索引或使用全索引扫描,不论是否达到慢查询阀值的语句是否
记录日志,默认OFF,即不记录
log_slow_rate_limit = 1 多少次查询才记录,mariadb特有
log_slow_verbosity= Query_plan,explain 记录内容
log_slow_queries = OFF 同slow_query_log 新版已废弃
【例28】慢查询⽇志,默认关闭
临时启⽤
MariaDB [mysql]> show global variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | OFF |
+----------------+-------+
1 row in set (0.00 sec)
MariaDB [mysql]> set global slow_query_log=on;
Query OK, 0 rows affected (0.00 sec)
MariaDB [mysql]> show global variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | ON |
+----------------+-------+
1 row in set (0.00 sec)
⽣成慢查询⽇志
7 ~]# ll /var/lib/mysql/
-rw-rw---- 1 mysql mysql 176 May 30 19:16 centos7-slow.log
慢查询⽇志的默认超时时间10秒
7 ~]# mysqladmin variables |grep ong_query_time
| long_query_time | 10.000000
永久启⽤
7 ~]# vim /etc/my.cnf
[mysqld]
slow_query_log
long_query_time=1
7 ~]# systemctl restart mariadb
7 ~]# mysql
MariaDB [(none)]> show global variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | ON |
+----------------+-------+
1 row in set (0.00 sec)
MariaDB [(none)]> use hellodb;
MariaDB [hellodb]> select tid,sleep(1) from teachers;
+-----+----------+
| tid | sleep(1) |
+-----+----------+
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
+-----+----------+
4 rows in set (4.03 sec)
记录进⼊⽇志
7 ~]# cat /var/lib/mysql/centos7-slow.log
/usr/libexec/mysqld, Version: 5.5.60-MariaDB (MariaDB Server). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
/usr/libexec/mysqld, Version: 5.5.60-MariaDB (MariaDB Server). started with:
Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 220530 19:21:45
# User@Host: root[root] @ localhost []
# Thread_id: 2 Schema: hellodb QC_hit: No
# Query_time: 4.030022 Lock_time: 0.000117 Rows_sent: 4 Rows_examined: 4
use hellodb;
SET timestamp=1653909705;
select tid,sleep(1) from teachers;
【例29】慢查询⽇志,只要不⽤索引就计⼊慢查询⽇志
7 ~]# vim /etc/my.cnf
[mysqld]
log_queries_not_using_indexes
slow_query_log
long_query_time=1
7 ~]# systemctl restart mariadb
7 ~]# mysql hellodb
MariaDB [hellodb]> show global variables like 'log_queries_not_using_indexes';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | ON |
+-------------------------------+-------+
1 row in set (0.00 sec)
MariaDB [hellodb]> select * from students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
...
7 ~]# cat /var/lib/mysql/centos7-slow.log
/usr/libexec/mysqld, Version: 5.5.60-MariaDB (MariaDB Server). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
/usr/libexec/mysqld, Version: 5.5.60-MariaDB (MariaDB Server). started with:
Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 220530 19:21:45
# User@Host: root[root] @ localhost []
# Thread_id: 2 Schema: hellodb QC_hit: No
# Query_time: 4.030022 Lock_time: 0.000117 Rows_sent: 4 Rows_examined: 4
use hellodb;
SET timestamp=1653909705;
select tid,sleep(1) from teachers;
/usr/libexec/mysqld, Version: 5.5.60-MariaDB (MariaDB Server). started with:
Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 220530 19:30:37
# User@Host: root[root] @ localhost []
# Thread_id: 2 Schema: hellodb QC_hit: No
# Query_time: 0.000200 Lock_time: 0.000067 Rows_sent: 28 Rows_examined: 28
use hellodb;
SET timestamp=1653910237;
select * from students;
3.5、⼆进制⽇志
二进制日志:记录导致数据改变或潜在导致数据改变的SQL语句
记录已提交的日志
不依赖于存储引擎类型
功能:通过“重放”日志文件中的事件来生成数据副本
注意:建议二进制日志和数据文件分开存放
中继日志:relay log
主从复制架构中,从服务器用于保存从主服务器的二进制日志中读取的事件
二进制日志记录三种格式
基于“语句”记录:statement,记录语句,默认模式
基于“行”记录:row,记录数据,日志量较大
混合模式:mixed, 让系统自行判定该基于哪种方式进行
格式配置
show variables like ‘binlog_format';
二进制日志文件的构成
有两类文件
日志文件:mysql|mariadb-bin.文件名后缀,二进制格式 如: mariadb-bin.000001
索引文件:mysql|mariadb-bin.index,文本格式
二进制日志相关的服务器变量:
sql_log_bin=ON|OFF:是否记录二进制日志,默认ON
log_bin=/PATH/BIN_LOG_FILE:指定文件位置;默认OFF,表示不启用二进制日志功能,上述两项都开启才可
binlog_format=STATEMENT|ROW|MIXED:二进制日志记录的格式,默认STATEMENT
max_binlog_size=1073741824:单个二进制日志文件的最大体积,到达最大值会自动滚动,默认为1G
说明:文件达到上限时的大小未必为指定的精确值
sync_binlog=1|0:设定是否启动二进制日志即时同步磁盘功能,默认0,由操作系统负责同步日志到磁盘
expire_logs_days=N:二进制日志可以自动删除的天数。 默认为0,即不自动删除
二进制日志相关配置
查看mariadb自行管理使用中的二进制日志文件列表,及大小 SHOW {BINARY | MASTER} LOGS
查看使用中的二进制日志文件 SHOW MASTER STATUS
查看二进制文件中的指定内容
SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
show binlog events in ‘mysql-bin.000001' from 6516 limit 2,3
【例30】可以⽤shell脚本操作mysql数据库,使⽤mysql的-e参数可以执⾏各种sql的(创建,删除,增,删,改、查)等各种操作 。在mysql外删除数据库hellodb。
[root@centos7 ~]# ll /var/lib/mysql/
total 28708
-rw-rw---- 1 mysql mysql 16384 May 30 19:29 aria_log.00000001
-rw-rw---- 1 mysql mysql 52 May 30 19:29 aria_log_control
-rw-rw---- 1 mysql mysql 1182 May 30 19:05 centos7.log
-rw-rw---- 1 mysql mysql 1027 May 30 19:30 centos7-slow.log
drwx------ 2 mysql mysql 150 May 30 01:08 hellodb <--删除此项
-rw-rw---- 1 mysql mysql 18874368 May 30 19:30 ibdata1
-rw-rw---- 1 mysql mysql 5242880 May 30 19:30 ib_logfile0
-rw-rw---- 1 mysql mysql 5242880 May 30 01:05 ib_logfile1
drwx------ 2 mysql mysql 4096 May 30 01:05 mysql
srwxrwxrwx 1 mysql mysql 0 May 30 19:29 mysql.sock
drwx------ 2 mysql mysql 4096 May 30 01:05 performance_schema
drwx------ 2 mysql mysql 6 May 30 01:05 test
[root@centos7 ~]# mysql -e 'drop database hellodb' #在mysql外删除数据库hellodb。
[root@centos7 ~]# ll /var/lib/mysql/ #发现刚刚的'hellodb'已删除
total 28708
-rw-rw---- 1 mysql mysql 16384 May 30 19:29 aria_log.00000001
-rw-rw---- 1 mysql mysql 52 May 30 19:29 aria_log_control
-rw-rw---- 1 mysql mysql 1182 May 30 19:05 centos7.log
-rw-rw---- 1 mysql mysql 1027 May 30 19:30 centos7-slow.log
-rw-rw---- 1 mysql mysql 18874368 May 30 19:30 ibdata1
-rw-rw---- 1 mysql mysql 5242880 May 30 19:41 ib_logfile0
-rw-rw---- 1 mysql mysql 5242880 May 30 01:05 ib_logfile1
drwx------ 2 mysql mysql 4096 May 30 01:05 mysql
srwxrwxrwx 1 mysql mysql 0 May 30 19:29 mysql.sock
drwx------ 2 mysql mysql 4096 May 30 01:05 performance_schema
drwx------ 2 mysql mysql 6 May 30 01:05 test
【例31】每个表的结构和数据分开存放,10版本以上默认。
7 ~]# vim /etc/my.cnf
[mysqld]
innodb_file_per_table
7 ~]# systemctl restart mariadb
导⼊数据库
7 ~]# mysql < hellodb_innodb.sql
.frm为表结构⽂件,.ibd为表数据⽂件。
7 ~]# ll /var/lib/mysql/hellodb/
total 1432
-rw-rw---- 1 mysql mysql 8636 May 30 19:49 classes.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 classes.ibd
-rw-rw---- 1 mysql mysql 8630 May 30 19:49 coc.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 coc.ibd
-rw-rw---- 1 mysql mysql 8602 May 30 19:49 courses.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 courses.ibd
-rw-rw---- 1 mysql mysql 61 May 30 19:49 db.opt
-rw-rw---- 1 mysql mysql 8658 May 30 19:49 scores.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 scores.ibd
-rw-rw---- 1 mysql mysql 8736 May 30 19:49 students.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 students.ibd
-rw-rw---- 1 mysql mysql 8656 May 30 19:49 teachers.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 teachers.ibd
-rw-rw---- 1 mysql mysql 8622 May 30 19:49 toc.frm
-rw-rw---- 1 mysql mysql 98304 May 30 19:49 toc.ibd
【例32】⼆进制⽇志记录格式
7 ~]# mysql hellodb
MariaDB [hellodb]> show global variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)
7 ~]# vim /etc/my.cnf
[mysqld]
binlog_format=row
7 ~]# systemctl restart mariadb
7 ~]# mysql hellodb
MariaDB [hellodb]> show global variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
【例33】⼆进制⽇志,默认没有启⽤
组要同时开启两项:是否记录和指定⽂件位置
MariaDB [hellodb]> show global variables like 'sql_log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin | ON |
+---------------+-------+
1 row in set (0.00 sec)
MariaDB [hellodb]> show global variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | OFF |
+---------------+-------+
1 row in set (0.00 sec)
sql_log_bin,变量⾥可以改,临时禁⽤(还原数据库时)。log_bin只读变量不能改,只能改配置。
MariaDB [hellodb]> set global log_bin=off;
ERROR 1238 (HY000): Variable 'log_bin' is a read only variable
7 ~]# vim /etc/my.cnf
[mysqld]
log_bin
7 ~]# systemctl restart mariadb
7 ~]# ll /var/lib/mysql/
...
-rw-rw---- 1 mysql mysql 245 May 30 20:01 mariadb-bin.000001
-rw-rw---- 1 mysql mysql 21 May 30 20:01 mariadb-bin.index
【例34】建议⼆进制⽇志和数据库⽂件分开存放,提⾼可⽤性
7 ~]# mkdir /data/bin
7 ~]# chown mysql.mysql /data/bin
7 ~]# vim /etc/my.cnf
7 ~]# vim /etc/my.cnf
[mysqld]
log_bin=/data/bin/mysql-bin
7 ~]# systemctl restart mariadb
新的⼆进制⽇志⽣成
7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 245 May 30 20:04 mysql-bin.000001
-rw-rw---- 1 mysql mysql 27 May 30 20:04 mysql-bin.index
7 ~]# cat /data/bin/mysql-bin.index
/data/bin/mysql-bin.000001
【例35】⼆进制⽇志,修改会记录,查看不会修改记录。
7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 245 May 30 20:04 mysql-bin.000001
-rw-rw---- 1 mysql mysql 27 May 30 20:04 mysql-bin.index
7 ~]# mysql
MariaDB [(none)]> grant all on hellodb.* to test@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 377 May 30 20:06 mysql-bin.000001 <--大小377
-rw-rw---- 1 mysql mysql 27 May 30 20:04 mysql-bin.index
7 ~]# mysql
MariaDB [(none)]> select * from hellodb.students; #查看不会修改记录
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
...
7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 377 May 30 20:06 mysql-bin.000001 <--大小377
-rw-rw---- 1 mysql mysql 27 May 30 20:04 mysql-bin.index
7 ~]# mysql
MariaDB [(none)]> insert hellodb.students (stuid,name,age)values(26,'tom',28); #修改、添加一条记录
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> select * from hellodb.students;
...
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
| 26 | tom | 28 | F | NULL | NULL |
+-------+---------------+-----+--------+---------+-----------+
26 rows in set (0.00 sec)
7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 586 May 30 20:10 mysql-bin.000001 <--修改会记录、发现文件大小从之前的'377'变成'586'
-rw-rw---- 1 mysql mysql 27 May 30 20:04 mysql-bin.index
【例36】⼆进制⽇志的⼤⼩,单个⼆进制⽇志⽂件的最⼤体积,到达最⼤值会⾃动滚动,默认为1G。
MariaDB [(none)]> show global variables like 'max_binlog_size';
+-----------------+------------+
| Variable_name | Value |
+-----------------+------------+
| max_binlog_size | 1073741824 |
+-----------------+------------+
1 row in set (0.00 sec)
【例37】查看⼆进制⽇志。
MariaDB [(none)]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 586 |
+------------------+-----------+
1 row in set (0.00 sec)
MariaDB [(none)]> show binlog events in 'mysql-bin.000001';
+------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 1 | 245 | Server ver: 5.5.60-MariaDB, Binlog ver: 4 |
| mysql-bin.000001 | 245 | Query | 1 | 377 | grant all on hellodb.* to test@'%' identified by '123456' |
| mysql-bin.000001 | 377 | Query | 1 | 441 | BEGIN |
| mysql-bin.000001 | 441 | Query | 1 | 559 | insert hellodb.students (stuid,name,age)values(26,'tom',28) |
| mysql-bin.000001 | 559 | Xid | 1 | 586 | COMMIT /* xid=12 */ |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------------------------+
5 rows in set (0.00 sec)
MariaDB [(none)]> show binlog events in 'mysql-bin.000001' from 441;
+------------------+-----+------------+-----------+-------------+-------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+------------+-----------+-------------+-------------------------------------------------------------+
| mysql-bin.000001 | 441 | Query | 1 | 559 | insert hellodb.students (stuid,name,age)values(26,'tom',28) |
| mysql-bin.000001 | 559 | Xid | 1 | 586 | COMMIT /* xid=12 */ |
+------------------+-----+------------+-----------+-------------+-------------------------------------------------------------+
2 rows in set (0.00 sec)
【例38】重启数据库,会⾃动⽣成新的⼆进制⽂件
[root@centos7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 586 May 30 20:10 mysql-bin.000001
-rw-rw---- 1 mysql mysql 27 May 30 20:04 mysql-bin.index
[root@centos7 ~]# systemctl restart mariadb
[root@centos7 ~]# ll /data/bin
total 12
-rw-rw---- 1 mysql mysql 605 May 30 20:24 mysql-bin.000001
-rw-rw---- 1 mysql mysql 245 May 30 20:24 mysql-bin.000002 <--⽣成新的⼆进制⽂件
-rw-rw---- 1 mysql mysql 54 May 30 20:24 mysql-bin.index
【例39】⽣成⼤⽂件,⼆进制⽂件变得巨⼤,testlog.sql
7 ~]# mysql hellodb < testlog.sql
执⾏前,⽂件⼤⼩
[root@centos7 ~]# du -sh /data/bin
12K /data/bin
[root@centos7 ~]# du -sh /var/lib/mysql/
30M /var/lib/mysql/
[root@centos7 ~]# mysql hellodb
MariaDB [hellodb]> call pro_testlog();
Query OK, 1 row affected, 3 warnings (20.95 sec)
MariaDB [hellodb]> select count(*) from testlog;
+----------+
| count(*) |
+----------+
| 100000 |
+----------+
1 row in set (0.08 sec)
执⾏后,⽂件⼤⼩
7 ~]# du -sh /data/bin
60M /data/bin
7 ~]# du -sh /var/lib/mysql/
38M /var/lib/mysql/
7 ~]# ll /data/bin
total 61176
-rw-rw---- 1 mysql mysql 605 May 30 20:24 mysql-bin.000001
-rw-rw---- 1 mysql mysql 29078480 May 30 20:33 mysql-bin.000002
-rw-rw---- 1 mysql mysql 81 May 31 00:47 mysql-bin.index
3.6、mysqlbinlog:⼆进制⽇志的客户端命令⼯具
命令格式:
mysqlbinlog [OPTIONS] log_file…
--start-position=# 指定开始位置
--stop-position=#
--start-datetime=
--stop-datetime=
时间格式:YYYY-MM-DD hh:mm:ss
--base64-output[=name]
-v -vvv
清除指定二进制日志:
PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
示例:
PURGE BINARY LOGS TO ‘mariadb-bin.000003’;删除3之前的日志
PURGE BINARY LOGS BEFORE '2017-01-23';
PURGE BINARY LOGS BEFORE '2017-03-22 09:25:30';
删除所有二进制日志,index文件重新记数
RESET MASTER [TO #]; 删除所有二进制日志文件,并重新生成日志文件,文件名从#开始记数,默认从1开
始,一般是master主机第一次启动时执行,MariaDB10.1.6开始支持TO #
切换日志文件:
FLUSH LOGS;
【例40】mysqlbinlog:⼆进制⽇志的客户端命令⼯具。-v查看,解密的命令。
7 ~]# mysqlbinlog /data/bin/mysql-bin.000001
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#220530 20:04:57 server id 1 end_log_pos 245 Start: binlog v 4, server v 5.5.60-MariaDB created 220530 20:04:57 at startup
ROLLBACK/*!*/;
...
# at 559
#220530 20:10:56 server id 1 end_log_pos 586 Xid = 12
COMMIT/*!*/;
# at 586
#220530 20:24:33 server id 1 end_log_pos 605 Stop
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
【例41】查看指定的⼆进制命令
看mysql-bin.000002⾥的全部内容
7 ~]# mysqlbinlog /data/bin/mysql-bin.000002 -v
查看指定的⼆进制命令
#查看'/data/bin/mysql-bin.000002'文件、开始位置'29078160'、结束位置'29078453'
7 ~]# mysqlbinlog --start-position=29078160 --stop-position=29078453 /data/bin/mysql-bin.000002 -v
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#220530 20:24:40 server id 1 end_log_pos 245 Start: binlog v 4, server v 5.5.60-MariaDB created 220530 20:24:40 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
iLeUYg8BAAAA8QAAAPUAAAABAAQANS41LjYwLU1hcmlhREIAbG9nAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACIt5RiEzgNAAgAEgAEBAQEEgAA2QAEGggAAAAICAgCAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAw/a44w==
'/*!*/;
# at 29078160
#220530 20:33:23 server id 1 end_log_pos 29078187 Xid = 300016
COMMIT/*!*/;
# at 29078187
#220530 20:33:23 server id 1 end_log_pos 29078258 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1653914003/*!*/;
SET @@session.pseudo_thread_id=3/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 29078258
#220530 20:33:23 server id 1 end_log_pos 29078286 Intvar
SET INSERT_ID=100000/*!*/;
# at 29078286
#220530 20:33:23 server id 1 end_log_pos 29078453 Query thread_id=3 exec_time=0 error_code=0
use `hellodb`/*!*/;
SET TIMESTAMP=1653914003/*!*/;
insert into testlog(name,age) values (concat('wang', NAME_CONST('i',100000)), NAME_CONST('i',100000))
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
可以导出,恢复数据库⽤
7 ~]# mysqlbinlog --start-position=29078160 --stop-position=29078453 /data/bin/mysql-bin.000002 > a.sql
【例42】清理⼆进制⽇志⽂件命令
MariaDB [hellodb]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 605 |
| mysql-bin.000002 | 29078480 |
+------------------+-----------+
2 rows in set (0.00 sec)
MariaDB [hellodb]> flush logs;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 605 |
| mysql-bin.000002 | 29078480 |
| mysql-bin.000003 | 245 |
+------------------+-----------+
3 rows in set (0.00 sec)
删除3之前的
MariaDB [hellodb]> PURGE BINARY LOGS TO 'mysql-bin.000003';
Query OK, 0 rows affected (0.01 sec)
MariaDB [hellodb]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000003 | 245 |
+------------------+-----------+
1 row in set (0.00 sec)
真的删除了
7 ~]# ll /data/bin
total 8
-rw-rw---- 1 mysql mysql 245 May 31 01:12 mysql-bin.000003
-rw-rw---- 1 mysql mysql 27 May 31 01:13 mysql-bin.index
【例43】并重新⽣成⽇志⽂件,做主从复试时需要⽤到!10.1版本以上可以指定从哪⾥开始。
MariaDB [hellodb]> reset master;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 245 |
+------------------+-----------+
1 row in set (0.00 sec)
在数据库外,刷新
7 ~]# ll /data/bin/
total 8
-rw-rw---- 1 mysql mysql 245 May 31 01:15 mysql-bin.000001
-rw-rw---- 1 mysql mysql 27 May 31 01:15 mysql-bin.index
7 ~]# mysqladmin flush-logs
7 ~]# ll /data/bin/
total 16
-rw-rw---- 1 mysql mysql 245 May 31 01:17 mysql-bin.000001
-rw-rw---- 1 mysql mysql 288 May 31 01:18 mysql-bin.000002
-rw-rw---- 1 mysql mysql 81 May 31 01:18 mysql-bin.index