前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何锁“住”MySQL

如何锁“住”MySQL

作者头像
石的三次方
发布2021-01-05 22:32:51
1.1K0
发布2021-01-05 22:32:51
举报
文章被收录于专栏:石的三次方石的三次方

MySQL锁概述

1. 锁

锁是计算机协调多个进程或线程并发访问某一资源的机制。

在数据库中,除传统的计算资源的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的问题,锁冲突也是影响数据库并发访问性能的一个重要的因素。

2. 分类

「从数据操作类型区分:」

  • 读锁。又称共享锁:针对同一份数据,多个读操作可以同时进行而不会互相影响
  • 写锁。又称排它锁:当前写操作没有完成前,他会阻断其他写锁和读锁

「从数据操作颗粒度:」

  • 表锁。在进行数据操作的时候,将一张表全部加锁。即悲观锁
  • 行锁。仅仅对操作的行进行加锁,不同行之间没有影响
2.1 表锁(偏读)

MyISAM的锁就是表锁。

MyISAM在执行查询查询语句之前默认给所有的表加读锁,在执行增删改操作之前,会自动给涉及到的表加写锁

  • 加读锁。
代码语言:javascript
复制
lock table 表名 read ;
  • 加写锁。
代码语言:javascript
复制
lock table 表名 write ;
  • 查看表中的所有锁
代码语言:javascript
复制
show open tables ;
  • 释放表锁
代码语言:javascript
复制
unlock tables ;
2.1.1 加读锁
  • 给表mylock加读锁
  • 当前MySQL会话中执行查询当前加锁表。「可以查询」
  • 当前MySQL会话中执行修改当前加锁表。「不能修改」
  • 当前MySQL会话中执行查询其他未加锁表。「不能查询」
  • 其他会话中执行查询加锁表。「可以查询」
  • 其他会话中执行修改加锁表。「进入阻塞状态」。当释放锁以后就会立即查询出数据
  • 其他会话中执行查询其他未加锁表。「可以查询」
2.1.2 加写锁
  • 添加写锁
  • 当前会话中查询加锁表。「可以查询」
  • 当前会话中查询其他未加锁表。「不能查询」
  • 当前会话中修改加锁表。「可以更改」
  • 其他会话中读取加锁表。「进入阻塞」
2.1.3 表锁加读写锁的总结
  • MyISAM表的读操作,不会阻塞其他进程对同一表的读操作,但会阻塞对同一个表的写操作。只有当读锁被释放以后,才可以进行写操作。
  • MyISAM表的写操作,会阻塞其他进程对同一表的读操作,只有当写锁释放以后,才可以进行读操作
  • 对于其他进程:读锁会阻塞写不会阻塞读,写锁将读和写都阻塞
  • 对于当前进程:读锁会禁止其他表读取,当前表写操作
2.1.4 分析表锁定
代码语言:javascript
复制
show status like 'table%';
  • table_locks_immediate :产生表级锁定的次数。标识可以立即获取锁的查询次数,没立即获取锁值加一
  • table_locks_waited:出现标记锁定争用而发生的等待次数(不能获取立即获取锁的次数,没等待一次就加一)
  • table-open_cache_hits:从table sharefree list中找到一个表的缓存,如果找到则加一
  • table_open_cache_misses:和上面的hits相反,如果在缓存中找不到实例则需要重新实例化,每次加一
  • table_open_cache_overflows:超过缓存区大小的实例个数
  • MyISAM的读写锁调度是以写优先,这也是MyISAM不适合做主表的引擎。因为写锁后,其他线程不能做任何的操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。
2.2 行锁(偏写)

InnoDB使用行锁,锁定粒度低,发生锁冲突的概率最低,并发度也最高。

「行锁演示:」

  • MySQLInnoDB引擎下的自动隔离级别为「事务」,每一次请求都相当于提交一次事务
  • 当前会话,取消自动提交,修改一行的值。
  • 另一个会话,读取这一行的值。「读取到的是原数据」
  • 另一个会话,更新这一行。「进程阻塞」
  • 当前进程提交事务。「另一个会话,恢复」
2.2.1 由于出现索引失效导致行锁变表锁
  • 模拟索引字段类型转换导致索引失效。
  • 插入一个整形的name,底层出现索引失效。
  • 另一个会话,出现进程阻塞

这个的主要原因是:「由于出现索引失效导致只能从全表读取,导致行锁变表锁」

2.2.2 由于出现范围写操作导致出现间隙锁
  • 更新一个范围内的字段
  • 其他会话对这个范围内的数据进行写操作

