zoukankan      html  css  js  c++  java
  • 第28章 锁

    这个章节讨论 MYSQL 如何使用locking 还解决并发的数据访问。它覆盖以下几个主题:


    1.Locking 内容


    2.使用显示的表锁


    3.使用锁顾问


    28.1 Locking 内容








    MYSQL server 使用多线程结果使它可以为多个并发的客户端提供服务。


    对于每个客户端的连接,server 分配一个线程作为连接处理器。


    如果每个客户端访问不同的表,他们不需要相互干涉。


    然而,当多个客户端尝试访问同一个表的时候, server需要协调客户端连接。


    否则,就会产生问题,比如一个客户端在改变记录时另外的客户端在读他们


    或者2个客户端对相同的行同时做改变。为了改变这个问题MYSQL使用locking


    Locking 是一个机制 阻止发生同时的数据访问。


    Locks有server管理, 它在数据上枷锁代表客户端限制访问直到锁被释放。




    Lock 允许通过持有锁的客户端访问数据


    锁的机制是串行化访问数据  因此多个客户端需要执行冲突的操作,都必须等待








    不是所有类型的并发访问都会产生冲突,因此 锁的类型需要是依赖客户端是去读还是写




    1.如果客户端是要去读取数据,另外的客户端也要读取相同的数据 不会产生冲突,




    他们可以在同一时间同时读取。然而,如果另外的客户端需要修改数据 必须等待读完成




    2. 如果客户端需要写数据,所有的客户端必须等待写完成,不管那些客户端是要读还是写




    换句话说,读必须阻塞写,但是不堵塞其他readers.一个写必须堵塞readers和writes.




    read locks 和write locks 允许那些限制被强制。




    Locking 允许客户端等待访问直到等到认为是安全的来处理,


    换句话说,locks 阻止数据冲突通过不允许并发冲突的改变和读取正在改变的数据。




    数据上的锁可以显示的和隐示的获得:


    1.对于客户端没有特别指定获得LOCKS,MYSQL server 隐示的需要Locks


    用于处理客户端语句的安全。 比如,server 需要一个读的lock 当客户端执行select 语句和一个写的lock


    当客户端执行一个INSERT语句的时候,隐示的LOCKS是需要的只用于单个语句周期。








    2.如果隐示的锁是不充足的对于客户端的目的,它可以显示的管理locks通过使用lock table


    和unlock table来释放。


    显示的locking 可能是必须的 当客户端需要执行一个操作,跨越多个语句 不能被其他客户端冲突。






    比如,一个应用可能从表里选择一个值然后用它来判断其他表的要更新的记录


    用隐示locking ,有可能其他客户端执行它们,可能改变了第一次客户端的操作(丢失更新)


    为了避免这个,第一个客户端可以显示的放置锁。




    另外类型的锁是顾问的,或者合作的,lock. 顾问锁不锁数据 他们不阻止通过客户端访问数据


    除了相互冲突的程度。


    不像隐式和显示的数据锁,顾问锁不是有server 管理。客户端管理顾问锁使用一些函数调用来协调他们。


    数据锁在MYSQL里发生在不同的层面, 显示锁 需要Lock tables语句


    隐式的锁, 锁的级别取决于MYSQL的引擎:




    1. MYISAM,MEMORY 和merge 表在表级别锁


    2.BDB 表在PAGE 级别锁定




    3.InnoDB 是行级锁


    不同级别的lock力度有不同的并发特性:


    1.表锁不被描述为页或者行锁对于冲突在一个读写环境。一个table lock 防止其他客户端对表做任何改变,


    尽管客户端持有锁不能访问其他客户端需要修改的部分。


    页级和行级锁,客户端锁住一叶或者行不会阻止其他客户端修改其他的页或者行








    2.死锁 不能发生在表锁 但是可以在页锁或者行锁。比如,在行锁模式,




    两个客户端可能相互需要一个行锁在不同的行,如果他们每个都试图修改被另一个回话持有的记录,


    没有一个客户端能够处理 这个被叫做死锁。




    在表锁里,server可以server可以判断哪种类型的锁是需要的在执行语句前,因此死锁永远不会发生。


    (一个异常时可能的当客户端使用游标,因为游标必须持有一个打开的锁用于客户断跨越所有的语句。


    假设客户端1 打开了一个游标用于读取表数据t1




    客户端t2 打开一个游标用于读取表t2.当游标被打开后,如果每个客户端尝试更新数正在被其他回话读取的数据,


    死锁也会发生)




    28.2  显示的表锁


    客户端管理显示的table locks 用2个语句 lock tables 需要table locks


    和unlock tables 释放他们,获得显示的locks 在某些情况下是有用的:




    1. 一个隐式的表锁 持续周期是一个简单查询,不适用于执行一个多语句的更新 需要和其他客户端没有冲突。


    首先,server做更少的工作来得到和释放锁,因为它不需要处理每个语句。


    它简单的需要所有需要锁的在操作开始的时候,结束后全部释放。


    第二,对那些修改数据的语句,index flush是减少了。  比如,如果你要执行多个INSERT 语句


    使用隐式的锁,index flush跟着每个语句发生。


    如果你lock table使用显示的然后执行所有的inert,index flushing 只发生一次当你释放锁的时候。




    LOCK TABLES 语句意味着每个表被locked 需要锁的类型


    下面的语句需要一耳光read lock 在country 表和一个写的Lock在City 表:


    LOCK TABLES Country READ,City WRITE;






    为了使用LOCK TABLES,你必须有LOCK TABLES的权限,和SELECT 权限用于每个被锁的表


    如果任何一个表已经被Lock正在使用,LOCK TABLES 会阻塞。它不返回知道获得所有需要的锁




    如果你使用多个表当你需要一个显示的锁,你必须同时锁住他们因为你不能使用任何未锁定的表




    当你持有显示锁的时候,同时你必须锁住所有的表在一个单独的lock 语句里。


    LOCK TABLES 释放任何锁,你不能执行多次来获得多个锁:


    1.READ


    Locks 一个表用于读,A READ LOCK 锁住表用于read查询比如SELECT 从表获得数据


    它不允许写操作 比如INSERT,DELETE或者UPDATE 修改表数据


    SESSION 1:
    mysql> lock table t1 READ;
    Query OK, 0 rows affected (0.00 sec)






    SESSION 2:
    mysql> insert into t1 values(3);




    mysql>  insert into t1 values(3);
    ERROR 1099 (HY000): Table 't1' was locked with a READ lock and can't be updated


    甚至获得锁的客户端也不能执行。 当一个表锁用于read,另外的客户端可以同时读取表数据,


    但是没有客户端可以写。




    2.WRITE


    Locks一个表用于写,一耳光写的锁是一个排它锁。它可能只被需要当一个表不被使用




    一旦使用,只有一个客户端持有写锁能对表进行读写操作。




    SESSION 1:


    mysql> lock table t1 write;
    Query OK, 0 rows affected (0.00 sec)


    SESSION 2:
    mysql> select * from t1; ---hang






    mysql>  show full processlist;
    +----+------+-----------+------+---------+------+-------+-----------------------+
    | Id | User | Host      | db   | Command | Time | State | Info                  |
    +----+------+-----------+------+---------+------+-------+-----------------------+
    | 11 | test |           | NULL | Sleep   | 1616 |       | NULL                  |
    | 14 | test |           | NULL | Sleep   |  197 |       | NULL                  |
    | 16 | test |           | NULL | Sleep   |    1 |       | NULL                  |
    | 19 | root | localhost | test | Query   |    0 | init  | show full processlist |
    | 20 | root | localhost | test | Sleep   |   10 |       | NULL                  |
    +----+------+-----------+------+---------+------+-------+-----------------------+
    5 rows in set (0.00 sec)




    3.READ LOCAL:


    LOCKS 一个表用于读,单数允许并发的插入,一个并发的INSERTS是一个异常对于 readers block writers




    原则, 如果只应用于MyISAM表。 如果一个MyISAM表有空洞由于删除或者修改数据


    insert 经常占据表的尾部。在这种情况下,一个客户端从表里读取数据可以使用READ LOCK 锁


    允许其他用户来向表里插入数据 当客户端持有read lock 读取数据时




    当 MyISAM 表确实有空洞,你可以重新移动他们通过使用OPTIMIZE TABLE 来进行碎片整理。




    你可能需要一个READ LOCK 锁用于碎片整理 MyISAM 表, 或者对于一个non-MyISAM表


    在这些例子中,冲突的insert 是不允许的,这时候的Lock就想普通的read lock.




    4.LOW_PRIORITY WRITE:




    Locks 一个表用于写,但是需要一个相对低优先级的lock.




    如果客户端必须等待Lock,其他客户端需要read locks 在等待期间是被允许首选得到它们需要的锁的




    普通的write lock请求是满足的当没有其他客户端使用表的时候




    如果其他客户端正在使用表当请求来式,它会等待直到那些客户端完成。




    一个LOW_PRIORITY_WRITE lock 请求需要等待热议一个新的读请求的到来 当lock 请求是挂起的时候


    释放显示的锁,执行一个unlock tables语句,这个语句没有带tables


    因为它会释放所有被客户端持有的显示的锁




    客户端持有的显示锁被释放如果客户端执行了另一个lock tables语句.






    locks 不能通过连接维持;如果客户端突然中断,且有任何没释放的锁,server隐含的释放锁。




    一个具有超级权限的管理员能中断客户端连接通过kill 语句,也可以释放锁。




    只有客户端持有锁需要LOCK TABLES 能释放锁,另外的客户端不能释放它


    换句话说,如果你需要一个锁,它属于你的直到你放弃它  另外的客户端不能强制你释放它。


    Table locks 通过事务来影响 返回来也一样。




    一个事务的开始 用START TRANSACTION 引起一个隐式的UNLOCK TABLES。


    执行一个LOCK TABLES语句将隐式的提交任何事务。如果你已经锁住了任何表,




    执行一个UNLOCK TABLES语句将隐式的提交任何事务


    28.3  顾问锁


    一个顾问锁是一个协同锁。 一个顾问锁没有能力阻止数据被其他客户端访问,但是它是基于


    所有客户端会使用一个商定的转换为协同的使用一个资源的协议。




    这个约定是lock的名字,是一个简单的字符窜。当名字被锁定,顾问锁是被认为是合适的


    每个其他协同客户端限制执行任何动作




    顾问锁是用一组函数调用实现的,为了得到顾问锁 使用GET_LOCK() 函数


    mysql> select get_lock('my lock',5);
    +-----------------------+
    | get_lock('my lock',5) |
    +-----------------------+
    |                     1 |
    +-----------------------+
    1 row in set (0.00 sec)


    第一个参数是字符串用于指定需要锁定的名字,第2个参数是超时值单位秒 表明
    等待多长时间。


    GET_LOCK() 返回1表示成功,0超时发生表明锁不能获得 NULL表示发生了错误





































































  • 相关阅读:
    python笔记2-python常见数据类型(一)
    python笔记1-环境安装和基本语法
    selenium自动化脚本错误总结
    Postman-Post请求示例
    用PHP删除ftp下载导致的文件空行
    JS实现鼠标悬浮,显示内容
    asp.net中处理程序调用HttpContext.Current.Session获取值出错
    自动化创建tornado项目
    fabric运维
    Python3虚拟环境安装:virtualenv、virtualenvwralpper
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13351768.html
Copyright © 2011-2022 走看看