首页 数据库 mysql教程 MySQL锁的管理机制_MySQL

MySQL锁的管理机制_MySQL

May 30, 2016 pm 05:11 PM
机制

**********************************

MySQL锁的管理机制

**********************************

 

MySQL server层面的一些锁
? table-level locking(表级锁)

? page-level locking(页级锁)

? row-level locking(行级锁)
————————————————————————————————————————————————————————————————————


一、表级锁:直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作。如果你是写锁,则其它进程则读也不允许.
对MyISAM表进行表级锁定


MyISAM表的锁
? 读锁,LOCK TABLE GYJ_T1 READ,自身只读,不能写;其他线程仍可读,不能写。多个线程都可提交read lock。
? 写锁,LOCK TABLE GYJ_T1 [LOW_PRIORITY] WRITE ,自身可读写;其他线程完全不可读写。
? 释放锁,UNLOCK TABLES
? SELECT自动加读锁
? 其他DML、DDL自动加写锁


Innodb行级锁升级表级锁的三种情况。
1.Innodb auto-inc锁
InnoDB处理具有auto increment字段的表的时候,会使用一种特殊的表锁——AUTO-INC。
简单来说就是innodb会在内存里保存一个计数器用来记录auto_increment的值,当插入数据时,就会用一个表锁来锁住这个计数器,
直到插入结束。一条一条插入问题不大,但是如果高并发插入,就会造成sql阻塞。
解决方法有两种
A)不用auto increment字段,自己维护主键生成。该方法中选择主键生成策略很重要, 要综合考虑简单和效率问题。假设使用uuid,
虽然简单但是会造成该表的主键效率很低(innodb的主键是特殊的index,其他的index会引用主键,详见mysql文档)
B) 修改innodb_autoinc_lock_mode
innodb_autoinc_lock_mode = 0 (“traditional” lock mode:全部使用表锁)
innodb_autoinc_lock_mode = 1 (“consecutive” lock mode:可预判行数时使用新方式,不可时使用表锁)
innodb_autoinc_lock_mode = 2 (“interleaved” lock mode:全部使用新方式,不安全,不适合replication)

2.Innodb 全表更新、全索引更新
3.Innodb 使用SR事务隔离级别


二、页级锁:表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
对BDB表进行页级锁定,BDB现在没有了,很老的数据库,4点几的才有,现在从数据库上删除掉了

三、行级锁:仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作。
对InnoDB表进行行级锁定


Innodb加行锁的方式
1.record lock(行/记录锁)
2.gap lock(间隙锁)
3.next-key lock (record lock + gap lock)

InnoDB是通过给索引上的索引项加锁来实现行锁
InnoDB有几种锁:
? 共享锁(S - LOCKING),允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁
? 排它锁(X - LOCKING),允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他锁


InnoDB还独有的实现了2种锁:
? 意向共享锁(IS),事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁
? 意向独占锁(IX),事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁


注意:
(1)在不通过索引条件查询的时候,InnoDB使用的是表锁(默认地,全表所有行加锁,和表级锁相当,
例外条件是 RC + innodb_locks_unsafe_for_binlog 组合选项),而不是细粒度行锁。
(2)由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,
是会出现锁冲突的。


共享锁:SELECT * FROM xx WHERE … LOCK IN SHARE MODE
加排他锁:SELECT * FROM xx WHERE … FOR UPDATE


在5.1以前,只能通过SHOW FULL PROCESSLIST、SHOW ENGINE INOODB STATUS等命令查看锁的状态
在5.1之后:(使用了InnoDB plugin之后)
INFORMATION_SCHEMA:
INNODB_TRX
INNODB_LOCKS
InnoDB_LOCK_WAITS


show engine innodb mutex; #latch锁


show engine innodb status\G; #lock锁


INNODB_TRX
select * from information_schema.innodb_trx\G;
INNODB_LOCKS
select * from information_schema.innodb_locks\G; |
INNODB_LOCK_WAITS
select * from information_schema.innodb_lock_waits\G;

innodb_trx:
看下innodb_trx表中,几个最常用的字段:
trx_id:InnoDB存储引擎内部唯一的事务ID
trx_state:当前事务的状态
trx_started:事务的开始时间。
trx_wait_started:事务等待开始的时间。
trx_mysql_thread_id:Mysql中的线程ID,SHOW PROCESSLIST显示的结果。
trx_query:事务运行的sql语句。


