MySQL数据库知识学习(四)数据库锁及存储引擎

本文深入解析数据库中的锁机制,涵盖悲观锁、乐观锁、共享锁、排他锁、行锁、表锁、页锁等概念,以及它们在MyISAM和InnoDB存储引擎中的具体实现。同时,探讨了不同锁机制对并发性能的影响,以及如何根据应用场景选择合适的锁策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

           在之前Java并发编程的学习中,我们知道对于共享资源的访问会导致很多并发问题。在数据库中,除了传统的计算资源(CPU、RAM、I/O等等)的争用之外,数据也是一种供许多用户共享访问的资源。如何保证数据并发访问的一致性、有效性,是数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素。

数据库的锁

悲观锁和乐观锁

悲观锁:

顾名思义,很悲观,就是每次拿数据的时候都认为别的线程会修改数据,所以在每次拿的时候都会给数据上锁。上锁之后,当别的线程想要拿数据时,就会阻塞,直到给数据上锁的线程将事务提交或者回滚。传统的关系型数据库里就用到了很多这种锁机制,比如行锁,表锁,共享锁,排他锁等,都是在做操作之前先上锁。   

乐观锁: 

乐观锁其实不会上锁。顾名思义,很乐观,它默认别的线程不会修改数据,所以不会上锁。只是在更新前去判断别的线程在此期间有没有修改数据,如果修改了,会交给业务层去处理。 

乐观锁不是数据库自带的,需要我们自己去实现。常用的实现方式是使用版本戳,例如在一张表中添加一个整型字段version,每更新version++,比如某个时刻version=1,线程A读取了此version=1,线程B也读取了此version=1,当线程A更新数据之前,判断version仍然为1,更新成功,version++变为2,但是当线程B再提交更新时,发现version变为2了,与之前读的version=1不一致,就知道有别的线程更新了数据,这个时候就会进行业务逻辑的处理。 

通常情况下,写操作较少时,使用乐观锁,写操作较多时,使用悲观锁。

共享锁和排他锁

共享锁: 

共享锁又称为读锁,一个线程给数据加上共享锁后,其他线程只能读数据,不能修改。 
   
排他锁: 

排他锁又称为写锁,和共享锁的区别在于,其他线程既不能读也不能修改。 

级别锁

行锁: 

行锁,由字面意思理解,就是给某一行加上锁,也就是一条记录加上锁。如下语句:

SELECT * from city where id = "1"  lock in share mode; 

由于对于city表中,id字段为主键,就也相当于索引。执行加锁时,会将id这个索引为1的记录加上锁,那么这个锁就是行锁。
   
表锁: 

表锁,和行锁相对应,给整个表加上锁。 

页锁: 

行锁锁指定行,表锁锁整张表,页锁是折中实现,即一次锁定相邻的一组记录。 

MySQL的锁

相对于其他的数据库而言,MySQL的锁机制比较简单,最显著的特点就是不同的存储引擎支持不同的锁机制。根据不同的存储引擎,MySQL中锁的特性可以大致归纳如下:

 行锁表锁页锁
MyISAM  
InnoDB 
BDB 

开销、加锁速度、死锁、粒度、并发性能

  • 表锁:开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
  • 行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高
  • 页锁:开销和加锁速度介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般

很难笼统的说哪种锁最好,只能根据具体应用的特点来说哪种锁更加合适。

仅仅从锁的角度来说的话:表锁更适用于以查询为主,只有少量按索引条件更新数据的应用;行锁更适用于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用

MyISAM表锁

MyISAM存储引擎只支持表锁,这也是MySQL开始几个版本中唯一支持的锁类型。随着应用对事务完整性和并发性要求的不断提高,MySQL才开始开发基于事务的存储引擎,后来慢慢出现了支持页锁的BDB存储引擎和支持行锁的InnoDB存储引擎。但是MyISAM的表锁依然是使用最为广泛的锁类型。

MySQL的表级锁有两种模式:表共享锁(Table Read Lock)和表排他锁(Table Write Lock),或称读锁和写锁。

                                        请求锁模式

                      是否兼容

当前锁模式

None读锁写锁
读锁
写锁

