mysql5.7官网直译锁操作优化--并发添加,元数据锁,外部闭锁

来源:互联网 发布:淘宝店怎么推广宣传 编辑:程序博客网 时间:2024/05/20 07:35
8.11.3 Concurrent Inserts 并发插入
MyISAM存储引擎支持并发插入从而来减少对读写对给出表的竞争:如果一张MyISAM表的数据文件没有漏洞存在(也就是在表中删除了中间的行),一个插入语句能够被执行用于添加一行到表的末尾在同一时间查询语句可以读取表中的数据。如果有多个插入语句,他们将被排队并且顺序执行,并发查询语句。并发插入的结果可能并不会立马可见。
系统变量concurrent_insert能够设置用来修改并发插入的过程。默认的话,变量值是AUTO(or 1)并且并发处理会按描述的方式处理。如果concurrent_insert的值设置为NEVER(or 0),那么并发插入不可用。如果变量的值是ALWAYS(or 2),并发插入在表的末尾是被允许的即使表的中间有被删除的行。了解关于concurrent_insert系统变量的描述。
如果你使用了二进制日志,并发插入会被转为正常的插入对于CREATE ... SELECT OR INSERT ... SELECT 语句。这样的完成保证你能够根据日志的备份操作能够再次创建一个完整的表。具体请看5.4.4的二进制日志。另外,这些语句一个读锁被放在被查询的表比方说插入语句会锁表。其影响就是并发插入表的操作必须等待直到锁释放才能开始执行。
通过LOAD DATA INFILE,如果你的并发性在MyISAM表满足并发插入的条件(也就是,表中没有空白块),其他session能够检索数据从表中通过LOAD DATA的执行。使用CONCURRENT选项对LOAD DATA有一点影响,即使是没有其他session在同一时间使用表。
如果你指定额特别高的优先级,它覆盖了--low-priority-updates选项的影响,服务器是以此项启动的。这也会使得并发插入不可用。
对于表锁,READ LOCAL和READ不同是READ LOCAL允许无冲突插入语句(并发插入)执行在锁存在的情况下。然而,如果你持有锁,并且你通过使用过程在服务器外边操作数据库则不能使用。
-----------------------------------
8.11.4 Metadata Locking 元数据锁
MySQL使用元数据锁来管理并发权限方法数据库对象并且保证数据一致性。元锁应用不仅仅在表,而且在schemas,存储程序(程序,函数,触发器和scheduled 事件),和表空间。
元数据锁涉及到一些开销,随着查询量的增加而增加。元数据的竞争也会增加当多个查询试着访问相同的对象的情况下。
元数据锁并不是表定义缓存的替代品,并且它的互斥器和锁不同于LOCK_open 互斥器。下面的描述提供了一些关于元数据锁如何工作的信息。
为了保证事物串行化,服务器一定不允许一个session来执行一个数据定于语句在表中,其中表被用于一个未完成的明显或者是隐藏的依据开始的其他session的事物。服务器的实现通过要求在表中使用一个元数据锁对应一个事物并且延迟释放锁直到事物结束。一个在表中的元数据锁会阻止对表结构的改变。这种锁方法表明表中已经有一个sesion在执行一个事物,而其他session不能使用DDL语句直到事物结束。
这个原则的应用不仅仅是对事物表,而且适用非事物表。支持一个session开始一个事物使用在事物表t和非事物表nt如下:
START TRANSACTION;
SELECT * FROM t;
SELECT * FROM nt;
服务器持有元数据锁在表t和nt中直到事物结束。如果另一个session尝试一个DDL或者写锁操作在表中,则会被阻塞直到元数据锁释放事物结束。例如,第二个session被阻塞如果它尝试任何这些操作:
DROP TABLE t;
ALTER TABLE t ...;
DROP TABLE nt;
ALTER TABLE nt ...;
LOCK TABLE t ... WRITE;
同样的行为应用对于LOCK TABLES ...READ.也就是,明显的或是隐藏的开始的事物用于更新任何表(事物或者非事物)将会阻塞并且通过LOCK TABLES ...READ语句对于表的操作。
如果服务要求元数据锁对于一个语句也就是语法上允许但是执行失败了,它不会提前释放一个锁。锁的释放依然需要等到事物结束因为失败的语句也会写入一个二进制日志并且锁会保持日志的一致性。
在自动提交模式,每一个语句实际上都是一个完整的事物,所以元数据锁要求一直持有直到语句结束。
对于一个PREPARE语句要求的元数据锁一旦语句已经被准备好则锁会被释放,即使preparation发生在一个多语句事物。
---------------------------
8.11.5 External Locking 外部闭锁
外部闭锁是使用文件系统锁来管理对MyISAM数据库表的多程序竞争。外部闭锁被用于如下情形其中一个单一的程序如MySQL服务器不可能只有一个请求访问数据库表。如下举例:
>如果你跑多个服务使用相同的数据库目录(不推荐如此设置),每一个服务必须有外部闭锁可以用。
>如果你使用myisamchk来完成表的维护操作在MyISAM表,你必须要保证服务不在允许中,或者是服务有外部闭锁可以用从而保证表文件合作通过myisamchk来访问表。同时保证使用myisampack来打包myisam表。如果服务运行在外部闭锁可以用的情况下,你能够使用myisamchk在任何时候用于读操作例如检查表。在这种情况下,如果服务试着更新表其中myisamchk来完成,服务将会等待myisamchk来完成之后再继续。
如果你使用myisamchk到写操作例如J纠正和优化表,或者如果你使用myisampack来打包表,你必须总是抱着mysqld服务没有使用表。如果你不停止mysqld,之后完成一个mysqladmin flush-tables 在你执行myisamchk之前。你的表也许被损坏如果服务和myisamchk同时访问表。


由于外部闭锁的影响,每一个要访问表的程序都必须在访问之前获得一个文件系统所。如果所有必须的锁不能被得到,程序将被阻塞直到获得锁(当前持有锁的程序释放了锁)。
外部闭锁会影响服务器性能因为服务器有时必须等待其他程序在它访问表之前。
外部闭锁并不是必须的如果你在给出的一个数据文件目录里运行一个单一的服务并且没有其他程序如myisamchk在服务运行过程中修改表。如果你是只读表对于其他程序,外部闭锁也不需要。尽管myisamchk也许会告警如果服务在myisamchk在读取表的时候改变了表。
为了使用myisamchk,使得外部锁失效,你必须要么在myisam执行的过程中停止运行服务,要么在运行myisamchk之前锁并刷出表。(请看8.12.1的系统因素)为了避免这种要求,使用CHECK TABLE 和 REPAIR TABLE 语句来简化和修复MyISAM表。
对于mysqld,外部闭锁是通过系统变量skip_external_locking的值来控制的。当这个变量可用,外部闭锁不可用,反之亦然。外部闭锁默认不可用。
外部闭锁的使用可以被控制在服务启动的时候使用--external-locking 或者 --skip-external-locking选项。
如果你使用外部闭锁选项来更新Myisam表从多个mysql程序中,你必须保证下面的条件被满足:
1)对于其他程序更新了的表,查询不能使用查询缓存。
2)服务开始时不能使用--delay-key-write-all选项或者使用DELAY_KEY_WRITE=1表选项对于任何共享表。否则,索引变体可能发生。
最容易满足这些条件的方法是总是使用--external-locking 和--delay-key-write=OFF和--query-cache-size=0.(这不会默认完成因为在许多设置中它是有用的有一个之前的混合的选项)
到这里关于锁的优化就结束了。接下来我们要说明的是Chapter 11 Data Types 数据类型。
阅读全文
0 0