InnoDB 存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比 MyISAM的存储引擎,InnoDB 写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
存储方式 InnoDB 存储表和索引有以下两种方式。
使用共享表空间存储,这种方式创建的表的表结构保存在数据库的库目录.frm 文件中,数据和索引保存在数据库的家目录的ibdata中,定义的表空间中,可以是多个文件。
使用多表空间存储,这种方式创建的表的表结构仍然保存在.frm 文件中,但是每个表的数据和索引单独保存在.ibd 中,和共享项表不同的是ibd文件和frm一起在库文件夹中和myisam引擎一样。如果是个分区表,则每个分区对应单独的.ibd文件,文件名是“表名+分区名”,可以在创建分区的时候指定每个分区的数据文件的位置,以此来将表的 IO 均匀分布在多个磁盘上。
要使用多表空间的存储方式,需要设置innodb_file_per_table参数,对于新建的表按照多表空间的方式创建,已有的表仍然使用共享表空间存储。如果将已有的多表空间方式修改回共享表空间的方式,则新建表会在共享表空间中创建,但已有的多表空间的表仍然保存原来的访问方式。所以多表空间的参数生效后,只对新建的表生效。
注意:无论是多表还是共享表储存,ibdata都是非常重要的文件。它分为三个部分
1.数据查找部分 2.数据保存部分 3.回滚保存部分
数据查找部分会查看所有的表,会看你是多表保存还是共享表,然后根据这里来决定去哪里寻找表。所以如果没有这个表,就算有多表存储的两个文件,也会在查找的时候显示表不存在,仅仅是show tables 的时候会显示有表。
共享表空间的配置:
在配置共享表空间的情况下,mysql数据目录下会有一个文件ibdata1,而且随着数据的增多,持续增加,
数据库的删除操作并不会缩减ibdata1的容量。
这是由于my.cnf的配置:
innodb_data_file_path = ibdata1:10M:autoextend
配置说明,innodb共享表空间文件是ibdata1,并且初始设置10M空间,当表空间不足时自动扩张
这样就会导致一个问题,当越来越多的数据增加的时候,ibdata也会持续膨胀,有的达到几十G,上百G
那么,当前存储数据的磁盘分区满的时候,要怎么样去扩展数据空间呢?
可以进行如下配置:
例,新增的数据空间分区为/new_data
那么可以新增一个新的共享表空间文件,指向新分区
innodb_data_file_path = ibdata1:60690M;/new_data/ibdata2:10G:autoextend
这样即可制定新表空间文件到/new_data目录下。注意多个表弓箭的话,只有最后一个可以加上自动拓展。
还有一个参数是 innodb_date_home_dir
是共享表空间文件的存放路径,在这个路径后面在跟上path的路径。
事务处理
事务处理是让用户对mysql的各种操作暂时保存在内存中而不直接写入到磁盘中,到用户执行commit提交写入磁盘或者rollback回滚取消内存中的操作才结束事务。
mysql只有innodb才支持事务处理,事务处理有两种进行的方式,一种是修改参数autocommit为false来使影响innodb的操作都要进行事务处理,一个是打开自动提交然后每次通过start transaction来进入一个事务处理的交互,直到commit提交或者rollback回滚才结束这一个事务处理。
查看变量可以发现自动提交是打开的。这时候的操作会自动提交
插入数据之后切换终端发现也是存在的说明已经修改了磁盘。
这里可以观察到打开了事务处理之后
插入数据虽然自己显示表已经有但是切换终端发现并没有写入磁盘。
当我们提交的时候可以发现另一个终端已经有了
我们尝试修改参数来进行实验
另一个终端是没有这个数据的 但是自己是有的
我们吧他回滚操作 会发现又没有了 说明写入内存的数据被清除
再来介绍事务处理的savepoint
类似与游戏中的保存进度,我们对没有提交的事务进行保存
定义三个断点。
回滚到某个断点
如果没设置to 直接全部回滚 commit则全部写入。
两个注意点
1.任何对表结构数据库做的修改都会提交之前的所有事务处理
类似于 alter table , create index / drop index
drop table , lock table , start transaction
2.如果关闭客户端,事务处理全部回滚,不考虑正常或者不正常的退出。
外键约束
删除会共同删除 更改共同更改。
行级锁
表锁:不会出现死锁,发生锁冲突几率高,并发低。
行锁:会出现死锁,发生锁冲突几率低,并发高。
锁冲突:例如说事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。(但是共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)
死锁:例如说两个事务,事务A锁住了15行,同时事务B锁住了610行,此时事务A请求锁住610行,就会阻塞直到事务B施放610行的锁,而随后事务B又请求锁住15行,事务B也阻塞直到事务A释放15行的锁。死锁发生时,会产生Deadlock错误。
锁是对表操作的,所以自然锁住全表的表锁就不会出现死锁。
行锁分 共享锁 和 排它锁。
共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。
排它锁又称:写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。
上共享锁的写法:lock in share mode
例如: select math from zje where math>60 lock in share mode;
上排它锁的写法:for update
例如:select math from zje where math >60 for update;
https://blog.youkuaiyun.com/u014453898/article/details/56068841
会阻塞直到前面锁取消。
无法上其他锁
https://blog.youkuaiyun.com/u014453898/article/details/56068841
事务隔离等级
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
查看事务隔离等级
两个事务之间的隔离关系
实验开两个事务 分别插入和更新来在另一个事务中查看。
https://www.cnblogs.com/huanongying/p/7021555.html
缓存和重做日志
缓存 Innodb_buffer_pool_size 进入数据库之后加载的缓存
重做日志
innodb_mirrored_log_groups 镜像组的数量,默认为1没有镜像
innodb_log_group_home_dir 日志组所在的路径,默认为data的home目录;
innodb_log_files_in_group 日志组的数量,默认为2;
innodb_log_file_size 日志组的大小,默认为5M;
http://blog.itpub.net/29654823/viewspace-2147683/
innodb_log_buffer_size 日志缓冲池的大小,图上为30M; 每个InnDB存储引擎至少有1个重做日志文件组(group),每个文件组下至少有两个重做日志文件,默认的为ib_logfile0、ib_logfile1;
日志组中每个重做日志的大小一致,并循环使用;
InnoDB存储引擎先写重做日志文件,当文件满了的时候,会自动切换到日志文件2,当重做日志文件2也写满时,会再切换到重做日志文件1, 在空闲的时候会慢慢加载到大磁盘中 如果加载完了就会有一个切换点 就可以覆盖原来的文件。
为了保证安全和性能,请设置每个重做日志文件设置镜像,并分配到不同的磁盘上面;
还有一个很重要的参数 innodb_flush_log_at_trx_commit是将事务日志从innodb log buffer写入到redo log中。
有三个参数
0 大约一秒刷新一次
1 每个事务处理提交的时候讲缓存刷新到日志文件中
2 在提交时或者一秒都会刷新一次。