可见,对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求,只要有排他锁存在,无论是写操作还是读操作都会被阻塞。

并发插入(Concurrent Inserts)

虽然MyISAM表的串行的,但这是就总体而言的。在一定条件下,MyISAM表也支持查询和插入操作的并发进行。

MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、12

  • 当concurrent_insert设置为0时,不允许并发插入。
  • 当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。
  • 当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。

MyISAM的锁调度

MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的。那么,一个进程请求某个 MyISAM表的读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?

答案是写进程先获得锁不仅如此,即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前!这是因为MySQL认为写请求一般比读请求要重要。这也正是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。这种情况有时可能会变得非常糟糕!幸好我们可以通过一些设置来调节MyISAM 的调度行为。

  1. 通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。
  2. 通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
  3. 通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。
  4. 另外,MySQL也提供了一种折中的办法来调节读写冲突,即给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会。

需要注意的是,一些需要长时间运行的查询操作,也会使写进程“饿死”!因此,应用中应尽量避免出现长时间运行的查询操作,不要总想用一条SELECT语句来解决问题,因为这种看似巧妙的SQL语句,往往比较复杂,执行时间较长,在可能的情况下可以通过使用中间表等措施对SQL语句做一定的“分解”,使每一步查询都能在较短时间完成,从而减少锁冲突。如果复杂查询不可避免,应尽量安排在数据库空闲时段执行,比如一些定期统计可以安排在夜间执行。

InnoDB锁

InnoDB锁问题

InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题,事务的知识详见这篇文章

我们知道事务的由一组SQL语句组成的逻辑处理单元,它具有以下4个属性(ACID):

  • 原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
  • 一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。
  • 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
  • 持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持更多的用户。但并发事务处理也会带来一些问题,主要包括以下几种情况。

  • 更新丢失(Lost Update):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题--最后的更新覆盖了由其他事务所做的更新。例如,两个编辑人员制作了同一文档的电子副本。每个编辑人员独立地更改其副本,然后保存更改后的副本,这样就覆盖了原始文档。最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的更改。如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一文件,则可避免此问题。
  • 脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做"脏读"。
  • 不可重复读(Non-Repeatable Reads):一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”。
  • 幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。

为了避免这些问题,数据库提供一定的事务隔离机制来解决。数据库实现事务隔离的方式,基本上可分为以下两种。

  • 一种是在读取数据前,对其加锁,阻止其他事务对数据进行修改。
  • 另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。

ISO/ANSI SQL92定义了4个事务隔离级别,每个级别的隔离程度不同,允许出现的副作用也不同,应用可以根据自己的业务逻辑要求,通过选择不同的隔离级别来平衡 “隔离”与“并发”的矛盾。

而这些隔离机制的不同功能,显然是通过数据库锁来实现的。

InnoDB锁实现

为了更好的实现隔离机制的功能,InnoDB实现了以下类型的行锁

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
  • 排他锁(X)  :允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

                                   请求锁模式

                   是否兼容

当前锁模式

XIXSIS
X冲突冲突

冲突

冲突
IX冲突兼容冲突兼容
S冲突冲突兼容兼容
IS冲突兼容兼容兼容

如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。意向锁是InnoDB自动加的,不需用户干预。

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。

//共享锁(S)
SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;

//排他锁(X)
SELECT * FROM table_name WHERE ... FOR UPDATE;

InnoDB行锁实现方式

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

所以在实际的应用中,应该尽量使用索引查询,提高并发性能。

需要注意的是,即便在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL通过判断不同执行计划的代价来决定的,如果MySQL认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下InnoDB将使用表锁,而不是行锁。因此,在分析锁冲突时,别忘了检查SQL的执行计划,以确认是否真正使用了索引。

//通过用explain检查两条SQL的执行计划
explain select * from tab_with_index where name = 1;

间隙锁(Next-Key锁)

         当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。

举例来说,假如emp表中只有101条记录,其empid的值分别是 1,2,...,100,101,下面的SQL:

Select * from  emp where empid > 100 for update;

是一个范围条件的检索,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。

很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。