innodb_locks
看下innodb_locks表中,几个最常用的字段:
lock_id:锁的ID。
lock_trx_id:事务ID。
lock_mode:锁的模式。
lock_type:锁的类型,表锁还是行锁。
lock_table:要加锁的表。
lock_index:锁的索引。
lock_space:InnoDB存储引擎表空间的ID号。
lock_page:被锁住的页的数量。若是表锁,则该值为NULL。
lock_rec:被锁住的行的数量。若是表锁,则该值为NULL。
lock_data:被锁住的行的主键值。当是表锁时,该值为NULL。


innodb_lock_waits
看下innodb_lock_waits表中,几个最常用的字段:
requesting_trx_id:申请锁资源的事务ID。
requesting_lock_id:申请的锁的ID。
blocking_trx_id:阻塞的锁的ID。


***************************************************************************************************************
实验一:观察INNODB_TRX、INNODB_LOCKS、InnoDB_LOCK_WAITS、processlist,status
**************************************************************************************************************

create table gyj_t1(id int primairy key,name varchar(10));
insert into gyj_t1 values(1,'AAAAA');
mysql> show variables like '%autocommit%';
mysql> select @@tx_isolation;
mysql> show variables like 'innodb_lock_wait_timeout';
mysql> set global innodb_lock_wait_timeout=600;
mysql> set innodb_lock_wait_timeout=600;


session 1
mysql> begin;
mysql> update gyj_t1 set name='BBBBB' where id=1;


session 2
mysql> begin;
mysql> update gyj_t1 set name='bbbbb' where id=1;


session 3
mysql> select * from information_schema.innodb_trx\G;
mysql> select * from information_schema.innodb_locks\G;
mysql> select * from information_schema.innodb_lock_waits\G;
mysql> show processlist;
mysql> show engine innodb status\G;




*********************************************
实验二:锁案例一,聚集索引上的锁
**********************************************

1.默认RR隔离级别
2.自动提交
3.创建表
CREATE TABLE student
(
id int unsigned not null auto_increment,
xh int unsigned not null,
name varchar(10) not null,
bjmc varchar(20) not null,
primary key(id),
key xh(xh)
) engine =InnoDB;


3.插入两条记录
insert into student values (1, 1, 'guoyj', 'jsj01'), (2, 2, 'jfedu', 'jsj01');


4.场景一
set autocommit=0;
(1)session 1
select * from student where id=1 for update;


(2)session 2
select * from student where id=1; #一致性非锁定读,这时侯会阻塞吗?(不会)
select * from student where id=1 lock in share mode; #这时侯会阻塞吗?(会)


(3)session 1
commit;或 rollback;


总结:一致性非锁定读测试(不产生任何锁,所以不会锁等待)
意向排它锁,意向共享锁互斥测试(会发生锁等待)


5.场景二
set autocommit=0;
(1)session 1
select * from student where name='guoyj' for update;


(2)session 2
select * from student where name='jfedu' for update; #这时侯会阻塞吗?(会)


(3)session 1
commit;或 rollback;


总结:看表结构,name这列没有索引,在RR隔离级别所有的记录全部都会被锁定,排它锁。


6.场景三
set autocommit=0;
(1)session 1
select * from student where xh=1 and name='guoyj' for update;
(2)session 2
select * from student where xh=1 and name='jfedu' for update; #这时侯会阻塞吗?(会)
(3)session 1
commit;或 rollback;


总结:xh是有索引的,xh=1,会话1会话2是同一行记录,同一个索引会被锁定的,出现冲突,发生等(name上没有索引,范围会扩大!)


7.场景四
那如果我把会话1的SQL,换成:select *from student where xh=2 and name='jfedu' for update;后会话2会发生锁等待吗?


set autocommit=0;
(1)session 1
select * from student where xh=1 and name='guoyj' for update;


(2)session 2
select * from student where xh=2 and name='jfedu' for update; #这时侯会阻塞吗?(不会)


总结:
会话2:xh是有索引的,xh=2 会话1会话2是不同的行记录,不是同一个索引,不会发生等待!
MySQL的行锁是针对索引加的锁,而不是记录加的锁!
由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,
是会出现锁冲突的。应用设计的时侯要注意这点。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

深入了解CSS布局重新计算和渲染的机制 深入了解CSS布局重新计算和渲染的机制 Jan 26, 2024 am 09:11 AM

