当前位置: 首页 > 后端技术 > PHP

Innodb

时间:2023-03-30 05:56:39 PHP

1。MySQL5.5及以后版本默认的存储引擎为不了解存储引擎的数据库用户提供了极大的便利,因为innodb适用于大多数应用场景。与myisam不同,innodb是一个事务性存储引擎。也就是说,innodb支持事务的acid特性。InnoDB的设计更适合大量的小事务,而且在大多数情况下,小事务可以正常提交,很少回滚。2.Innodb使用表空间进行数据存储2.1关于innodb_file_per_table参数Innodb和mysiam存储数据的方式不同,innodb有自己的表空间概念。表中的数据存储在表空间中,具体表空间由参数innodb_file_per_table决定。ON:为每个innodb表创建一个空间,tablename.ibd(.ibd后缀)OFF:将数据存储在系统的共享表空间,ibdatax(x代表一个数字,从1开始)3.系统表空间和如何选择独立表空间3.1比较3.1.1系统表空间不能简单的缩小文件大小mysql5.6之前的innodb参数-innodb_file_per_table=OFF(默认),即数据会存放在系统表空间默认情况下。默认设置会遇到以下问题:在繁忙的系统中,系统表空间不断增长。不超过我们的磁盘限制是可以接受的,但是一旦我们的磁盘空间不足,为了腾出磁盘空间,我们不得不删除系统中大量的无效数据(比如没有被使用的日志数据)很长一段时间等)。我们删除数据后,系统表空间不会缩小。在这种情况下,我们希望通过复制文件来备份数据库。虽然删除了数据,但是表空间的大小并没有改变,也就是说我们每次删除都浪费了很多空间。不要以为我们不会遇到备份问题。其实最常用的热备份方式就是这样处理的。这时候我们会遇到一些使用系统表空间进行存储的问题。缩小系统表空间的唯一方法是导出系统表空间中的表,删除innodb文件,重启mysql服务器,重建表空间,然后导入数据。这个过程其实是非常复杂和耗时的,这在繁忙的生产环境中显然是不可能的。所以如果我们使用系统表空间来存储表数据,我们面临的问题是我们不能轻易收缩系统文件,导致大量的空间浪费和大量的磁盘碎片,从而降低系统性能。3.1.2独立表空间可以使用optimizetable命令缩减系统文件如果我们使用独立表空间,清理大表的数据后,我们可以很方便的缩表,使用optimizetable命令重建桌子。但是比重建整个系统要快很多,而且不需要重启数据库服务器,甚至不会影响这张表的正常访问。所以从这个角度来说,使用单独的表空间显然要比使用系统表空间好很多。3.1.3系统表空间会产生io瓶颈对于系统表空间来说,只有一个文件。如果同时对多张表进行数据刷新,实际上是在文件系统层面依次进行,所以会存在一定的IO瓶颈。3.1.4独立表空间可以同时刷新数据到多个文件对于独立表空间,每个表都有自己的表空间文件。在写入数据时,可以使用多个文件来增加io处理的性能。所以,对于有普通写操作的系统,不宜使用系统表空间来统一存储数据,而应使用独立的表空间。3.2建议使用独立的表空间来管理使用innodb存储引擎的表。mysql5.6以后,默认使用innodb存储引擎的表配置是一个独立的存储空间。3.3转表步骤将原来存在于系统表空间的表转至独立表空间的方法3.3.1使用mysqldump导出所有数据库表数据如果数据库使用了存储过程、触发器、定时事件等,必须记得一起导出。3.3.2停止mysql服务器,修改参数,删除innodb相关文件停止mysql服务。如果是主从架构,我们可以先从从服务器进行这些操作。停止mysql服务器后,我们需要修改my.cnf文件,增加参数innodb_file_per_table,然后手动删除原innodb系统中的相关数据文件。此时,系统表空间将不包含任何数据。3.3.3重启mysql服务,重建innodb系统表空间导入之前备份的数据完成数据恢复,将原来存在于系统表空间的数据迁移到独立表空间。我们也可以不按照上面的操作。修改系统参数后,重启服务后执行所有需要修改的innodb表:altertabletable_nameengine=innodb;。这样也可以将系统表空间中的表迁移到独立表空间中,但是系统表空间占用的空间是无法恢复的,所以按照上面正规的步骤进行。3.3.5迁移后系统表空间存储的内容我们将系统表空间的数据迁移到独立表空间后,现在系统表空间的内容是什么?答案是虽然我们迁移了系统表数据,但是系统表空间还有一些重要的东西需要存放。其中之一是innodb数据字典信息数据字典是数据对象结构的元数据信息,它存储了与数据库对象相关的信息。如:表、列、索引、内部键等。mysql定义是用.frm文件来存储表结构的,那么.frm文件和系统空间的数据字典有什么区别呢?首先,.frm文件是mysqlserver层生成的文件,可以理解为mysql数据库server层的数据字典,对所有mysql存储引擎都是一样的。mysql数据层保存的东西与存储引擎无关,而InnoDB内部的数据字典是在存储引擎内部生成的,可以保证事务的一定安全性。另外,innodb存储引擎并不直接使用mysql的某些类型的数据,而是自己封装了定义,所以它的数据字典存储了所有引擎相关的内容。最后,.frm文件只是一个简单的二进制文件,通过b-tree管理innodb数据字典。系统表空间中除了innodb数据字典外,还有undo回滚段和innodb临时表两类。在mysql5.7中都可以从系统表中删除,但是很多人会默认存放在系统表空间中。这里要声明的是,mysql5.6已经支持undorollbacksegment的存储了。4.innodb存储引擎的特点4.1Innodb是一个事务型存储引擎完全支持acidfeatureofthings、redolog和undolog。单位是byte,程序每秒都会将缓冲区中的数据刷新到磁盘中,所以缓冲区不需要配置太大。innodb_log_files_in_group:决定了数据库目录下ib_**文件的数量。Undolog有助于回滚未提交的事务,实现多版本并发控制。Contactredolog存储已提交的事务,undolog存储未提交的事务。修改InnoDB表时,不仅会产生redolog,还会产生undolog。如果用户事务失败或者使用了回滚语句,则需要使用undolog中的信息。redolog是顺序写入的,在数据??库允许的情况下不需要读取redolog。undolog需要随机读写。mysql5.6中的undolog可以独立于系统空间存在。如果条件允许,我们可以将undolog存储在固态存储设备上,这样可以获得更好的性能。4.2Innodb支持行级锁不同于myisam支持的表级锁。行级锁的特点是在进行写操作的时候,我们需要锁定的资源更少,这样就可以支持更多的并发。需要注意的是,InnoDB的行级锁是由存储引擎层实现的,而MySQL服务器根本不了解锁在存储引擎中的实现。说到锁,大家可能不太了解。锁在数据库中的作用是什么?因为锁对我们数据库的性能有很大的影响,这里介绍一下什么是锁。很多开发者可能会问,他们经常听到dba提到的各种锁,比如行级锁、表级锁、共享锁、独裁锁等等。这些锁是干什么用的?4.2.1什么是锁?锁是数据库系统不同于文件系统的一个重要特性。锁的主要功能是管理对共享资源的并发访问。并发访问是一件很麻烦的事情。任何在运行环境下运行良好的系统,一旦涉及到并发,就可能会出现各种问题。例如,在邮件系统中,在一个邮箱中,所有的邮件都是一个接一个地堆叠起来,首尾相接。这种结构对于阅读和传递邮件都有很大的好处。当收到新邮件时,只需将其插入文件末尾即可。当有两个用户同时向邮箱投递邮件时会发生什么?很有可能邮箱中的数据会被破坏,两封邮件的内容会出现交集。当然,这可能与我们平时生活中的感受大不相同。那是因为现在的邮箱系统是用锁来控制的。锁确保当一个用户将邮件投递到邮箱时,另一个用户将阻塞并且不能写入同一个文件的末尾。那么锁的另一个作用就是实现事务隔离。前面提到,我们通过redolog和undolog来实现事务的原子性、一致性和持久性,而隔离是需要锁来实现的。被未提交事务锁定的数据不能被其他事务查询。4.2.2锁的常见分类了解了锁的定义和作用之后,我们来看一下锁的常见分类。共享锁(也叫读锁):可见读锁是共享的,不会阻塞。多个线程可以同时读取同一个资源,互不干扰。独占锁(也称为写锁):写锁是排他性的,排他性的,会阻塞其他的写锁和读锁。这是对数据完整性的考虑。只有这样才能保证在给定的时间内只有一个线程可以执行写入,防止其他用户对资源进行读写,这就是我们前面提到的事务隔离。.对于innodb来说,读锁和写锁都是行锁。兼容性指的是同一行记录的可见兼容性根据上面的介绍,请求同一个资源应该是互斥的,但是实际体验和上面的不一样。(锁比上面说的复杂很多)初始化数据库中的数据测试,两个连接启动一个事务。一个连接在表的第一行加了排他锁,另一个连接在不提交事务的情况下获取了带排它锁的数据。这与我们介绍的兼容性情况完全不同。为什么?这是innodb在实现锁方面的独到之处。这里innodb使用的是我们上面提到的undolog中的记录,所以我们在第二次连接中查看到的数据其实就是undolog中存储的版本。也就是说,这不是我们在第一次连接时更新的内容。4.2.3锁粒度锁粒度即锁策略,是指锁定资源的最小单位。比如给一行加锁,最小单位就是行,这个锁就叫做行级锁。如果最小单位是列,则称为列级锁。同样,如果锁的最小单位是表,那么锁的最小单位就是表级锁。表级锁:mysql中最基本的表策略,开销最小,并发度低的策略。表锁在加锁时会锁住整个表。用户在写入表之前需要获得写锁。这样会阻塞其他用户的读写操作。只有在没有写锁的情况下,其他用户才能获得读锁。前面说过,读锁不会互相阻塞。表级锁通常是在mysqlserver层实现的,所以虽然innodb实现了行级锁,但是在某些时候,mysql数据服务层还是会对innodb表加表级锁。实验使用两个连接,一个连接加表级排它锁,第二个连接从表中获取数据,第一个连接执行解锁操作,第二个连接会执行行级锁:可以支持最大程度的并发处理,同时锁比表级锁更昂贵。目前,行级锁在innodb和其他存储引擎中实现。行级锁只在存储引擎实现,在mysql服务层没有实现。4.2.4阻塞与死锁什么是阻塞:阻塞是不同锁之间的兼容关系。在某个时刻,一个事务中的锁需要等待另一个事务中的锁释放其占用的资源,这就形成了阻塞。阻塞是为了保证事务能够并发正常运行,但是当系统中出现大量阻塞时,往往意味着系统出现了问题。可能对频繁更新的表或由于其他管理操作(如表备份)的查询速度很慢。对经常访问的资源加排它锁。太多的阻塞不是一个好现象。会造成数据库中大量的连接堆积,占用大量的系统资源,降低系统的整体性能。什么是死锁:死锁是指两个或多个事务在执行过程中占用了对方正在等待的资源时发生的异常。一个阻塞事务占用阻塞事务的多个资源,死锁是产生一个事务的多个事务互相占用对方的等待资源。这是阻塞和死锁最大的区别。另一个区别是死锁数据库系统会自动发现,并在多个占用资源的事务中,选择一个占用资源最少的事务执行回滚操作。这样其他事务就可以正常运行,死锁就可以由系统自动处理了。如果只有少量死锁,则不会对系统造成任何影响。只要在应用程序中发现死锁,就可以重新处理。但是,如果系统中经常出现大量的死锁,那么就需要引起注意了。通常,可以通过在多个事务中以相同顺序访问所需资源,或者通过添加相关索引来解决死锁。Innodbstatuscheckshowengineinnodbstatus该命令的用法百度5.Innodb适用场景innodb适用于大多数OLTP应用。不管是否需要事务支持,只要不使用innodb不支持的特殊功能,我们就应该在新系统中使用innodb存储引擎。提到的特殊功能可能包括前面介绍的myisam功能中的空间应用和全文索引的应用。由于mysql5.7之前只支持myisam存储引擎,所以如果我们要使用mysql来存储这类应用数据,可能就只能选择myisam存储引擎了。但是这种情况在mysql5.7之后有了改变,innodb支持全文索引和空间功能。所以对于这类应用,我们也可以使用innodb存储引擎进行存储。Innodb和myisam是mysql最常用的两个存储引擎,有些引擎会用到,请听下一章分解。相关文章InnoDB引擎独立表空间innodb_file_per_tableMySQLServer参数优化-innodb_file_per_table(独立表空间)showengineinnodbstatus死锁和阻塞关系解读