MySQL的锁(1)

摘要:
MySQL的锁管理机制:元数据元数据锁:在表缓存中实现,为DDL提供隔离操作。MySQL有三个锁定级别:页面级别、表级别和行级别。b、 写入MyISAM表(添加写锁)将阻止其他进程读取和写入同一表。只有当释放写锁时,其他进程才能执行读写操作。MyISAM存储引擎有一个系统变量concurrent_insert,专门用于控制其并发插入行为。其值可以分别为0、1或2。这也是MySQL的默认设置。

    锁机制是数据库系统区别于文件系统的一个关键特性,他可以确保用户能以一致的方式读取和修改数据。

    为了保证一致性,必须有锁的介入。MySQL操作缓冲池中的LRU列表,删除、添加、移动LRU列表中的元素等地方也都适用锁,从而允许对多种不同资源的并发访问。

    打个比方,我们到淘宝上买一件商品,商品只有一件库存,这个时候如果还有另一个人买,那么如何解决是你买到还是另一个人买到的问题?

image

    这里肯定要用到事物,我们先从库存表中取出物品数量,然后插入订单,付款后插入付款表信息,然后更新商品数量。在这个过程中,使用锁可以对有限的资源进行保护,解决隔离和并发的矛盾。   

MySQL的锁管理机制:

  1. Meta-data元数据锁:在table cache缓存里实现的,为DDL(Data Definition Language)提供隔离操作。一种特别的meta-data元数据类型,叫Name Lock。(SQL层)
  2. 表级table-level数据锁(SQL层)
  3. 存储引擎特有机制 — row locks行锁,page locks页锁,table locks表级,版本控制(在引擎中实现)
  4. 全局读锁 — FLUSH TABLES WITH READ LOCK(SQL层)

上张图:

image

MySQL的锁执行流程:

image

  • 计算语句使用到的所有表
  • 在每个表:打开open表 — 从table cache缓存里得到TABLE对象,并在此表加上meta-data元数据锁
  • 等待全局读锁后改变数据
  • 在每个表:锁lock表 — 在表加上table-level数据锁
  • 执行语句:调用:handler::write_row()/read_rnd()/read_index(),等;隐式地调用引擎级engine-level锁机制
  • 在每个表:释放表的数据锁
  • 在每个表:释放表的DDL锁并把表放回table cache缓存里
  • DDL语句也是一样,没有典型的执行计划。

MySQL三种锁地级别:页级、表级、行级。

三种锁地特性:

    表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
    行级锁:开销稍大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
    页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

   

    在执行SQL语句时,会实现存储引擎内部锁,比如InnoDB存储引擎的“行锁”(MyISAM存储引擎只支持表锁,而InnoDB存储引擎支持行锁。实际上,行锁并不总是会增加开销,只有当实现本身增加开销时,行锁才会增加开销)。

表锁:

手动增加表锁:

lock table XXX read(write);

释放表锁:

unlock tables;

   image

表级锁性能监控:

show status like ‘table%’;

image如果Table_locks_waited的值比较高,则说明存在着比较严重的表锁争用情况。

表级锁的锁模式:表共享读锁(Table Read Lock)和 表独占写锁(Table Write Lock)

    MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁。
    所以对MyISAM表进行操作,会有以下情况:
         a、对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
        b、对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。

    简而言之,就是读锁会阻塞写,但是不会堵塞读。而写锁则会把读和写都堵塞。

关于表锁并发插入 
    原则上数据表有一个读锁时,其它进程无法对此表进行更新操作,但在一定条件下,MyISAM表也支持查询和插入操作的并发进行。
    MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。
        a、当concurrent_insert设置为0时,不允许并发插入。
        b、当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。
        c、当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。

表锁地优化:

    使用表级锁定在锁定实现的过程中比实现行级锁定或页级锁定所带来的附加成本要小,锁定本身所消耗的资源也是最少的。但是由于锁定的颗粒度比较大,所以造成锁定资源的争用情况也会比其他的锁定级别都要多,从而在较大程度上会降低并发处理能力。所以表锁优化,最关键的是如何让其提高并发度。由于锁定级别是不可能改变的了,所以首先需要尽可能地锁定的时间变短,然后就是让可能并发进行的操作尽可能地并发。

1.缩短锁定时间:

    1)尽量减少大的复杂的Query,将复杂的Query分拆成几个小的Query分步进行;

    2)尽可能地建立足够高效的索引,让数据检索更迅速;

    3)尽量让MyISAM存储引擎的表至存放必要的信息,控制字段类型;

    4)利用合理的机会优化MyISAM表数据文件。

    2、分离能并行的操作

2.合理利用上面提到的concurrent_insert
3.合理利用读写优先级:

    MyISAM的表级锁定对于读和写是有不同优先级设定的,默认情况下是写优先级要大于读。所以,可以根据系统环境的差异决定读与写的优先级。如果系统是一个以读为主,而且要优先保证查询性能的话,可以通过设置系统参数选项low_priority_updates=1,将写的优先级设置为比读低,即告诉MyISAM尽量优先处理读请求。当然,如果系统需要优先保证数据写入的性能的话,则不用设置low_priority_updates参数了。

    以上笔记参考网络资料以及《MySQL技术内幕:InnoDB存储引擎》,如有谬误请指正

    下一次整理一下行锁的笔记~

免责声明:文章转载自《MySQL的锁(1)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇java oracle thin 和 oci 连接方式实现多数据库的故障切换Centos7修改dns的方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Mysql报错java.sql.SQLException:null,message from server:"Host '27,45,38,132' is not allowed to connect

Mysql报错java.sql.SQLException:null,message from server:"Host '27,45,38,132' is not allowed to connect 远程连接mysql数据库,出现异常: null,message from server:"Host '27,45,38,132' is not allowe...

postgres 行列转换

行转列 imos=# create table test_split_to_table(id int, name_list varchar); CREATE TABLE imos=# insert into test_split_to_table values(1,'a;b;c'),(2,'d;e;f'); INSERT 0 2 imos=# imos=#...

肝了它!Oracle SQL性能优化技巧大总结

Oracle SQL性能优化技巧大总结 (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效):Oracle的解 析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。假如有3个以上的表连接查询, 那就需要...

mysql启动报错。mysql is running,but pid file not found解决办法

之前数据库一直好好的,今天突然不能用了,不知为何。后来在网上找答案终于解决了。 查看状态: /etc/init.d/mysql status /etc/init.d/mysql statusMySQL is not running, but lock file (/var/lock/subsys/mysql[FAILED] 过滤MySQL进程后kill掉。...

如何让您的php也支持pthreads多线程

  我们常常会碰到这样一种情况,开发环境在windows下开发,而生产环境确是linux。windows下能正常运行,上传到linux后却无法好好地玩耍了。然后开始了一轮尼玛式的疯狂的查找原因,最后发现是服务器环境问题。这时只能默默地爆一句shit。最近在用php多线程开发一个小功能也碰到类似的问题,在此记录一下。   1、查找资料发现php5.3或以上,...

HTML表格基础详解

       在现在 div 大行其道的时代,table 这个标签似乎很少被人提及,到处都是 div+css 布局的书以及博客文章,但其实 table 以及连带的其他表格标签依然在网页中占很重要的地位,特别是后台展示数据的时候表格运用是否熟练就显得很重要,一个清爽简约的表格能够把繁杂的数据表现得很有条理,虽然 div 布局也可以做到,但是总没有表格来得方便...