CSS回流(reflow)和重绘(repaint)是网页性能优化中非常重要的概念。在开发网页时,了解这两个概念的工作原理,可以帮助我们提高网页的响应速度和用户体验。本文将深入探讨CSS回流和重绘的机制,并提供具体的代码示例。一、CSS回流(reflow)是什么?当DOM结构中的元素发生可视性、尺寸或位置改变时,浏览器需要重新计算并应用CSS样式,然后重新布局

PHP中的自动加载机制 PHP中的自动加载机制 Jun 18, 2023 pm 01:11 PM

随着PHP语言越来越受欢迎,开发人员需要使用越来越多的类和函数。当项目规模扩大时,手动引入所有依赖项将变得不切实际。这时候就需要一种自动加载机制来简化代码开发和维护过程。自动加载机制是一种PHP语言的特性,可以在运行时自动载入所需的类和接口,并减少手动的类文件引入。这样,程序员可以专注于开发代码,减少因繁琐的手动类引入而产生的错误和时间浪费。在PHP中,一般

深入探讨Golang变量的存储位置和机制 深入探讨Golang变量的存储位置和机制 Feb 28, 2024 pm 09:45 PM

标题:深入探讨Golang变量的存储位置和机制随着Go语言(Golang)在云计算、大数据和人工智能领域的应用逐渐增多,深入了解Golang变量的存储位置和机制变得尤为重要。在本文中,我们将详细探讨Golang中变量的内存分配、存储位置以及相关的机制。通过具体代码示例,帮助读者更好地理解Golang变量在内存中是如何存储和管理的。1.Golang变量的内存

Go语言垃圾回收机制详解 Go语言垃圾回收机制详解 Mar 26, 2024 pm 02:42 PM

Go语言(也称为Golang)是谷歌开发的一种高效的编程语言,具有并发性和垃圾回收机制等特点。本文将详细解释Go语言中的垃圾回收机制,包括其原理、实现方式以及代码示例。1.垃圾回收原理Go语言的垃圾回收机制是通过“标记-清除”算法实现的。在程序运行过程中,Go运行时会在堆中跟踪哪些对象是可以被访问的(被标记),而哪些对象是无法被访问的,即垃圾数据(需要清除

PHP中的隐式转换机制解析 PHP中的隐式转换机制解析 Mar 09, 2024 am 08:00 AM

PHP中的隐式转换机制解析在PHP编程中,隐式转换是指在不显式指定类型转换的情况下,PHP自动将一个数据类型转换为另一个数据类型的过程。隐式转换机制在编程中非常常见,但也容易造成一些意想不到的bug,因此了解隐式转换机制的原理和规则对于编写稳健的PHP代码非常重要。1.整型与浮点型之间的隐式转换在PHP中,整型和浮点型之间的隐式转换是非常常见的。当一个整型

重要的JS缓存机制概念:了解普及五个知识点 重要的JS缓存机制概念:了解普及五个知识点 Jan 23, 2024 am 09:52 AM

知识普及:了解JS缓存机制的五个重要概念,需要具体代码示例在前端开发中,JavaScript(JS)缓存机制是一个非常关键的概念。理解和正确运用缓存机制可以极大地提升网页的加载速度和性能。本文将介绍JS缓存机制的五个重要概念,并提供相应的代码示例。一、浏览器缓存浏览器缓存是指在第一次访问网页时,浏览器会将网页的相关资源(例如JS文件、CSS文件、图片等)保存

Go 语言中的内存管理机制是怎样的? Go 语言中的内存管理机制是怎样的? Jun 10, 2023 pm 04:04 PM

Go语言是一门广泛用于系统级编程的高效编程语言,其主要优势之一是其内存管理机制。Go语言内建的垃圾回收机制(GarbageCollection,简称GC)使得程序员不必亲自进行内存分配和释放操作,提高了开发效率和代码质量。本文将对Go语言中的内存管理机制进行详细介绍。一、Go内存分配在Go语言中,内存分配使用了两个堆区:小对象堆(small

解惑:Golang 中的并发机制究竟是怎样实现的 解惑:Golang 中的并发机制究竟是怎样实现的 Mar 18, 2024 pm 09:18 PM

在当今互联网高并发、大规模数据处理的时代,如何高效地实现并发成为了开发人员面临的一个重要问题。在众多编程语言中,Golang(即Go语言)以其简洁易学、高效并发的特点,受到了越来越多开发者的青睐。Golang的并发机制是怎样实现的呢?让我们一起来解惑。Golang中的并发机制Golang的并发机制是建立在“goroutine”(协程)和“channel”(

See all articles