高性能MySQL(第二版)第一章 基础篇——读书笔记

来源:互联网 发布:mac qq 截图录屏 失效 编辑:程序博客网 时间:2024/06/05 11:30

一.MySQL服务器架构的逻辑视图




1.连接管理与安全性    
2.优化查询
      1>解析查询
      2>创建内部数据结构(解析树)
      3>优化
                 重写查询
                 决定查询的读表顺序
                 选择需使用的索引   
  • 存储引擎对服务器的查询优化过程有影响。
  • 服务器会“询问”查询缓存。
  • 用户可以通过特殊的关键字给优化器传递各种提示,影响它的优化过程。还可以请求服务器给出优化过程的各种说明.使用户可以知晓服务器是如何进行优化决策的,为用户提供一个参考基准。方便用户重写查询,架构和修改相关配置,便于应用尽可能高效的运行。 
二.并发控制 
      1. 读锁(Read Lock)/写锁(Write Lock)
           某一资源上的读锁是共享的,或者说是互补阻塞的。在同一时间,多个用户可以同时读取同一资源,而互不干扰。
           写锁是排他的,一个写锁会阻塞其他的读锁或者写锁。在给定时间里,只有一个用户能写入资源。

     2.锁粒度(Lock Granularity)
        一种提高共享资源并发性的方法:
        只锁定部分须修改的数据,而不是所有的资源。任何时间,在给定的资源上,被加锁的数据量越小,就可以允许更多的并发修改,只要相互之间互不冲突即可。
        另外一方面,加锁也会消耗系统资源。每一种锁操作,如获得锁,检查锁是否已解除,以及释放锁等。都会增加系统的开销。如果系统花大量时间来管理锁,而不是读/写数据,那么系统整体性能可能会受此影响。
        所谓的锁策略,就是在锁开销和数据安全之间寻求一种平衡,这种平衡也能影响系统性能。

       表锁
          MySQL中,开销最小的锁策略是表锁
          
       行级锁
          行级锁可以带来最大的并发处理(同时也带来最大的开销)。

三.事务
     关于事务,银行应用是一个经典的案例,可以解释事务应用的必要性。假设一银行数据库有两张表,checking表和saving表。现在要从Jane的支票账户(checking Account)转账200美元到她的存款账户(savings Account),那么需要完成至少三步操作:
         1.检查支票存款账户的余额是否大于200$
         2.从支票存款账户余额中减去200$
         3.在存款账户余额中增加200$
     所有的操作被打包到一个事务里,如果某一步失败,就回滚(rollback)所有已完成的步骤。

     可以用start transaction 语句开始一个事务,用COMMIT语句提交整个事务,永久的修改数据,或者用ROLLBACK语句回滚整个事务,取消已做的修改。事务SQL案例如下:
         1.start transaction;
         2.select balance from checking where custom_id = 1005373;
         3.update checking set balance = balance -200.00 where customer_id = 1005373;
         4.update savings set balance = balance + 200.00 where customer_id = 1005373;
         5.commit;
     试想一下,如果数据库服务器在执行第4句语句时,数据库突然崩溃,会发生什么事儿?没有人知道,但是用户可能会损失200元美元。再加入,在执行第3和第4句之间时,另一个进程同时运行,它的母的是要先删除支票账户的全部余额,那么结果可能是,银行根本不知道有这个逻辑事先发生,白白给用户增加了200元存款。

    除非系统通过ACID测试,否则空谈事务概念是不够的,ACID代表了原子性,一致性,隔离性和持久性。这些概念与事务的处理标准密切关联,一个有效的事务处理系统必须满足相关标准。
     a.原子性      b.一致性      c.隔离性    d.持久性

    1.隔离级
          读取未提交内容
          读取提交内容
          可重读
          可串行化
     
     读取未提交内容和可重读的区别:
            如果你从控制的角度来看,两者的区别就比较大:对于前者,只需要锁住满足条件的记录;对于后者,要锁住满足条件及其附近的记录。

    2.死锁 
            死锁是指两个或者多个事务在同一资源上互相占用,并请求加锁时,而导致的恶性循环现象。当多个事务以不同顺序试图对同一资源加锁时,就会产生死锁。任何时间,多个事务同时加锁一个资源,一定产生死锁。例如,设想下列两个事务同时处理StockPrice表:

     事务1 
           start transaction;
            update StockPrice set close = 45.50 where stock_id = 4 and date = '2002-05-01';
            update StockPrice set close = 19.80 where stock_id = 3 and date = '2002-05-02';
            commit;

     事务2
             start transaction;
             update StockPriceset close = 19.80where stock_id = 3and date ='2002-05-02';
             update StockPriceset close = 45.50where stock_id = 4and date ='2002-05-01';
             commit;

        如果很不幸凑巧,每个事务在处理过程中,都执行了第一个查询,又更新了数据行,也加锁了该数据行。接着,每个事务都去视图更新第二个数据行,却发现该行已被(对方)加锁,然后两个事务都开始互相等待对方完成,陷入无限等待中,除非有外部因素介入,才能解除死锁。
        为了解决这个问题,数据库系统事先了各种死锁检测和死锁超时机制。对于更复杂的系统。例如InnoDB存储引擎,可以预测循环相关性,并立即返回错误。这种解决方式实际很有效,否则死锁将导致很慢的查询,其他的解决方式,是让查询到达一个锁等待超时时间,然后再放弃争用,但这种方式不够好。目前InnoDB处理死锁的方法是,回滚拥有最少排他行级的事务(一种对最易回滚事务的大致估算)

三.事务日志
     事务日志可使事务处理过程更加高效,和每次数据以改变就更新磁盘中表数据的方式不同,存储引擎可以先更新数据的内存中得拷贝。这非常快,然后,存储引擎将数据改变记录写入事务日志,它位于磁盘上,因此具有持久性。这相对较快,因为追加日志事件导致的写操作,只涉及了磁盘很小区域上得顺序I/O(Sequential I/O),而替代了写磁盘中表所需要的大量随机I/O(Random I/O). 最后,相关进程会在某个事件把表数据更新到磁盘上。因此大多存储引擎都选用了这种技术,也是通常所说的预写式日志,利用两次磁盘写入操作把数据改变磁盘。

四,多版本并发控制(MVCC , Multiversion Concurrentcy Control)


五.为自己的应用选择合适的数据库引擎
     在设计基于MySQL的应用时,要决定选择何种存储引擎来存储数据。如果不在设计阶段就考虑这个问题,在后续工作中可能就会面临复杂的问题。用户可能会发现默认配置的引擎并不能满足自己的某种需要,比如事务。或者,应用产生的混合读写查询需要更细粒度的加锁机制,而不是MyISAM提供的表锁。
     引擎的选择可以基于每一张表,因此,需要清醒的考虑如何使用每一张表,以及如何存储数据。这种考虑也有助用户从整体上正确的理解应用,并且预测应用的增长需求,理解和掌握相关信息为自己的应用选择合适的引擎。
                                      
原创粉丝点击