美文网首页
Mysql性能优化-4.锁与事务

Mysql性能优化-4.锁与事务

作者: 笨鸡 | 来源:发表于2019-05-11 10:01 被阅读0次

1.锁的作用

  • 避免资源争用的机制功能。
  • 资源争用:多个任务同时使用一个资源,对该资源产生争用。
  • 数据库中,记录(数据)就是资源,不同的客户端对记录CRUD操作就是任务。
  • 思路,就是在某个任务使用资源时,标识出来,其他任务就不能同时操作,等待或者放弃了。

2.流程

先尝试加锁,如果锁定成功,去使用资源。否则等待或者放弃!
加锁 》锁状态 》操作资源 》释放锁

3.锁的类型

  • 共享锁,读锁,S-lock。是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。如果事务A对数据A加上了共享锁,其他事务只能对A再加共享锁,不能加排他锁,获得共享锁的事务只能读数据,不能修改数据。
  • 在查询语句后面增加LOCK IN SHARE MODE,Mysql会对查询结束中的每行都加共享锁,当没有其它线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。
  • 排他锁,独占锁,写锁,X-lock。如果事务A对数据A加上排他锁后,则其他事务不能再对A加任何类型的锁,其他事务也不能对A做update,insert,delete操作,因为在innodb中这些操作默认加了排他锁,可以进行select操作因为查询的时候是不加任何锁的。
  • 在查询语句后面增加FOR UPDATE,Mysql会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。
  • Mysql 在执行任何的SQL时,都会自动增加锁定。通常不需要认为操作锁。
其他事务操作 共享锁 排他锁
select(默认不加锁)
update 不能 不能
insert 不能 不能
delete 不能 不能
加共享锁 不能
加排他锁 不能 不能

4.锁粒度(范围)

在MySQL中,锁被实现了不同的粒度。
一旦加锁,锁定的记录数量不同。

  • 表级锁定,table-level:操作会锁定整张表,无论是共享锁还是独占锁。
  • 行级锁定,row-level:操作会锁定该操作的记录。

MySQL的Innodb同时实现了表级和行级

5.MySQL中锁的相关语法

  • 表锁,myisam、innodb都是表锁。

  • 加锁:lock tables table-name1,table-name2 READ|WRITE;

  • 解锁:unlock tables;

  • 对于Innodb,支持行锁。
    对查询的记录增加共享锁:select * from table where id < 10 lock in share mode;
    对查询的记录增加排他锁:select * from table where id < 10 for update;

mysql> lock tables innodb1 read;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb1;
+----+--------+
| id | title  |
+----+--------+
| 11 | 令狐冲 |
| 16 | 成昆   |
| 23 | 张无忌 |
| 27 | 风清扬 |
| 28 | 风清扬 |
| 29 | 李莫愁 |
| 30 | 张无忌 |
| 31 | 风清扬 |
| 35 | 胡佩   |
| 36 | 胡佩   |
+----+--------+
10 rows in set (0.00 sec)

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

mysql> lock tables innodb1 write;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb1;
+----+--------+
| id | title  |
+----+--------+
| 11 | 令狐冲 |
| 16 | 周杰伦 |
| 23 | 张无忌 |
| 27 | 风清扬 |
| 28 | 风清扬 |
| 29 | 李莫愁 |
| 30 | 张无忌 |
| 31 | 风清扬 |
| 35 | 胡佩   |
| 36 | 胡佩   |
+----+--------+
10 rows in set (0.00 sec)

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb1 where id < 25 lock in share mode;
+----+--------+
| id | title  |
+----+--------+
| 11 | 令狐冲 |
| 16 | 周杰伦 |
| 23 | 张无忌 |
+----+--------+
3 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb1 where id < 25 for update;
+----+--------+
| id | title  |
+----+--------+
| 11 | 令狐冲 |
| 16 | 成昆   |
| 23 | 张无忌 |
+----+--------+
3 rows in set (0.00 sec)

mysql> update innodb1 set title = '任我行' where id = 16;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

6.事务

  • 开启事务 start transaction;或者 begin;
  • 回滚事务 rollback;
  • 提交事务 commit;
隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
未提交读(Read Uncommitted) 可能 可能 可能
已提交读(Read Committed) 不可能 可能 可能
可重复读(Repeatable Read) 不可能 不可能 可能
可串行化(Serializable) 不可能 不可能 不可能
  • 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
  • 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
  • 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
InnoDB使用不同的锁策略(Locking Strategy)来实现不同的隔离级别。

一,读未提交(Read Uncommitted)
这种事务隔离级别下,select语句不加锁。
画外音:官方的说法是
SELECT statements are performed in a nonlocking fashion.
此时,可能读取到不一致的数据,即“读脏”。这是并发最高,一致性最差的隔离级别。

二,串行化(Serializable)
这种事务的隔离级别下,所有select语句都会被隐式的转化为select ... in share mode.
这可能导致,如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住。
画外音:官方的说法是
To force a plain SELECT to block if other transactions have modified the 
selected rows.
这是一致性最好的,但并发性最差的隔离级别。
在互联网大数据量,高并发量的场景下,几乎不会使用上述两种隔离级别。

