文章目录
- 写在前面
- 1、什么是锁
- 2、lock 与 latch
- 3、InnoDB 存储引擎中的锁
- 3.1、🐼 锁的类型
- 3.2、🐼 一致性非锁定读
- 3.3、🐼 一致性锁定读
- 3.4、🐼 自增长
- 3.5、AUTO-INC Locking
- 3.5、🐼 外键
- 写在后面
写在前面
🔔🔔🔔 开发多用户、数据库驱动的应用时,最大的一个难点是:一方面要最大程度地利用数据库的并发访问,另外一方面还要确保每个用户能以一致的方式读取和修改数据。为此就有了锁 (locking)的机制,同时这也是数据库系统区别于文件系统的一个关键特性。
InnoDB存储引擎较之MySQL 数据库的其他存储引在这方面技高一筹,其实现方式非常类似于Oracle 数据库。而只有正确了解这些锁的内部机制才能充分发挥InnoDB存储引肇在锁方面的优势。
1、什么是锁
数据库锁是一种用于管理并发访问的机制,用于确保在多个用户同时访问数据库时数据的一致性和完整性。当多个用户同时对数据库进行读取或写入操作时,可能会导致数据不一致或冲突的情况发生。数据库锁的作用就是在并发访问时对数据库中的数据进行加锁,以确保同一时间只有一个用户可以对数据进行修改或读取。
数据库锁可以分为两种类型:共享锁(Shared Lock)和排他锁(Exclusive Lock)。
- 🌵 共享锁(Shared Lock):也称为读锁,当一个事务对某个数据对象加上共享锁后,其他事务也可以对该数据对象加上共享锁,但不能加上排他锁。多个事务可以同时持有共享锁,用于并发读取数据。
- 🌵 排他锁(Exclusive Lock):也称为写锁,当一个事务对某个数据对象加上排他锁后,其他事务无法对该数据对象加上共享锁或排他锁。只有该事务释放锁之后,其他事务才能对该数据对象进行读取或修改。
数据库锁的使用需要谨慎,过多的锁会降低并发性能,而过少的锁可能会导致数据不一致或冲突的问题。因此,在设计数据库应用时,需要根据具体情况合理选择和管理数据库锁,以平衡并发性能和数据一致性的需求。
InnoDB 存储引擎锁的实现和 Oracle 数据库非常类似,提供一致性的非锁定读、行级锁支持。行级锁没有相关额外的开销,并可以同时得到并发性和一致性。
2、lock 与 latch
在计算机科学中,lock(锁)和latch(门闩)是用于控制并发访问的机制,但在不同的上下文中有着不同的含义。
- 🌵 Lock(锁):
锁是一种同步机制,用于保护共享资源的访问。它确保在同一时间只有一个线程可以访问被锁定的资源。锁可以分为两种类型:
- 排他锁(Exclusive Lock):也称为互斥锁,它只允许一个线程独占地访问被锁定的资源。其他线程必须等待锁被释放才能访问该资源。
- 共享锁(Shared Lock):允许多个线程同时以只读方式访问被锁定的资源,但不允许写操作。只有当所有共享锁都被释放后,才能获取排他锁。
- 锁的主要目的是确保在并发访问时数据的一致性和完整性。它可以防止多个线程同时对共享资源进行写操作,从而避免数据竞争和不一致的结果。
- 🌵Latch(门闩):
- 门闩是一种轻量级的同步机制,用于保护共享资源的访问。与锁不同,门闩通常是一种非阻塞的机制,用于提供对共享资源的独占访问,而不是控制并发访问。
- 门闩的主要目的是确保在访问共享资源之前,资源处于一致的状态。它通常用于内存管理、缓存管理等领域,以确保在访问共享资源之前,所需的前提条件已经满足。
- 与锁不同,门闩通常是一次性的,一旦门闩被打开,就无法再次关闭。它们通常用于同步线程或进程之间的操作,以确保在需要的时候某些条件已经满足。
锁和门闩都是用于控制并发访问的机制,但具体的实现和应用场景有所不同。锁主要用于保护共享资源的访问,确保数据的一致性和完整性;而门闩主要用于确保在访问共享资源之前,资源处于一致的状态。
3、InnoDB 存储引擎中的锁
InnoDB是MySQL数据库中一种常用的存储引擎。在InnoDB存储引擎中,锁是用于实现并发访问控制的重要机制。
InnoDB存储引擎支持两种类型的锁:行级锁和表级锁。
- 🌵 行级锁(Row-level Locking):
行级锁是InnoDB存储引擎的默认锁定级别。它允许多个事务同时访问同一张表的不同行,从而提高并发性能。行级锁可以分为两种类型:
- 共享锁(Shared Lock):也称为读锁,也叫 S 锁,允许多个事务同时读取同一行的数据,但不允许其他事务对该行进行修改。
- 排他锁(Exclusive Lock):也称为写锁,也叫 X 锁,只允许一个事务独占地对某一行进行读取和修改操作,其他事务必须等待锁释放。
- 🌵 表级锁(Table-level Locking):
- 表级锁是在特定情况下使用的锁定级别,它锁定整个表而不是单独的行。当需要对整个表进行操作时,InnoDB会自动升级为表级锁。表级锁会对整个表进行锁定,这会导致其他事务无法同时对表进行读取或修改操作,从而降低并发性能。
InnoDB存储引擎中的锁是自动管理的,通常不需要手动操作。它们会根据事务的隔离级别和具体的操作类型来自动选择适当的锁定级别。同时,InnoDB还使用多版本并发控制(MVCC)来提高并发性能,避免了一些传统锁定机制的性能问题。
3.1、🐼 锁的类型
InnoDB存储引擎中的锁有以下几种类型:
- 🌵 共享锁(Shared Lock):也称为读锁。多个事务可以同时持有共享锁,用于读取数据,但不能进行修改操作。共享锁之间不会互相阻塞,多个事务可以同时持有共享锁。
🔴共享锁(Shared Lock)是一种并发控制机制,用于在数据库系统中实现读取操作的共享访问。它允许多个事务同时获取同一个资源的共享锁,以便并发读取数据,而不会互相干扰或产生冲突。
🔴 共享锁的特点如下:
1. 多个事务可以同时获取共享锁,这意味着它们可以并发地读取被锁定的资源。
2. 共享锁之间不会互相阻塞,因为它们不会相互冲突。
3. 共享锁和排他锁之间存在冲突,即一个事务获取了共享锁后,其他事务无法获取该资源的排他锁,只能获取共享锁。
🔴 共享锁的应用场景通常是在读取操作频繁的情况下,例如查询操作。多个事务可以同时获取共享锁来读取数据,提高了并发性能和系统的响应速度。但是需要注意的是,共享锁不能阻止其他事务获取相同资源的共享锁,因此可能导致读取到已经被修改的数据(脏读)或不一致的结果。
🔴 在数据库系统中,共享锁通常与排他锁(Exclusive Lock)一起使用,以实现读写操作的并发控制。共享锁和排他锁的使用需要根据具体的业务需求和事务的隔离级别进行合理的选择和管理。
- 🌵 排他锁(Exclusive Lock):也称为写锁。只有一个事务可以持有排他锁,用于读取和修改数据。其他事务无法同时持有排他锁,必须等待锁释放。
🔴 排他锁(Exclusive Lock)是一种并发控制机制,用于在数据库系统中实现写入操作的独占访问。它确保只有一个事务可以获取>资源的排他锁,以便进行独占的写入操作,其他事务无法同时获取相同资源的排他锁,从而避免了数据的并发冲突。
🔴 排他锁的特点如下:
- 只有一个事务可以获取排他锁,其他事务无法同时获取相同资源的排他锁。
- 排他锁之间会互相阻塞,因为它们会相互冲突。
- 排他锁可以防止其他事务获取相同资源的共享锁或排他锁,从而确保独占的写入操作。
🔴排他锁的应用场景通常是在写入操作频繁或需要保证数据一致性的情况下,例如更新、删除操作。只有一个事务可以获取排他锁>来修改数据,避免了并发写入操作导致的数据冲突和不一致性。
🔴在数据库系统中,排他锁通常与共享锁(Shared Lock)一起使用,以实现读写操作的并发控制。通过合理地使用排他锁和共享>锁,可以提高并发性能、保证数据的一致性和完整性。
🔴需要注意的是,排他锁可能导致其他事务的阻塞和等待,因此在使用排他锁时需要考虑事务的隔离级别和性能影响。同时,避免>长时间持有排他锁,以免造成系统的资源竞争和性能问题。
- 🌵 记录锁(Record Lock):也称为行锁。在InnoDB中,行级锁是通过记录锁来实现的。记录锁可以是共享锁或排他锁,用于保护特定行的数据。
🔴记录锁(Record Lock)是一种并发控制机制,用于在数据库系统中实现对数据记录的独占访问。它是一种粒度更细的锁,用于保护数据库中的单个记录或数据行,以避免多个事务同时对同一记录进行修改而引发的并发冲突。
🔴记录锁的特点如下:
- 粒度较细:记录锁作用于数据库中的单个记录或数据行,而不是整个表或数据库对象。
- 独占访问:一旦一个事务获得了某个记录的记录锁,其他事务就无法同时获取相同记录的记录锁,从而保证了独占访问。
- 阻塞和等待:如果一个事务请求获取某个记录的记录锁,而该记录已经被其他事务占用,那么该事务会被阻塞或等待,直到该记录的记录锁被释放。
🔴记录锁的应用场景通常是在需要对数据库中的单个记录进行修改的情况下,例如更新或删除操作。通过使用记录锁,可以确保只有一个事务可以修改某个记录,避免了并发修改操作导致的数据冲突和不一致性。
🔴需要注意的是,记录锁的使用需要谨慎,过多或过长时间持有记录锁可能会导致其他事务的阻塞和性能问题。因此,在设计数据库并发控制策略时,需要综合考虑事务的隔离级别、并发访问模式和性能需求,合理使用记录锁来保证数据的一致性和完整性
- 🌵 意向锁(Intention Lock):意向锁是一种辅助锁,用于表示事务对表中某些行或页的意向操作。意向锁可以是意向共享锁(IS锁)或意向排他锁(IX锁)。当事务要对某一行进行加锁时,会先获取表级的意向锁,以表示对该行的意向操作。
🔴 意向锁(Intention Lock)是一种辅助锁,用于表示事务对表中某些行或页的意向操作。它有两种类型:
- 意向共享锁(Intention Shared Lock,IS锁):表示事务打算在某个表或某个页上设置共享锁。当一个事务要在某行上设置共>享锁时,需要先获取表级的意向共享锁。
- 意向排他锁(Intention Exclusive Lock,IX锁):表示事务打算在某个表或某个页上设置排他锁。当一个事务要在某行上设置>排他锁时,需要先获取表级的意向排他锁。
🔴 意向锁的作用是为了协调多个事务对同一表的行级锁的获取。通过意向锁,可以提高并发性能,避免冲突和死锁的发生。例如,>如果一个事务要在某一行上设置排他锁,那么其他事务可以先获取该表的意向共享锁或意向排他锁,而不需要等待排他锁的释放。
🔴 需要注意的是,意向锁是隐式获取的,由InnoDB存储引擎自动管理。在正常情况下,开发者无需直接操作意向锁。
- 🌵 自增锁(Auto-Increment Lock):自增锁是一种特殊的锁,用于保护自增列的并发插入操作。在InnoDB中,自增锁是通过隐藏的索引来实现的。
🔴 自增锁(Auto-Increment Lock)是一种并发控制机制,用于在多线程或多进程环境中实现对资源的独占访问。它通过使用一个自增的计数器来实现对资源的锁定和解锁操作。
🔴 自增锁的基本原理是,每个线程或进程在访问资源之前,先获取一个唯一的自增锁标识。这个标识可以是一个整数或一个唯一的字符串。当一个线程或进程获取到自增锁标识后,它就可以访问资源,其他线程或进程则需要等待。
🔴 自增锁的实现通常包括以下步骤:
- 初始化计数器:在系统启动时,初始化一个计数器,用于生成唯一的自增锁标识。
- 获取自增锁标识:当一个线程或进程需要访问资源时,它会通过增加计数器的值来获取一个唯一的自增锁标识。
- 访问资源:获取到自增锁标识后,线程或进程可以访问资源。
- 释放自增锁标识:当线程或进程完成对资源的访问后,它会释放自增锁标识,使其他线程或进程可以获取到该标识并访问资源。
🔴 自增锁的优点是简单且易于实现,适用于对资源进行短时间的独占访问。然而,它也存在一些限制和注意事项:
- 自增锁只能保证资源的独占访问,无法解决其他并发问题,如死锁、饥饿等。
- 自增锁的性能可能受限于计数器的实现和并发访问的频率。
- 自增锁的标识生成需要保证唯一性,避免冲突。
因此,在设计并发控制策略时,需要综合考虑系统的需求和特点,选择合适的并发控制机制,包括自增锁在内。
InnoDB存储引擎会根据具体的操作和隔离级别自动选择合适的锁策略,以保证数据的一致性和并发性能。同时,InnoDB还支持多版本并发控制(MVCC),通过版本号和回滚段来管理并发访问,提高了并发性能和事务隔离级别。
3.2、🐼 一致性非锁定读
InnoDB是MySQL数据库的一种存储引擎,它支持一致性非锁定读(Consistent Non-locking Read)的特性。
🌵 一致性非锁定读 是指在执行读操作时,不会对数据进行锁定,以允许其他事务并发地修改数据。这意味着读操作不会阻塞写操作,提高了并发性能。
InnoDB实现一致性非锁定读的方式是通过多版本并发控制(MVCC)机制。在MVCC中,每个事务读取的数据版本是固定的,即使其他事务对数据进行了修改,读取操作也不会受到影响。这样可以保证读取操作的一致性,同时不会对写操作造成阻塞。
在InnoDB中,一致性非锁定读的默认隔离级别是可重复读(REPEATABLE READ)。在可重复读隔离级别下,读操作会获取一个一致性视图,并在整个事务期间保持该视图不变。这意味着在同一个事务中进行的多次读操作,都会读取到相同的数据版本,即使其他事务对数据进行了修改。
需要注意的是,一致性非锁定读并不是完全没有锁定的操作。在某些情况下,仍然会使用锁定机制来保证数据的一致性。例如,在执行一些特定的读操作时,可能会使用共享锁(Shared Lock)来防止其他事务修改数据。
总结来说,InnoDB的一致性非锁定读通过MVCC机制实现,提供了高并发性能和读操作的一致性。默认情况下,InnoDB使用可重复读隔离级别来支持一致性非锁定读。
3.3、🐼 一致性锁定读
InnoDB是MySQL数据库的一种存储引擎,它支持一致性锁定读(Consistent Locking Read)的特性。
🌵 一致性锁定读 是指在执行读操作时,会对数据进行锁定,以保证读取的数据是一致的。这意味着读操作会阻塞写操作,确保读取的数据不会被并发修改。
在InnoDB中,一致性锁定读的默认隔离级别是可重复读(REPEATABLE READ)。在可重复读隔离级别下,读操作会获取共享锁(Shared Lock),防止其他事务对数据进行修改。这样可以保证读取操作的一致性,但也会对写操作造成阻塞。
需要注意的是,一致性锁定读可能会导致读取的数据版本落后于最新的数据。因为写操作会获取排他锁(Exclusive Lock),而读操作需要等待写操作释放锁之后才能进行。
InnoDB的一致性锁定读通过锁定机制来保证读取操作的一致性。默认情况下,InnoDB使用可重复读隔离级别来支持一致性锁定读。
3.4、🐼 自增长
自增长在数据库中是非常常见的一种属性,也是很多 DBA 或开发人员首选的主键方式。在InnoDB存储引擎的内存结构中,对每个含有自增长值的表都有一个自增长计数器(autoincrement counter)。当对含有自增长的计数器的表进行插入操作时,这个计数器会被初始化,执行如下的语句来得到计数器的值:
SELECT MAX(auto inc col) FROM t FOR UPDATE
插入操作会依据这个自增长的计数器值加1赋予自增长列。这个实现方式称做 🌵 AUTO-INC Locking。这种锁其实是采用一种特殊的表锁机制,为了提高插入的性能,锁不是在一个事务完成后才释放,而是在完成对自增长值插入的 SQL 语后立即释放。
3.5、AUTO-INC Locking
InnoDB的AUTO-INC Locking是指在使用自增列(AUTO_INCREMENT)时的锁机制。当多个事务同时插入数据到具有自增列的表中时,InnoDB会使用特殊的锁机制来保证生成的自增值的唯一性和连续性。
InnoDB的AUTO-INC Locking机制主要包括两个方面:
- 🌵 插入锁(Insert Intention Lock):当一个事务要插入数据到具有自增列的表中时,InnoDB会获取一个插入锁。这个锁会阻塞其他事务的插入操作,以确保生成的自增值的唯一性。
- 🌵 自增锁(Auto-Increment Lock):当一个事务获取到插入锁后,它会继续获取自增锁。自增锁会阻塞其他事务的插入操作,以确保生成的自增值的连续性。
通过使用插入锁和自增锁,InnoDB可以保证在并发插入操作中生成的自增值不会重复,并且按照插入的顺序连续递增。
需要注意的是,InnoDB的AUTO-INC Locking机制可能会对并发插入操作的性能产生一定的影响。如果并发插入操作非常频繁,可以考虑调整自增列的增长步长(例如使用更大的AUTO_INCREMENT_INCREMENT值),以减少锁竞争和提高性能。
总之,InnoDB的AUTO-INC Locking是一种用于保证自增值唯一性和连续性的锁机制,通过插入锁和自增锁来实现。
3.5、🐼 外键
外键主要用于引用完整性的约束检查。在InnoDB存储引擎中,对于一个外键列,如果没有显式地对这个列加索引,InnoDB 存储引擎自动对其加一个索引,因为这样可以避免表锁一一这比 Oracle 数据库做得好,racle 数据库不会自动添加索引,用户必须自己手动添加,这也导致了 Oracle 数据库中可能产生死锁。
对于外键值的插人或更新,首先需要查询父表中的记录,即 SELECT父表。但是对于父表的SELECT操作,不是使用一致性锁定读的方式,因为这样会发生数据不一致的问题,因此这时使用的是SELECT···LOCKIN SHARE MODE方式,即主动对父表加一个S锁。如果这时父表上已经这样加X锁,子表上的操作会被阻塞。
写在后面
总之,InnoDB存储引擎通过行级锁定实现并发控制,并提供了多种锁定粒度和锁定类型。它还通过自动锁定和死锁处理机制来简化开发人员的工作。在使用InnoDB时,可以根据具体的业务需求和性能要求进行锁定优化。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net