间隙锁:「MySQL在执行范围写操作的时候,会默认将这个范围内的数据全部加锁,如果当前进行没有进行提交,那么其他进程访问这个范围内的数据将会被阻塞。」

2.2.3 手动开启行锁
代码语言:javascript
复制
mysql> begin ;
Query OK, 0 rows affected (0.00 sec)

mysql>select * from 表名 where id = 3 for update #锁定id=3的行

mysql> commit ; # 如果不进行提交,那么其他进程将不能对该行进行写操作
2.2.4 分析行锁定
代码语言:javascript
复制
mysql> show status like 'innodb_row_lock%';
+-------------------------------+--------+
| Variable_name                 | Value  |
+-------------------------------+--------+
| Innodb_row_lock_current_waits | 0      |
| Innodb_row_lock_time          | 397427 |
| Innodb_row_lock_time_avg      | 39742  |
| Innodb_row_lock_time_max      | 51038  |
| Innodb_row_lock_waits         | 10     |
+-------------------------------+--------+
5 rows in set (0.00 sec)
  • Innodb_row_lock_current_waits。当前正在等待锁定的数量
  • Innodb_row_lock_time。锁定以后进程等待时间总和
  • Innodb_row_lock_time_avg。每次等待的平均时间
  • Innodb_row_lock_time_max。等待的最大时间
  • Innodb_row_lock_waits。等待次数
2.2.5 行锁优化
  • 尽可能让所有的数据检索都通过索引来完成,避免无索引导致行锁升级为表锁
  • 合理设计索引,缩小锁的范围
  • 尽可能使用准确的数值检索或者范围较小,避免间隙锁
  • 尽量控制事务大小,减少锁定资源量和时间长度
  • 尽可能低级别事务隔离
3. 页锁

开销和加锁时间界于表锁和行锁之间:会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

MySQL主从复制

1. MySQL主从复制过程

  • master将改变记录记录到二进制文件中。
  • slavemaster的二进制日志文件中的记录拷贝到它的中继日志文件relay log
  • slave读取这个中继文件,将改变应用到自己的数据库中。MySQL的复制是异步且串行化的

2. 主从复制的基本原则

  • 每一个slave只有一个master
  • 每个slave只能有一个唯一的服务器ID
  • 每个master可以有多个slave

3. 配置主从复制

3.1 主master

windowlinux的配置相同,只不过修改的配置文件不一样而已。在window中修改my.ini,在linux中修改my.cnf文件。

  • 设置服务器唯一ID。server-id=1
  • 启动二进制日志文件。log-bin=一个路径/mysqlbin
  • 启动错误日志文件。log-err=一个路径/mysqlerr「可选参数」
  • 设置MySQL根目录。basedir='安装目录'「可选参数」
  • 设置临时目录。tmpdir=「可选参数」
  • 设置主机的读写情况。read-only=0读写均可
  • 设置不需要复制的数据库。binlog-lgnore-db=数据库名「可选参数」
  • 设置需要复制的数据库名字。binlog-do-db「可选参数」
3.2 从slave
  • 设置服务器唯一ID。server-id=2
  • 启用二进制文件。
3.3 其他配置
  • 重启mysql服务
  • 关闭防火墙。Linux关闭命令service iptable stop
  • 主机添加授权账户,并刷新;
代码语言:javascript
复制
GRANT REPLICATION SLAVE  ON*.* TO 'zhangsan'@'从机器数据库IP‘ IDENTIFIED BY '123456';
flush privileges;
  • 查询master状态。记录Fileposition的值
代码语言:javascript
复制
show master status ;
  • 从机配置需要启动服务的主机
代码语言:javascript
复制
CHANGE MASTER TO MASTER_HOST='主机IP',
        MASTER_USER='zhangsan',
        MASTER_PASSWORD='123456',
        MASTER_LOG_FILE='File名字',
        MASTER_LOG_POS=Position数字;
  • 从机启动slave
代码语言:javascript
复制
start slave;
# 当Slave_IO_Running:YES
# Slave_SQL_Running:YES
# 这两个字段均为YES的时候才说明主从复制配置成功

stop slave;
#停止主从复制
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 石的三次方 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MySQL锁概述
    • 1. 锁
      • 2. 分类
        • 2.1 表锁(偏读)
        • 2.2 行锁(偏写)
        • 3. 页锁
    • MySQL主从复制
      • 1. MySQL主从复制过程
        • 2. 主从复制的基本原则
          • 3. 配置主从复制
            • 3.1 主master
            • 3.2 从slave
            • 3.3 其他配置
        相关产品与服务
        云数据库 SQL Server
        腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档