MySQL锁知识理解

MySQL搜索引擎锁支持:

  1. MyISAM:表锁
  2. InnoDB:行锁、表锁
  3. BDB:页锁、表锁

性能表现:

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

MyISAM

**show status like ‘tables%’;**查看table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:

show status like 'tables%';
mysql> show status like 'table%';
+----------------------------## 标题+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Table_locks_immediate      | 5     |
| Table_locks_waited         | 0     |
| Table_open_cache_hits      | 51    |
| Table_open_cache_misses    | 21    |
| Table_open_cache_overflows | 0     |
+----------------------------+-------+
5 rows in set (0.00 sec)

Table_locks_waited:表示锁争用情况。

锁模式

MySQL表锁有读锁read写锁write 两种模式。

MyISAM中,读锁为共享锁,写锁为排他锁,读读兼容,读写不兼容,写写不兼容。 读写操作,写写操作之间是串行的。

显示加锁和自动加锁

显示加锁语句为

lock table mytable read;
lock tables mytable read,mytable2 read;
lock table mytable write;
lock tables mytable write,mytable2 write;

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。

MyISAM不支持锁升级:加了读锁不能升级为写锁。

并发插入concurrent_insert

并发插入表示加了读锁后其他进程可以在一定条件下插入数据

  • 0:不允许并发插入
  • 1:表示没有空洞时(表中间没有删除数据,可以用OPTIMIZE TABLE消除内存碎片)可以并发插入
  • 2.任何时候都可以并发插入

MyISAM锁调度

读写互斥、写写互斥的条件下,如果在读时另一进程有一条写操作,甚至在读后另一进程有一条写操作,写操作会先获得锁(先执行)。这是因为MySQL认为写请求一般比读请求要重要,这也是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,会造成读“死状态”。可以同过一些参数来改变:

  1. 通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。
  2. 通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
  3. 通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。

三种参数表示MyISAM这种要么读优先要么写优先的特性,另外,MySQL也提供了一种折中的办法来调节读写冲突,即给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会。

应用中也应尽量避免出现长时间运行的查询操作。

innoDB锁知识

InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁

show status like ‘innodb_row_lock%’; 用以分析行锁的争用情况。

mysql> show status like 'innodb_row_lock%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0     |
| Innodb_row_lock_time          | 0     |
| Innodb_row_lock_time_avg      | 0     |
| Innodb_row_lock_time_max      | 0     |
| Innodb_row_lock_waits         | 0     |
+-------------------------------+-------+
5 rows in set (0.00 sec)

如果发现锁争用比较严重,InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值比较高。

InnoDB行锁模式及加锁方法

  1. 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
  2. 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁
    (Intention Locks),这两种意向锁都是表锁
  3. 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  4. 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

加锁方式

共享锁(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将使用表锁!

间隙锁(Next-Key锁)

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

参考资料:https://blog.csdn.net/tanga842428/article/details/52748531

发布了239 篇原创文章 · 获赞 70 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43777983/article/details/103501299