锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算机资源(CPU、RAM、I/O)的争用之外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤为重要,也更加复杂
MySQL中的锁,按照锁的粒度分为以下三类:
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性
为什么全局逻辑备份,就需要加全局锁呢?
1、如果不加全局锁,可能存在的问题
假设数据库中存在这样的三张表:tb_stock库存表,tb_order订单表,tb_orderlog订单日志表
此时备份出来的数据是存在问题的。因为备份出来的数据,tb_stock表与tb_order表的数据不一致(有最新操作的订单信息,但是库存数没减)
此时就可以借助于MySQL的全局锁来解决
2、再来分析一下加了全局锁后的情况
对数据库进行逻辑备份之前,先对整个数据库加上全局锁,一旦加了全局锁之后,其他的ddl、dml全部都处于阻塞状态,但是可以执行DQL语句,也就是只读状态,而数据备份就是查询操作。那么数据在进行逻辑备份的过程中,数据库中的数据就是不会发生变化的,这样就保证了数据的一致性和完整性。
1、加全局锁
flush tables with read lock;
2、数据备份
mysqldump -u用户名 -p密码 demo > demo.sql
3、释放锁
unlock tables;
数据库中加全局锁,是一个比较重的操作,存在以下问题:
在innoDB引擎中,可以在备份时加上参数–single-transaction 参数来完成不加锁得一致性数据备份
mysqldump --single-transaction -u用户名 -p密码 demo > demo.sql
表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中
对于表级锁,主要分为以下三类:
对于表锁,分为两类:
语法:
特点:
1、读锁
左侧为客户端一,对指定表加了读锁,不会影响右侧客户端二的读,但是会阻塞右侧客户端的写
2、写锁
左侧为客户端一,对指定表加了写锁,会阻塞右侧客户端的读和写
注意:读锁不会阻塞其他客户端的读,但是会阻塞写。写锁既会阻塞其他客户的读,又会阻塞其他客户端的写
元数据锁(meta data lock),简写MDL
MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性
也就是说,某一张表涉及到未提交的事务时,是不能够修改这张表的结构的。
常见的SQL操作时,所添加的元数据锁:
对应SQL | 锁类型 | 说明 |
---|---|---|
lock tables xxx read/write | shared_read_only / shared_no_read_write | |
select、select… lock in share mode | shared_read | 与shared_read、shared_write兼容,与exclusive互斥 |
insert、update、delete、select … for update | shared_write | 与shared_read、shared_write兼容,与exclusive互斥 |
alter table … | exclusive | 与其他的mdl都互斥 |
为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查
加入没有意向锁,客户端一对表加了行锁后,客户端二如何给表加表锁呢?
首先客户端一,开启了一个事务,然后执行DML操作,在执行DML语句时,会对涉及到的行加行锁
当客户端二,想对这张表加表锁时,会检查当前表是否有对应的行锁,如果没有,则添加表锁,此时就会从第一行数据,检查到最后一行数据,效率较低
有了意向锁之后:
客户端一,在执行DML操作时,会对涉及的行加行锁,同时也会对该表加上意向锁
而其他客户端,在对这张表加表锁的时候,会根据该表上所加的意向锁来判定是否可以成功加表锁,而不用逐行判断行锁情况
一旦事务提交了,意向共享锁、意向排他锁,都会自动释放
可以通过以下SQL,查看意向锁及行锁的加锁情况:
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from
performance_schema.data_locks;
演示:
1、意向共享锁与表读锁是兼容的
2、意向排他锁与表读、写锁都是互斥的
行级锁,每次操作锁对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中
InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级锁,主要分为以下三类:
InnoDB实现了以下两种类型的行锁:
两种锁的兼容情况如下:
常见的SQL语句,在执行时,所加的行锁如下:
SQL | 行锁类型 | 说明 |
---|---|---|
insert … | 排他锁 | 自动加锁 |
update … | 排他锁 | 自动加锁 |
delete … | 排他锁 | 自动加锁 |
select(正常) | 不加任何锁 | |
select … lock in share mode | 共享锁 | 需要手动在select之后加lock in share mode |
select … for update | 排他锁 | 需要手动在select之后加for update |
默认情况下,InnoDB在REPEATABLE READ事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读
可以通过以下sql,查看意向锁及行锁的加锁情况:
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from
performance_schema.data_locks;
示例:
CREATE TABLE `stu` (
`id` int NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int NOT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4;
INSERT INTO `stu` VALUES (1, 'tom', 1);
INSERT INTO `stu` VALUES (3, 'cat', 3);
INSERT INTO `stu` VALUES (8, 'rose', 8);
INSERT INTO `stu` VALUES (11, 'jetty', 11);
INSERT INTO `stu` VALUES (19, 'lily', 19);
INSERT INTO `stu` VALUES (25, 'luci', 25);
1、普通的select语句,执行时,不会加锁
select * from stu where id = 1;
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from
performance_schema.data_locks;
2、select… lock in share mode,加共享锁,共享锁与共享锁之间兼容
客户端一获取的是id为1这行的共享锁,客户端二是可以获取id为3这行的排他锁的,因为不是同一行数据,而如果客户端二想要获取id为1这行的排他锁,会处于阻塞状态,因为共享锁和排他锁之间互斥
3、排他锁与排他锁之间互斥
begin;
update stu set name = 'lei' where name = 'lily';
commit;
begin;
update stu set name = 'php' where id = 19;
commit;
当客户端一执行update语句,会为id为1的记录加排他锁;客户端二如果也执行update语句更新id为1的数据,也要为id为1的数据加排他锁,但是客户端二会处于阻塞状态,因为排他锁之间是互斥的。直到客户端一,把事务提交了,才会把这一行的行锁释放,此时客户端二,解除阻塞。
默认情况下,InnoDB在REPETABLE READ事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读
注意:间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一个间隙上采用间隙锁
1、表空间
表空间是InnoDB存储引擎逻辑结构的最高层,如果用户启用了参数innoDB_file_per_table,则每张表都会有一个表空间(xxx.ibd),一个mysql实例可以对应多个表空间,用于存储记录,索引等数据
2、段
段,分为数据段(Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollback segment),InnoDB是索引组织表,数据段就是B+数的叶子节点,索引段即为B+树的非叶子节点。段用来管理多个Extent(区)
3、区
区、表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16k,即一个区中一共有64个连续的页
4、页
页、是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16kb,为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区
5、行
行,InnoDB存储引擎数据是按行进行存放的
在行中,默认有两个隐藏字段:
MySQL5.5版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。
下面是InnoDB架构图,左侧为内存结构,右侧为磁盘结构
在左侧的内存结构中,主要分为四大块:Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer。接下来介绍一下这四个部分
InnoDB存储引擎基于磁盘文件存储,访问物理硬盘和在内存中进行访问,速度相差很大,为了尽可能弥补这两者之间的I/O效率的差值,就需要把经常使用的数据加载到缓冲池中,避免每次访问都进行磁盘I/O
在InnoDB的缓冲池中不仅缓存了索引页和数据页,还包含了undo页、插入缓存、自适应哈希索引以及InnoDB的锁信息等等
缓冲池Buffer Pool,是主内存中的一个区域,里面可以缓存磁盘上经常操作的真是数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度
缓冲池以page页为单位,底层采用链表数据结构管理page。根据状态,将page分为三种类型:
在专用服务器上,通常将多大80%的物理内存分配给缓冲池。参数设置为:show variables like ‘innodb_buffer_pool_size’;
Change Buffer,更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据page没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区Change Buffer中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,在将合并后的数据刷新到磁盘中,Change Buffer的意义是什么呢?
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了ChangeBuffer之后,可以在缓冲池中进行合并处理,减少磁盘IO
自适应hash索引,用于优化对Buffer Pool数据的查询。mysql的InnoDB引擎中虽然没有直接支持hash索引,但是提供了一个功能就是这个自适应hash索引。hash索引在进行等值匹配时,一般性能要高于B+树的,因为hash索引一般只需要一次IO即可,而B+树,可能需要几次匹配,所以hash索引的效率要高,但是hash索引又不适合做范围查询、模糊匹配等
InnoDB存储引擎会监控对表上个索引页的查询,如果观察到在特定的条件下hash索引可以提升速度,则建立hash索引,称之为自适应hash索引
自适应索引,无需人工干预,是系统根据情况自动完成
参数:adaptive_hash_index
Log Buffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log、undo log),默认大小为16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘I/O
参数:
innodb_log_buffer_size:缓冲区大小
innodb_flush_log_at_trx_commit:日志刷新到磁盘时机,取值主要包含以下三个:
1:日志在每次事务提交时写入并刷新到磁盘,默认值
0:每秒将日志写入并刷新到磁盘一次
2:日志在每次事务提交后写入,并每秒刷新到磁盘一次
系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据(在MySQL5.x版本中还包含InnoDB数据字典、undolog等)
参数:innodb_date_file_path
系统表空间,默认的文件名叫ibdatal
如果开启了innodb_file_per_table开关,则每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中
开关参数:innodb_file_per_table,该参数默认开启
也就是说,每创建一个表,都会产生一个表空间文件。
通用表空间,需要通过CREATE TABLESPACE语法创建通用表空间,在创建表时,可以指定该表空间
1、创建表空间
create tablespace ts_name add datafile 'file_name' engine = engine_name;
2、创建表时指定表空间
create table xxx ... tablespace ts_name;
撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(初始化为16M),用于存储undo log日志
InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据
双写缓冲区,innodb引擎将数据页从buffer pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据
重做日志,用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者是在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中,用于刷新脏页到磁盘时,发生错误时,进行数据恢复使用
在innodb的后台线程中,分为4类,分别为:Master Thread、IO Thread、Purge Thread、Page Cleaner Thread
核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收
在Innodb存储引擎中大量使用了AIO来处理IO请求,这样可以极大的提高数据库的性能,而IO Thread主要负责这些IO请求得回调
线程类型 | 默认个数 | 职责 |
---|---|---|
Read thread | 4 | 负责读操作 |
Write thread | 4 | 负责写操作 |
Log thread | 1 | 负责将日志缓冲区刷新到磁盘 |
Insert buffer thread | 1 | 负责将写缓冲区内容刷新到磁盘 |
可以通过以下的这条指令,查看到innodb的状态信息,其中就包含IO Thread信息
show engine innodb status \G;
主要用于回收事务已经提交了的undo log,在事务提交之后,undo log可能不用了,就用它来回收
协助Master Thread刷新脏页到磁盘的线程,它可以减轻Master Thread的工作压力,减少阻塞
事务是一组操作的集合,他是不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败
对于这四大特性,实际上分为两个部分。其中原子性、一致性、持久化,实际上是由InnoDB中的两份日志来保证的,一份是redo log日志、一份是undo log日志;而隔离性是通过数据库的锁,加上mvcc来保证的
重做日志,记录的是事务提交时数据页的物理修改,用来是实现事务的持久性
该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是内存中,后者是磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于刷新脏页到磁盘,发生错误时,进行数据恢复使用
如果没有redo log,可能会出现哪些问题?
在InnoDB引擎中的内存结构中,主要的内存区域就是缓冲池,在缓冲池中缓存了很多的数据页。当在一个事务中,执行多个增删改的操作时,InnoDB引擎会先操作缓冲池中的数据,如果缓冲区没有对应的数据,会通过后台线程将磁盘中的数据加载出来,存放在缓冲区中,然后将缓冲池中的数据修改,修改后的数据页为脏页。而脏页则会在一定的时机,通过后台线程刷新到磁盘中,从而保证缓冲区与磁盘的数据一致。而缓冲区的脏页数据并不是实时刷新的,而是一段时间之后将缓冲区的数据刷新到磁盘中,假如刷新到磁盘的过程出错了,而提示给用户事务提交成功,而数据却没有持久化下来,这就出现问题了,没有保证事务的持久性。
那么redo log是如何解决这个问题的?
有了redo log之后,当对缓冲区的数据进行增删改之后,会首先将操作的数据页的变化,记录在redo log buffer中。在事务提交时,会将redo log buffer中的数据刷新到redo log磁盘文件中。过一段时间之后,如果刷新缓冲区的脏页到磁盘时,发生错误,此时就可以借助于redo log进行数据恢复,这样就保证了事务的持久性。而如果脏页成功刷新到磁盘或者涉及到的数据已经落盘,此时redo log就没有作用了,就可以删除了。所以存在的两个redo log文件是循环写的
那为什么每一次提交事务,要刷新redo log到磁盘中呢,而不是直接将buffer pool中的脏页刷新到磁盘中呢?
因为在业务操作中,操作数据一般都是随机读写磁盘的,而不是顺序读写磁盘。而redo log在往磁盘文件中写入数据,由于是日志文件,所以都是顺序写的。顺序写的效率,要远大于随机写。这种先写日志的方式,称之为WAL(Write-Ahead Logging)
回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚(保证事务的原子性)和MVCC(多版本并发控制)
undo log和redo log记录物理日志不一样,前者是逻辑日志。可以认为当delete一条记录时,undo log会记录一条对应的insert记录,反之亦然;当update一条记录时,它会记录一条对应相反的update记录;当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚
undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC
undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的rollback segment回滚段中,内部包含1024个undo log segment
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于日常的操作,如:select … lock in share mode(共享锁),select … for update、update、insert、delete(排他锁)都是一种当前读
简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读
全称Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView
当创建了上面这张表之后,在查看表结构的时候,就可以显式的看到这三个字段。实际上除了这三个字段以外,InnoDB还会自动的添加三个隐藏字段及其含义分别是:
隐藏字段 | 含义 |
---|---|
DB_TRX_ID | 最近修改事务id,记录插入这条记录或最后一次修改该记录的事务id |
DB_ROLL_PTR | 回滚指针,指向这条记录上一版本,用于配合undo log,指向上一个版本 |
DB_ROW_ID | 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段 |
而上述的前两个字段是肯定会添加,是否添加最后一个字段DB_ROW_ID,要看当前表有没有主键,如果有主键,则不会添加隐藏字段
回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志
当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除
而update、delete的时候,产生的undo log日志不仅在回滚的时候需要,在快照读的时候也需要,不会立即删除
有一张表原始数据为:
DB_TRX_ID:代表最近下修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID,是自增的
DB_ROLL_PTR:由于这条数据是才插入的,没有被更新过,所以该字段值为null
然后,有四个并发事务同时在访问这张表
1、第一步
当事务2执行第一条修改语句时,会记录undo log日志,记录数据变更之前得样子;然后更新记录,并且记录本次操作得事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本
2、第二步
当事务3执行第一条修改语句时,也会记录undo log日志,记录数据变更之前得样子;然后更新记录,并且记录本次操作得事务id,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本
3、第三步
当事务4执行第一条修改语句时,也会记录undo log日志,记录数据变更之前的样子;然后更新记录,并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本
最终发现,不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,链表的头部是最近的旧纪录,链表尾部是最早的旧纪录
Readview(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(为提交的)id
ReadView中包含了四个核心字段:
字段 | 含义 |
---|---|
m_ids | 当前活跃的事务id集合 |
min_trx_id | 最小活跃事务ID |
max_trx_id | 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的) |
creator_trx_id | ReadView创建者的事务ID |
而在ReadView中就规定了版本链数据的访问规则:
tx_id代表当前undo log版本链对应事务ID
条件 | 是否可以访问 | 说明 |
---|---|---|
trx_id == creator_trx_id | 可以访问该版本 | 成立,说明数据是当前这个事务更改的 |
trx_id < min_trx_id | 可以访问该版本 | 成立,说明数据已经提交了 |
trx_id > max_trx_id | 不可以访问该版本 | 成立,说明该事务是在ReadVIew生成后才开启的 |
min_trx_id <= trx_id <= max_trx_id | 如果trx_ix不在m_ids中,是可以访问该版本的 | 成立,说明数据已经提交了 |
不同隔离级别,生成ReadView的时机不同:
RC隔离级别下,在事务中每一次执行快照读时生成ReadView
两次快照读读取数据,是如何获取数据的?
在事务5中,查询了两次id为30的记录,由于隔离级别为Read Committed,所以每一次进行快照读都会生成一个ReadView,那么两次生成的ReadView如下:
那么这两次快照读在获取数据时,就需要根据生成的ReadView以及ReadView的版本链访问规则,到undo log版本链中匹配数据,最终决定此次快照读返回的数据
1、第一次快照读具体的读取过程
在进行匹配时,会从undo log的版本链,从上到下进行挨个匹配
先匹配这条记录,这条记录对应的trx_id为4,也就是将4带入右侧的匹配规则中。①不满足 ②不满足 ③不满足 ④也是不满足,都不满足,则继续匹配undo log版本链的下一条
再匹配第二条这条记录对应的trx_id为3,也就是将3带入右侧的匹配规则中。①不满足 ②不满足 ③不满足 ④也是不满足,都不满足,则继续匹配undo log版本链的下一条
再匹配第三条,这条记录对应的trx_id为2,也就是将2带入右侧的匹配规则中。①不满足 ②满足 终止匹配,此次快照读,返回的数据就是版本链中记录的这条数据
2、第二次快照读具体二点读取过程
再进行匹配时,会从undo log的版本链,从上到下进行挨个匹配:
先匹配这条记录,这条记录对应的trx_id为4,也就是将4带入右侧的匹配规则中。①不满足 ②不满足 ③不满足 ④也是不满足,都不满足,则继续匹配undo log版本链的下一条
再匹配第二条这条记录对应的trx_id为3,也就是将3带入右侧的匹配规则中。①不满足 ②满足 终止匹配,此次快照读,返回的数据就是版本链中记录的这条数据
RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。而RR是可重复读,在下一个事务中,执行两次相同的select语句,查询到的结果是一样的
MySQL是如何做到可重复读的呢?
在RR隔离级别下,只是在事务中第一次快照读时生成ReadView,后续都是复用该ReadView,那么既然ReadView都一样,ReadView的版本链匹配规则也一样,那么最终快照读返回的结果也是一样的
所以,MVCC的实现原理就是通过InnoDB表的隐藏字段、undo log版本链、ReadView来实现的。而MVCC+锁,则实现了事务的隔离性。而一致性则是由redolog和undolog保证
MySQL数据库安装完成后,自带了以下四个数据库,具体作用如下:
数据库 | 含义 |
---|---|
mysql | 存储在MySQL服务器正常运行所需要的各种信息(时区、主从、用户、权限等) |
information_schema | 提供了访问数据库元数据的各种表和视图,包含数据库、表、字段类型及访问权限 |
performance_schema | 为MySQL服务器运行时状态提供了一个底层监控功能,主要用于收集数据库服务器性能参数 |
sys | 包含了一系列方便DBA和开发人员利用performance_schema性能数据库进行性能调优和诊断的视图 |
该mysql不是指mysql服务,而是指mysql的客户端工具
语法 :
mysql [options] [database]
选项 :
-u, --user=name #指定用户名
-p, --password[=name] #指定密码
-h, --host=name #指定服务器IP或域名
-P, --port=port #指定连接端口
-e, --execute=name #执行SQL语句并退出
-e选项可以在MySQL客户端执行SQL语句,而不用连接到MySQL数据库再执行,对于一些批处理脚本,这种方式尤其方便
示例:
mysql -uroot –p123456 db01 -e "select * from stu";
mysqladmin是一个执行管理操作的客户端程序,可以用它来检查服务器的配置和当前状态、创建并删除数据库等
通过帮助文档查看选项:
mysqladmin --help
语法:
mysqladmin [options] command ...
选项:
-u, --user=name #指定用户名
-p, --password[=name] #指定密码
-h, --host=name #指定服务器IP或域名
-P, --port=port #指定连接端口
示例:
mysqladmin -uroot –p1234 drop 'test01';
mysqladmin -uroot –p1234 version;
由于服务器生成的二进制日志文件以二进制格式保存,所以如果要检查这些文本的文本格式,就会使用到mysqlbinlog日志管理工具
语法 :
mysqlbinlog [options] log-files1 log-files2 ...
选项 :
-d, --database=name 指定数据库名称,只列出指定的数据库相关操作。
-o, --offset=# 忽略掉日志中的前n行命令。
-r,--result-file=name 将输出的文本格式日志输出到指定文件。
-s, --short-form 显示简单格式, 省略掉一些信息。
--start-datatime=date1 --stop-datetime=date2 指定日期间隔内的所有日志。
--start-position=pos1 --stop-position=pos2 指定位置间隔内的所有日志。
A. 查看 binlog.000008这个二进制文件中的数据信息
mysqlbinlog binlog.000008
简单格式为:
mysqlbinlog -s binlog.000008
mysqlshow客户端对象查找工具,用来很快查找存在哪些数据库、数据库中的表、表中的列或索引
语法 :
mysqlshow [options] [db_name [table_name [col_name]]]
选项 :
--count 显示数据库及表的统计信息(数据库,表 均可以不指定)
-i 显示指定数据库或者指定表的状态信息
示例:
#查询test库中每个表中的字段书,及行数
mysqlshow -uroot -p2143 test --count
#查询test库中book表的详细情况
mysqlshow -uroot -p2143 test book --count
示例:
1、查询每个数据库的表的数量及表中记录的数量
mysqlshow -uroot -p密码 --count
2、查看数据库db01的统计信息
mysqlshow -uroot -p1234 db01 --count
3、查看数据库db01中的course
mysqlshow -uroot -p1234 db01 course --count
4、查看数据库db01中的course表的id字段的信息
mysqlshow -uroot -p1234 db01 course id --count
mysqldump客户端工具用来备份数据库或在不同数据库之间进行数据迁移。本分内容包括创建表,及插入表的sql语句
语法 :
mysqldump [options] db_name [tables]
mysqldump [options] --database/-B db1 [db2 db3...]
mysqldump [options] --all-databases/-A
连接选项 :
-u, --user=name 指定用户名
-p, --password[=name] 指定密码
-h, --host=name 指定服务器ip或域名
-P, --port=# 指定连接端口
输出选项:
--add-drop-database 在每个数据库创建语句前加上 drop database 语句
--add-drop-table 在每个表创建语句前加上 drop table 语句 , 默认开启 ; 不开启 (--skip-add-drop-table)
-n, --no-create-db 不包含数据库的创建语句
-t, --no-create-info 不包含数据表的创建语句
-d --no-data 不包含数据
-T, --tab=name 自动生成两个文件:一个.sql文件,创建表结构的语句;一个.txt文件,数据文件
示例:
1、备份db01数据库
mysqldump -uroot -p1234 db01 > db01.sql
备份出来的数据包括:
2、备份db01数据库中的表的数据,不备份表结构
mysqldump -uroot -p1234 -t db01 > db01.sql
3、将db01数据库的表结构与数据分开备份
mysqldump -uroot -p1234 -T /root db01 score
1、mysqlimport
mysqlimport是客户端数据导入工具,用来导入mysqldump加-T参数后导出来的文本文件
语法 :
mysqlimport [options] db_name textfile1 [textfile2...]
示例 :
mysqlimport -uroot -p2143 test /tmp/city.txt
2、source
如果需要导入sql文件,可以使用mysql中的source指令:
语法 :
source /root/xxxxx.sql