需要注意的是,InnoDB除了通过范围条件加锁时使用间隙锁外,如果使用相等条件请求给一个不存在的记录加锁,InnoDB也会使用间隙锁!比如以上例子中如使用以下SQL也会加间隙锁,因为102是不存在的数据。

select * from emp where empid = 102 for update;

InnoDB不同隔离级别下锁的差异

锁和多版本数据是InnoDB实现一致性读和ISO/ANSI SQL92隔离级别的手段,因此,在不同的隔离级别下,InnoDB处理SQL时采用的一致性读策略和需要的锁是不同的。

                                            隔离级别

               一致性读和锁

SQL

Read UncommitedRead CommitedRepeatable ReadSerializable
SQL条件    
select相等None locksConsisten read/None lockConsisten read/None lockShare locks
范围None locksConsisten read/None lockConsisten read/None lockShare Next-Key
update相等exclusive locksexclusive locksexclusive locksExclusive locks
范围exclusive next-keyexclusive next-keyexclusive next-keyexclusive next-key
InsertN/Aexclusive locksexclusive locksexclusive locksexclusive locks
replace无键冲突exclusive locksexclusive locksexclusive locksexclusive locks
键冲突exclusive next-keyexclusive next-keyexclusive next-keyexclusive next-key
delete相等exclusive locksexclusive locksexclusive locksexclusive locks
范围exclusive next-keyexclusive next-keyexclusive next-keyexclusive next-key
Select ... from ... Lock in share mode相等Share locksShare locksShare locksShare locks
范围Share locksShare locksShare Next-KeyShare Next-Key
Select * from ... For update相等exclusive locksexclusive locksexclusive locksexclusive locks
范围exclusive locksShare locksexclusive next-keyexclusive next-key

Insert into ... Select ...

(指源表锁)

innodb_locks_unsafe_for_binlog=offShare Next-KeyShare Next-KeyShare Next-KeyShare Next-Key
innodb_locks_unsafe_for_binlog=onNone locksConsisten read/None lockConsisten read/None lockShare Next-Key

create table ... Select ...

(指源表锁)

innodb_locks_unsafe_for_binlog=offShare Next-KeyShare Next-KeyShare Next-KeyShare Next-Key
innodb_locks_unsafe_for_binlog=onNone locksConsisten read/None lockConsisten read/None lockShare Next-Key

    从上表可以看出,对于许多SQL,隔离级别越高,InnoDB给记录集加的锁就越严格(尤其是使用范围条件的时候),产生锁冲突的可能性也就越高,从而对并发性事务处理性能的影响也就越大。

InnoDB的默认隔离级别是“可重复读”(REPEATABLE READ)。行锁就可以实现,行锁的锁定使同一事物不同时间SELECT的结果总是事务开始时时间点的状态,即得到的是同样的结果。但无法解决幻读问题,即虽然保证了每次查询同样的条件得到相同的结果的可重复读问题,但却无法保证其他事务不会插入了满足其查询条件的新数据。特别是范围查询中,同样的条件可以查询到之前的结果和满足条件的其他事务插入的新数据,间隙锁就可以解决这样的问题。

因此,我们在应用中,应该尽量使用较低的隔离级别,以减少锁争用的机率。实际上,通过优化事务逻辑,大部分应用使用Read Commited隔离级别就足够了。

死锁

MyISAM表锁是deadlock free的,这是因为MyISAM总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。但在InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,这就决定了在InnoDB中发生死锁是可能的。

最简单的例子就是,事务1和事务2需要对table1和table2都进行操作,但是事务1先操作table1获取table1的排他锁,事务2先操作table2获取table2的排他锁,而接下来两个事务都需要获得对方持有的排他锁才能继续完成事务,这种循环锁等待就是典型的死锁。通常来说,死锁都是应用设计的问题,通过调整业务流程、数据库对象设计、事务大小,以及访问数据库的SQL语句,绝大部分死锁都可以避免。

 

存储引擎

      数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,可以获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是插件式存储引擎

存储引擎一般具有以下作用

  1. 设计并创建数据库以保存系统所需的关系或XML文档。
  2. 实现系统以访问和更改数据库中存储的数据。包括实现网站或使用数据的应用程序,还包括生成使用SQL Server工具和实用工具以使用数据的过程。
  3. 为单位或客户部署实现的系统。
  4. 提供日常管理支持以优化数据库的性能。