三,可重复读(Repeated Read, RR)
这是InnoDB默认的隔离级别,在RR下:
(1)普通的select使用快照读(snapshot read),这是一种不加锁的一致性读(Consistent
 Nonlocking Read),底层使用MVCC来实现,具体的原理在《InnoDB并发如此高,原因竟然在这?》
 中有详细的描述;
(2)加锁的select(select ... in share mode / select ... for update), update,
delete等语句,它们的锁,依赖于它们是否在唯一索引(unique index)上使用了唯一的查询条件(
unique searchcondition),或者范围查询条件(range-type search condition):

在唯一索引上使用唯一的查询条件,会使用记录锁(record lock)
,而不会封锁记录之间的间隔,即不会使用间隙锁(gap lock)与临键锁(next-key lock)


范围查询条件,会使用间隙锁与临键锁,锁住索引记录之间的范围,避免范围间插入记录,以避免产生
幻影行记录,以及避免不可重复的读


画外音:这一段有点绕,多读几遍。
关于记录锁,间隙锁,临键锁的更多说明,详见《InnoDB,select为啥会阻塞insert?》。


四,读提交(Read Committed, RC)
这是互联网最常用的隔离级别,在RC下:
(1)普通读是快照读
(2)加锁的select, update, delete等语句,除了在外键约束检查(foreign-key constraint 
checking)以及重复键检查(duplicate-key checking)时会封锁区间,其他时刻都只使用记录锁;
此时,其他事务的插入依然可以执行,就可能导致,读取到幻影记录。

mysql> show variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set, 1 warning (0.00 sec)

mysql> set tx_isolation='read-uncommitted';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> set tx_isolation='read-committed';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> set tx_isolation='repeatable-read';
Query OK, 0 rows affected, 1 warning (0.00 sec)

脏读:事务a未提交,事务b就能读到a更改的数据

A B
begin select * from innodb1 where id =16; {id:16,title:任我行}
update innodb1 set title = '独孤求败' where id = 16; select * from innodb1 where id =16; {id:16,title:独孤求败}
commit;

不可重复读:事务a未提交,事务b读的未更改数据,a提交,事务b读的a的更改数据。

A B
begin begin
select * from innodb1 where id =16; {id:16,title:独孤求败}
update innodb1 set title = '任我行' where id = 16;
commit;
select * from innodb1 where id =16; {id:16,title:任我行}
commit;

可重复读:

A B
begin begin
select * from innodb1 where id =16; {id:16,title:独孤求败}
update innodb1 set title = '任我行' where id = 16;
commit;
select * from innodb1 where id =16; {id:16,title:独孤求败}
commit;
select * from innodb1 where id =16; {id:16,title:任我行}

幻读

A B
begin begin
select * from innodb1 where id < 30;
insert into innodb1 values(24,'任盈');
commit;
update innodb1 set title = "任我行" where id < 30;
select * from innodb1 where id < 30; {id :24, 任我行}
commit;

相关文章

  • Mysql性能优化-4.锁与事务

    1.锁的作用 避免资源争用的机制功能。 资源争用:多个任务同时使用一个资源,对该资源产生争用。 数据库中,记录(数...

  • 99 MySQL性能实战优化

    mysql 性能优化 一 MySQL架构与执行流程原理 二 MySQL 索引底层实现原理 三 MYSQL事务...

  • MySQL数据库优化总结

    《高性能MySQL》指导 性能优化1.表优化2.索引优化3.查询优化4.服务器优化5.系统与硬件优化 稳定优化1....

  • MySQL相关文章索引(2)

    1.MySQL性能优化 对MySQL语句的性能分析与优化 Mysql 监控 Innodb 阻塞状况 MySQL索引...

  • Mysql性能优化-事务、锁和MVCC

    事务 mysql中如何开启事务: begin/start transaction --手工 commit/roll...

  • 高性能Mysql笔记

    一、Mysql架构与历史 1、架构图 2、锁 表锁 行级锁 3、事务 死锁 Mysql中的事务 1

  • 收藏-MySQL

    # MySQL的并发控制与加锁分析# MySQL的四种事务隔离级别# mysql共享锁与排他锁

  • 浅析mysql的锁

    目录:1.锁的定义与分类(表、行、页)2.锁相关的语句(查看锁)3.mysql事务4.乐观锁和悲观锁5.数据库死锁...

  • 2019-03-18文章精选

    1.深入理解 MySQL ——锁、事务与并发控制 各种锁、事务与并发,写得很详细。 2.剖析分布式锁 redis部...

  • mysql

    1. 数据库优化 2.mysql锁 2.1 InnoDB行锁类型 共享锁(S-Lock) 允许多个事务对于同一数据...

网友评论

      本文标题:Mysql性能优化-4.锁与事务

      本文链接:https://www.haomeiwen.com/subject/ubitaqtx.html