锁的介绍

Ⅰ、锁的概念

1.1 锁的作用

  • 对共享资源进行并发访问
  • 提供数据的完整性和一致性

1.2 锁的实现

每个数据库的锁的实现完全不同

  • MyISAM表锁
  • InnoDB行级锁
    Like Oracle???不一样
  • Microsoft SQL Server 行级锁with锁升级
    行锁超过5000个就升级为行级锁或者表锁

MySQL做的很棒,但是很难理解。

1.3 latch(闩锁)

  • mutex 互斥锁
  • rw-lock

他们是锁吗?

latch在内存中,控制内存数据结构的并发访问,针对程序内部资源(比如:全局变量),锁的是并发资源(临界区),lock是数据库层的锁,针对的是事务,锁的对象不是内存结构而是行

数据库中发生死锁会选择一个事务回滚,程序层中没有死锁检测

latch无处不在,对某一个对象并发访问的控制,和lock也没啥好比较的,完全不搭界

lock由latch来保证和实现

tips:
如何查看latch? 了解即可,基本用不着

(root@localhost) [(none)]> show engine innodb mutex;
+--------+---------------------------+----------+
| Type   | Name                      | Status   |
+--------+---------------------------+----------+
| InnoDB | rwlock: dict0dict.cc:1184 | waits=3  |
| InnoDB | rwlock: log0log.cc:838    | waits=23 |
+--------+---------------------------+----------+
2 rows in set (0.00 sec)

即使很大也没什么意义,代表不了什么,waits很长就代表这个latch有并发
某时间点数据写入量很大,那重做日志的这把latch可能就会很大
读取量大的话,bp的latch可能会很大

Ⅱ、 演示锁

session1:
(root@localhost) [test]> show create table l\G
*************************** 1. row ***************************
       Table: l
Create Table: CREATE TABLE `l` (
  `a` int(11) NOT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`),
  UNIQUE KEY `c` (`c`),
  KEY `b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

(root@localhost) [test]> select * from l;
+---+------+------+------+
| a | b    | c    | d    |
+---+------+------+------+
| 2 |    4 |    6 |    8 |
| 4 |    6 |    8 |   10 |
| 6 |    8 |   10 |   12 |
| 8 |   10 |   12 |   14 |
+---+------+------+------+
4 rows in set (0.00 sec)

(root@localhost) [test]> begin;
Query OK, 0 rows affected (0.00 sec)

(root@localhost) [test]> delete from l where a = 2;
Query OK, 1 row affected (0.00 sec)

(root@localhost) [test]> update l set b = b + 1 where a = 4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

(root@localhost) [test]> select * from l;
+---+------+------+------+
| a | b    | c    | d    |
+---+------+------+------+
| 4 |    7 |    8 |   10 |
| 6 |    8 |   10 |   12 |
| 8 |   10 |   12 |   14 |
+---+------+------+------+
3 rows in set (0.00 sec)

此时这两条记录上就被加了排他锁,在当前session看到这两条记录已经变化了

再开一个session看到的还是原来的记录,因为事务还没提交,mvcc特性

session2:
(root@localhost) [test]> select * from l;
+---+------+------+------+
| a | b    | c    | d    |
+---+------+------+------+
| 2 |    4 |    6 |    8 |
| 4 |    6 |    8 |   10 |
| 6 |    8 |   10 |   12 |
| 8 |   10 |   12 |   14 |
+---+------+------+------+
4 rows in set (0.00 sec)

(root@localhost) [test]> show engine innodb status\G
...
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 29474225, ACTIVE 46 sec
2 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 2
MySQL thread id 296696, OS thread handle 140076853794560, query id 34555618 localhost root
Trx read view will not see trx with id >= 29474796, sees < 29474796
...

通常认为增删改会加排它锁,其实select也可以加,select后面用一个for update就对这条记录加锁了,但是这个锁住了没事,新开session依然可以读,mvcc机制————默认读永远不会被锁,即使你在全表更新

但新开session去select也加for update这时候就会等待了
posted @ 2018-05-31 20:20  91洲际哥  阅读(523)  评论(0编辑  收藏  举报