MySQL的存储引擎

可通过SHOW ENGINES;语句查看MySQL所支持的存储引擎:

å¨è¿éæå¥å¾çæè¿°

其中Support代表是否支持此引擎,Transactions表示此引擎是否支持事务管理,MySQL默认的是InnoDB引擎。

在MySQL中,不需要在整个服务器中使用同一种存储引擎,针对具体的要求,可以对每一个表使用不同的存储引擎

1、MyISAM存储引擎

MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事务,也不支持行级锁和外键。对于锁的定义稍后会提到。

MyIsam 存储引擎独立于操作系统,也就是可以在windows上使用,也可以比较简单的将数据转移到linux操作系统上去。这种存储引擎在创建表的时候,会创建三个文件,一个是.frm文件用于存储表的定义,一个是.MYD文件用于存储表的数据,另一个是.MYI文件,存储的是索引。操作系统对大文件的操作是比较慢的,这样将表分为三个文件,那么.MYD这个文件单独来存放数据自然可以优化数据库的查询等操作。

适用场景:

  • 不支持事务的设计,但是并不代表着有事务操作的项目不能用MyIsam存储引擎,可以在service层进行根据自己的业务需求进行相应的控制。
  • 不支持外键的表设计。
  • 查询速度很快,如果数据库insert和update的操作比较多的话采用表级锁效率低(建议使用innodb)
  • 整天 对表进行加锁的场景。
  • MyISAM极度强调快速读取操作。
  • MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。

2、InnoDB存储引擎

InnoDB是一个事务型的存储引擎,有行级锁定和外键约束,它是MySQL的默认存储引擎。

Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别,关于数据库事务与其隔离级别的内容请见这篇文章。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。

但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。

但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。如下:

//这个就是select锁表的一种,不明确主键。增删改查都可能会导致锁全表。
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;

适用场景:

  1. 更新多的表,适合处理多重并发的更新请求。
  2. 支持事务。
  3. 可以从灾难中恢复(通过bin-log日志等)。
  4. 外键约束。只有他支持外键。
  5. 支持自动增加列属性auto_increment

3、MyISAM与InnoDB引擎对比

效果对比:

1)事务

MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持,提供事务支持已经外部键等高级数据库功能。

InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “a%”

就是说在不确定的范围时,InnoDB还是会锁表的。

2)性能主题

MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快。

3)行数保存

InnoDB 中不保存表的具体行数,也就是说,执行select count() fromtable时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时,两种表的操作是一样的。

4)索引存储

对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

MyISAM支持全文索引(FULLTEXT)、压缩索引,InnoDB不支持

MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。

InnoDB存储引擎被完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB存储它的表&索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与MyISAM表不同,比如在MyISAM表中每个表被存在分离的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上。

5)服务器数据备份

InnoDB必须导出SQL来备份,LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

而且MyISAM应对错误编码导致的数据恢复速度快。MyISAM的数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。

InnoDB是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了。

6)锁的支持

MyISAM只支持表锁。InnoDB支持表锁、行锁 行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。

对比使用:

以下两点必须使用 InnoDB:

  1. 可靠性高或者要求事务处理,则使用InnoDB。这个是必须的。
  2. 表更新和查询都相当的频繁,并且表锁定的机会比较大的情况指定InnoDB数据引擎的创建。

对比之下,MyISAM的使用场景:

  1. 做很多count的计算的。如一些日志,调查的业务表。
  2. 插入修改不频繁,查询非常频繁的。

MySQL能够允许你在表这一层应用数据库引擎,所以你可以只对需要事务处理的表格来进行性能优化,而把不需要事务处理的表格交给更加轻便的MyISAM引擎。对于 MySQL而言,灵活性才是关键。
 

 

参考文章:

  https://blog.youkuaiyun.com/jack__frost/article/details/72904318

  https://juejin.im/post/5b55b842f265da0f9e589e79#heading-11

  https://blog.youkuaiyun.com/lishenglong666/article/details/53913126

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值