美高梅网站是多少开发进阶篇系列,Innodb表导致
分类:美高梅-数据

二. 关于死锁

  在myisam中是使用的表锁,在获得所需的全部锁时, 要么全部满足,要么等待,因此不会出现死锁。下面在innodb中演示一个死锁例子:

会话1

会话2

SET autocommit =0

SELECT * FROM city  WHERE city_id=103 FOR UPDATE;

SET autocommit =0

SELECT * FROM cityNew  WHERE city_id=103 FOR UPDATE;

-- 因为会话2 已获得排他锁, 该语句等待

 SELECT * FROM cityNew  WHERE city_id=103 FOR UPDATE;

 

 

-- 死锁

 SELECT * FROM city  WHERE city_id=103 FOR UPDATE;

错误代码: 1213

Deadlock found when trying to get lock; try restarting transaction

  上面案例中, 两个事务都需要获得对方持有的排他锁才能继续完成事务,这种循环锁等待就是典型的死锁。 发生死锁后,innodb会自动检测到,并使一个事务释放锁并回退(回滚),另一个事务得锁完成事务。

案例描述 在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志。
两个sql语句如下: (1)insert into backup_table select * from source_table
(2)DELETE FROM source_table WHERE Id>5 AND titleWeight<32768 AND joinTime<'$daysago_1week'
teamUser表的表结构如下:
PRIMARY KEY (`uid`,`Id`),
KEY `k_id_titleWeight_score` (`Id`,`titleWeight`,`score`),
ENGINE=InnoDB
两语句对source_table表的使用情况如下:

要使用lock tables,您必须拥有相关表的lock tables权限和select权限。

一. 什么时候使用表锁

  对于INNODB表,在绝大部分情况下都应该使用行锁。在个别特殊事务中,可以考虑使用表锁(建议)。
  1. 事务需要更新大部份或全部数据,表又比较大,默认的行锁不仅使这个事务执行效率低,可能造成其他事务长时间锁等待和锁冲突,这种情况考虑使用表锁来提高事务的执行速度(具我在sql server中的经历,该大表有上100w,删除40w,表锁有时会造成长时间未执行完成. 还是使用分批来执行好)。
  2. 事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚。这种情况可以考虑一次性锁定事务涉及的表,避免死锁,减少数据库因事务回滚带来的开销。
  使用表锁注意两点
    (1) lock tables虽然可以给innodb加表锁,但表锁不是由innodb存储引擎层管理,则是由上层mysql server负责。仅当autocommit=0, innodb_table_locks=1(默认设置)时,innodb层才知道mysql加的表锁,mysql server也才能感知innodb加的行锁。
    (2) 用lock tables对innodb表加锁时要注意, 要将autocommit 设置为0,否则mysql 不会给表加锁; 事务结束前,不要用unlock tables释放表锁,因为它会隐式的提交事务。 commit 或rollback 并不能释放用lock tables 加的表锁。必须用unlock tables释放表锁。

    下面在5.7版本数据库中,会话2也会阻塞,按上面说法是不会阻塞的,因为会话1没有设置SET autocommit =0(以后在论证)

-- 会话1 给city加表锁读,  不设置  SET autocommit =0
  LOCK TABLES city READ

  --  会话2 会阻塞
 UPDATE city SET CityCode='005' WHERE city_id=103  

  -- 会话1提交
 COMMIT;
 -- 会话1 释放表锁
 UNLOCK TABLES;

当使用非聚簇索引时,会根据得到的主键值遍历聚簇索引,得到相应的记录。
4.2四种死锁情况 在InnoDB中,使用行锁机制,于是,锁通常是逐步获得的,这就决定了在InnoDB中发生死锁是可能的。
即将分享的四种死锁的锁冲突分别是:不同表的相同记录行索引锁冲突、主键索引锁冲突、主键索引锁与非聚簇索引锁冲突、锁升级造成锁队列阻塞。
不同表的相同记录行锁冲突 案例:两个表、两行记录,交叉获得和申请互斥锁
美高梅网站是多少 1

如果您执行commit或执行不能命名保存点的rollback,则当前事务的所有保存点被删除。

三. 锁等待查看    

  涉及外部锁或表锁,innodb并不能完全自动检测到死锁,这需要设置锁等待超时参数innodb_lock_wait_timeout来解决(设置需慎重),这个参数并不是只用来解决死锁问题,在并发下,大量事务无法立即获得所需锁而挂起,将占用大量资源,甚至拖跨数据库 (在sql server中默认是-1 总是等待)。

--  下面是5秒  获取不到锁就超时
SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout';

美高梅网站是多少 2

美高梅网站是多少 3

·         create table, create database drop database, truncate table, alter function, alter procedure, create function, create procedure, drop function和drop procedure等语句会导致一个隐含提交。

Gdb结果显示,语句(1)(2)加锁的获取记录为多行,即逐行获得锁,这样就解释了语句(2)获得了主键索引锁还再次申请主键索引锁的情况。
由于语句(1)使用了主键索引,而语句(2)使用了非聚簇索引,两个事务获得记录行的顺序不同,而加锁的过程是边查边加、逐行获得,于是,就会出现如下情况:

mysql> lock table t write, t as t1 write;mysql> insert into t select * from t;error 1100: table 't' was not locked with lock tablesmysql> insert into t select * from t as t1;如果您的查询使用一个别名引用一个表,那么您必须使用同样的别名锁定该表。如果没有指定别名,则不会锁定该表。

(说明:”789200″为非聚簇索引,”200″为主键索引)

read local和read之间的区别是,read local允许在锁定被保持时,执行非冲突性insert语句(同时插入)。但是,如果您正打算在mysql外面操作数据库文件,同时您保持锁定,则不能使用read local。对于innodb表,read local与read相同。

美高梅网站是多少 4

注意,下面是对事务表使用lock tables的说明:

主键索引锁冲突 案例:本文案例,产生冲突在主键索引锁上
条件:
A、 两sql语句即两事务操作同一个表、使用不同索引
B、 申请的锁互斥
C、 操作多行记录
D、 查找到记录的顺序不一致

使用lock tables的主要原因是仿效事务,或在更新表时加快速度。这将在后面进行更详细的解释。

避免死锁的方法 InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句提供非锁定读。这些特色增加了多用户部署和性能。
但其行锁的机制也带来了产生死锁的风险,这就需要在应用程序设计时避免死锁的发生。以单个SQL语句组成的隐式事务来说,建议的避免死锁的方法如下:
1.如果使用insert…select语句备份表格且数据量较大,在单独的时间点操作,避免与其他sql语句争夺资源,或使用select into outfile加上load data infile代替 insert…select,这样不仅快,而且不会要求锁定
2. 一个锁定记录集的事务,其操作结果集应尽量简短,以免一次占用太多资源,与其他事务处理的记录冲突。
3.更新或者删除表格数据,sql语句的where条件都是主键或都是索引,避免两种情况交叉,造成死锁。对于where子句较复杂的情况,将其单独通过sql得到后,再在更新语句中使用。
4. sql语句的嵌套表格不要太多,能拆分就拆分,避免占有资源同时等待资源,导致与其他事务冲突。
5. 对定点运行脚本的情况,避免在同一时间点运行多个对同一表进行读写的脚本,特别注意加锁且操作数据量比较大的语句。
6.应用程序中增加对死锁的判断,如果事务意外结束,重新运行该事务,减少对功能的影响。

13.4.4. savepoint和rollback to savepoint语法
savepoint identifierrollback [work] to savepoint identifierrelease savepoint identifierinnodb支持sql语句savepoint, rollback to savepoint, release savepoint和自选的用于rollback的work关键词。

条件:
A、 两事务分别操作两个表、相同表的同一行记录
B、 申请的锁互斥
C、 申请的顺序不一致

error 1181: got error 153 during rollbackrelease savepoint语句会从当前事务的一组保存点中删除已命名的保存点。不出现提交或 回滚。如果保存点不存在,会出现错误。

美高梅网站是多少 5

begin和begin work被作为start transaction的别名受到支持,用于对事务进行初始化。start transaction是标准的sql语法,并且是启动一个ad-hoc事务的推荐方法。begin语句与begin关键词的使用不同。begin关键词可以启动一个begin...end复合语句。后者不会开始一项事务。请参见20.2.7节,“begin ... end复合语句”。

美高梅网站是多少 6
根据死锁记录的结果,可以看出确实是这两个语句发生了死锁,且锁冲突发生在主键索引上。那么,为什么两个sql语句会存在锁冲突呢?冲突为什么会在主键索引上呢?语句(2)得到了主键索引锁,为什么还会再次申请锁呢?
锁冲突分析
2.1 innodb的事务与行锁机制
MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关,MyISAM不支持事务、采用的是表级锁,而InnoDB支持ACID事务、 行级锁、并发。MySQL默认的行为是在每条SQL语句执行后执行一个COMMIT语句,从而有效的将每条语句作为一个单独的事务来处理。
2.2 两语句加锁情况 在innodb默认的事务隔离级别下,普通的SELECT是不需要加行锁的,但LOCK IN SHARE MODE、FOR UPDATE及高串行化级别中的SELECT都要加锁。有一个例外,此案例中,语句(1)insert into teamUser_20110121 select * from teamUser会对表teamUser_20110121(ENGINE= MyISAM)加表锁,并对teamUser表所有行的主键索引(即聚簇索引)加共享锁。默认对其使用主键索引。
而语句(2)DELETE FROM teamUser WHERE teamId=$teamId AND titleWeight<32768 AND joinTime<'$daysago_1week'为删除操作,会对选中行的主键索引加排他锁。由于此语句还使用了非聚簇索引KEY `k_teamid_titleWeight_score` (`teamId`,`titleWeight`,`score`)的前缀索引,于是,还会对相关行的此非聚簇索引加排他锁。
2.3 锁冲突的产生 由于共享锁与排他锁是互斥的,当一方拥有了某行记录的排他锁后,另一方就不能其拥有共享锁,同样,一方拥有了其共享锁后,另一方也无法得到其排他锁。所 以,当语句(1)、(2)同时运行时,相当于两个事务会同时申请某相同记录行的锁资源,于是会产生锁冲突。由于两个事务都会申请主键索引,锁冲突只会发生 在主键索引上。
常常看到一句话:在InnoDB中,除单个SQL组成的事务外,锁是逐步获得的。那就说明,单个SQL组成的事务锁是一次获得的。而此案例中,语句(2) 已经得到了主键索引的排他锁,为什么还会申请主键索引的排他锁呢?同理,语句(1)已经获得了主键索引的共享锁,为什么还会申请主键索引的共享锁呢?
死锁记录中,事务一等待锁的page no与事务二持有锁的page no相同,均为218436,这又代表什么呢?
我们的猜想是,innodb存储引擎中获得行锁是逐行获得的,并不是一次获得的。下面来证明。
死锁产生过程分析 要想知道innodb加锁的过程,唯一的方式就是运行mysql的debug版本,从gdb的输出中找到结果。根据gdb的结果得到,单个SQL组成的事 务,从宏观上来看,锁是在这个语句上一次获得的,但从底层实现上来看,是逐个记录行查询,得到符合条件的记录即对该行记录的索引加锁。
Gdb结果演示如下:

start transaction with consistent snaps教程hot;with consistent snapshot子句用于启动一个一致的读取,用于具有此类功能的存储引擎。目前,该子句只适用于innodb。该子句的效果与发布一个start transaction,后面跟一个来自任何innodb表的select的效果一样。请参见15.2.10.4节,“一致的非锁定读”。

美高梅网站是多少 7

set autocommit=0;通过把autocommit变量设置为零,禁用autocommit模式之后,您必须使用commit把变更存储到磁盘中,或着如果您想要忽略从事务开始进行以来做出的变更,使用rollback。

条件:
A、 两事务操作同一行记录
B、 一事务对某一记录先申请共享锁,再升级为排他锁
C、 另一事务在过程中申请这一记录的排他锁

·         对事务表(如innodb)使用lock tables的正确方法是,设置autocommit=0并且不能调用unlock tables,直到您明确地提交事务为止。当您调用lock tables时,innodb会内部地取其自己的表锁定,mysql取其自己的表锁定。innodb在下一个提交时释放其表锁定,但是,对于mysql,要释放表锁定,您必须调用unlock tables。您不应该让autocommit=1,因为那样的话,innodb会在调用lock tables之后立刻释放表锁定,并且很容易形成死锁定。注意,如果autocommit=1,我们根本不能获取innodb表锁定,这样就可以帮助旧的应用软件避免不必要的死锁定。

复制代码 代码如下:

自选的work关键词被支持,用于commit和release,与chain和release子句。chain和release可以被用于对事务完成进行附加控制。completion_type系统变量的值决定了默认完成的性质。请参见5.3.3节,“服务器系统变量”。

美高梅网站是多少 8

如果您正在使用一个事务安全型的存储引擎(如innodb, bdb或ndb簇),则您可以使用以下语句禁用autocommit模式:

(gdb) b lock_rec_lock
 Breakpoint 1 at 0×867120: file lock/lock0lock.c, line 2070.
 (gdb) c
 Continuing.
 [Switching to Thread 1168550240 (LWP 5540)]
 Breakpoint 1, lock_rec_lock (impl=0, mode=5, rec=0x2aedbe01c1 “789200″, index=0x2aada734b8, thr=0x2aada74c18) at lock/lock0lock.c:2070
 2070 {
 Current language: auto; currently c
 (gdb) c
 Continuing.
 Breakpoint 1, lock_rec_lock (impl=0, mode=1029, rec=0x2aedbc80ba “200″, index=0x2aada730b8, thr=0x2aada74c18) at lock/lock0lock.c:2070
 2070 {
 (gdb) c
 Continuing.
 Breakpoint 1, lock_rec_lock (impl=0, mode=5, rec=0x2aedbe01cf “789200″, index=0x2aada734b8, thr=0x2aada74c18) at lock/lock0lock.c:2070
 2070 {
 (gdb) c
 Continuing.

美高梅4858官方网站,您可以安全地使用kill来结束一个正在等待表锁定的线程。请参见13.5.5.3节,“kill语法”。

于是,两个事务分别拥有部分锁并等待被对方持有的锁,出现这种资源循环等待的情况,即死锁。此案例中被检测时候的锁冲突就发现在page no为218436和218103的锁上。
InnoDB 会自动检测一个事务的死锁并回滚一个或多个事务来防止死锁。Innodb会选择代价比较小的事务回滚,此次事务(1)解锁并回滚,语句(2)继续运行直至事务结束。
美高梅网站是多少,innodb死锁形式归纳 死锁产生的四要素:互斥条件:一个资源每次只能被一个进程使用;请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;不剥夺条件:进程 已获得的资源,在末使用完之前,不能强行剥夺;循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
Innodb检测死锁有两种情况,一种是满足循环等待条件,还有另一种策略:锁结构超过mysql配置中设置的最大数量或锁的遍历深度超过设置的最大深度 时,innodb也会判断为死锁(这是提高性能方面的考虑,避免事务一次占用太多的资源)。这里,我们只考虑满足死锁四要素的情况。
死锁的形式是多样的,但分析到innodb加锁情况的最底层,因循环等待条件而产生的死锁只有可能是四种形式:两张表两行记录交叉申请互斥锁、同一张表则存在主键索引锁冲突、主键索引锁与非聚簇索引锁冲突、锁升级导致的锁等待队列阻塞。
以下首先介绍innodb聚簇索引与非聚簇索引的数据存储形式,再以事例的方式解释这四种死锁情况。
4.1聚簇索引与非聚簇索引介绍 聚簇索引即主键索引,是一种对磁盘上实际数据重新组织以按指定的一个或多个列的值排序,聚簇索引的索引页面指针指向数据页面。非聚簇索引(即第二主键索 引)不重新组织表中的数据,索引顺序与数据物理排列顺序无关。索引通常是通过B-Tree数据结构来描述,那么,聚簇索引的叶节点就是数据节点,而非聚簇 索引的叶节点仍然是索引节点,通常是一个指针指向对应的数据块。
而innodb在非聚簇索引叶子节点包含了主键值作为指针。(这样是为了减少在移动行或数据分页时索引的维护工作。)其结构图如下:
美高梅网站是多少 9

·         如果您在事务中使用非事务安全型表,则对这些表的任何变更被立刻存储,不论autocommit模式的状态如何。

主键索引锁与非聚簇索引锁冲突 案例:同一行记录,两事务使用不同的索引进行更新操作

·         alter function, alter procedure, alter table, begin, create database, create function, create index, create procedure, create table, drop database, drop function, drop index, drop procedure, drop table, load master data, lock tables, rename table, set autocommit=1, start transaction, truncate table, unlock tables.

此案例涉及TSK_TASK表,该表相关字段及索引如下:
ID:主键;
MON_TIME:监测时间;
STATUS_ID:任务状态;
索引:KEY_TSKTASK_MONTIME2 (STATUS_ID, MON_TIME)。

start transaction;select @a:=sum(salary) from table1 where type=1;update table2 set [email protected] where type=1;commit;使用start transaction,autocommit仍然被禁用,直到您使用commit或rollback结束事务为止。然后autocommit模式恢复到原来的状态。

您可能感兴趣的文章:

  • Mysql数据库锁定机制详细介绍
  • mysql锁表和解锁语句分享
  • MySQL行级锁、表级锁、页级锁详细介绍
  • MYSQL锁表问题的解决方法
  • mysql 数据库死锁原因及解决办法
  • mysql 锁表锁行语句分享(MySQL事务处理)
  • 一次Mysql死锁排查过程的全纪录
  • Mysql(MyISAM)的读写互斥锁问题的解决方法
  • mysql锁定单个表的方法
  • 查找MySQL线程中死锁的ID的方法
  • Mysql 数据库死锁过程分析(select for update)
  • MySQL锁机制与用法分析

·         rollback不会释放mysql的非事务表锁定。

死锁日志打印出的时间点表明,语句(1)运行过程中,当语句(2)开始运行时,发生了死锁。
当mysql检测出死锁时,除了查看mysql的日志,还可以通过show InnoDB STATUS G语句在mysql客户端中查看最近一次的死锁记录。由于打印出来的语句会很乱,所以,最好先使用pager less命令,通过文件内容浏览方式查看结果,会更清晰。(以nopager结束)
得到的死锁记录如下:

3.    一次锁定一个表,直到线程得到所有锁定为止。

美高梅网站是多少 10

·         如果您正在对一组myisam表运行许多操作,锁定您正在使用的表,可以快很多。锁定myisam表可以加快插入、更新或删除的速度。不利方面是,没有线程可以更新一个用read锁定的表(包括保持锁定的表),也没有线程可以访问用write锁定的表(除了保持锁定的表以外)。

当执行update、delete操作时,会修改表中的数据信息。由于innodb存储引擎中索引的数据存储结构,会根据修改语句使用的索引以及修改信息 的不同执行不同的加锁顺序。当使用索引进行查找并修改记录时,会首先加使用的索引锁,然后,如果修改了主键信息,会加主键索引锁和所有非聚簇索引锁,修改 了非聚簇索引列值会加该种非聚簇索引锁。
此案例中,事务一使用非聚簇索引查找并修改主键值,事务二使用主键索引查找并修改主键值,加锁顺序不同,导致同时运行时产生资源循环等待。
锁升级造成锁队列阻塞 案例:同一行记录,事务内进行锁升级,与另一等待锁发送锁队列阻塞,导致死锁

有些myisam操作在lock tables之下更快的原因是,mysql不会清空用于已锁定表的关键缓存,直到unlock table被调用为止。通常,关键缓存在每个sql语句之后被清空。

条件:
A、 两事务使用不同索引
B、 申请的锁互斥
C、 操作同一行记录

开始一项事务会造成一个隐含的unlock tables被执行。

默认情况下,mysql教程采用autocommit模式运行。这意味着,当您执行一个用于更新(修改)表的语句之后,mysql立刻把更新存储到磁盘中。

如果您在更新了事务中一个事务表之后,发布一个rollback语句,则会出现一个er_warning_not_complete_rollback警告。对事务安全型表的变更被 回滚,但是对非事务安全型表没有变更。

该规则确保表锁定不会出现死锁定。但是,对于该规则,您需要注意其它的事情:

您也可以按照如下方法开始一项事务:

lock tables按照如下方式执行:

·         innodb中的create table语句被作为一个单一事务进行处理。这意味着,来自用户的rollback不会撤销用户在事务处理过程中创建的create table语句。

如果语句返回以下错误,则意味着不存在带有指定名称的保存点:

·                mysql> lock tables trans read, customer write;·                mysql> select sum(value) from trans where customer_id=some_id;·                mysql> update customer·                    ->     set total_value=sum_from_previous_statement·                    ->     where customer_id=some_id;·                mysql> unlock tables;如果没有lock tables,有可能另一个线程会在执行select和update语句之间在trans表中插入一个新行

13.4.3. 会造成隐式提交的语句
以下语句(以及同义词)均隐含地结束一个事务,似乎是在执行本语句前,您已经进行了一个commit。

13.4.2. 不能回滚的语句
有些语句不能被回滚。通常,这些语句包括数据定义语言(ddl)语句,比如创建或取消数据库教程的语句,和创建、取消或更改表或存储的子程序的语句。

如果一个线程获得对一个表地read锁定,该线程(和所有其它线程)只能从该表中读取。如果一个线程获得对一个表的write锁定,只有保持锁定的线程可以对表进行写入。其它的线程被阻止,直到锁定被释放时为止。

2.    如果使用一个读取和一个写入锁定对一个表进行锁定,则把写入锁定放在读取锁定之前。

transaction, commit和rollback语法 start transaction | begin [work]commit [work] [and [no] chain] [[no] release]rollback [work] [and [no] chain] [[no] release]set autocommi...

当您使用lock tables时,您必须锁定您打算在查询中使用的所有的表。虽然使用lock tables语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,在此情况下,您必须分别获得对每个别名的锁定。

·         当当前所有的表均被锁定时,unlock tables可以提交事务。

and chain子句会在当前事务结束时,立刻启动一个新事务,并且新事务与刚结束的事务有相同的隔离等级。release子句在终止了当前事务后,会让服务器断开与当前客户端的连接。包含no关键词可以抑制chain或release完成。如果completion_type系统变量被设置为一定的值,使连锁或释放完成可以默认进行,此时no关键词有用。

rollback to savepoint语句会向以命名的保存点回滚一个事务。如果在保存点被设置后,当前事务对行进行了更改,则这些更改会在 回滚中被撤销。但是,innodb不会释放被存储在保存点之后的存储器中的行锁定。(注意,对于新插入的行,锁定信息被存储在行中的事务id承载;锁定没有被分开存储在存储器中。在这种情况下,行锁定在撤销中被释放。)在被命名的保存点之后设置的保存点被删除。

如果您正在对一个表使用一个low_priority write锁定,这只意味着,mysql等待特定的锁定,直到没有申请read锁定的线程时为止。当线程已经获得write锁定,并正在等待得到锁定表清单中的用于下一个表的锁定时,所有其它线程会等待write锁定被释放。如果这成为对于应用程序的严重的问题,则您应该考虑把部分表转化为事务安全型表。

您在设计事务时,不应包含这类语句。如果您在事务的前部中发布了一个不能被回滚的语句,则后部的其它语句会发生错误,在这些情况下,通过发布rollback语句不能 回滚事务的全部效果。

1.    按照内部定义的顺序,对所有要被锁定的表进行分类。从用户的角度,此顺序是未经定义的。

·         在尝试锁定表之前,lock tables不是事务安全型的,会隐含地提交所有活性事务。同时,开始一项事务(例如,使用start transaction),会隐含地执行unlock tables。(见13.4.3节,“会造成隐式提交的语句”。

注意,您不能使用insert delayed锁定任何您正在使用的表,因为,在这种情况下,insert由另一个线程执行。

回滚可以慢速运行。在用户没有明确要求时,也可以进行回滚(例如,当错误发生时)。因此,在明确地和隐含的(rollback sql命令)回滚时,show processlist会在stage列中显示rolling back,用于连接。

mysql> lock table t as myalias read;mysql> select * from t;error 1100: table 't' was not locked with lock tablesmysql> select * from t as myalias;write锁定通常比read锁定拥有更高的优先权,以确保更新被尽快地处理。这意味着,如果一个线程获得了一个read锁定,则另一个线程会申请一个write锁定,后续的read锁定申请会等待,直到write线程获得锁定并释放锁定。您可以使用low_priority write锁定来允许其它线程在该线程正在等待write锁定时获得read锁定。只有当您确定最终将有一个时机,此时没有线程拥有read锁定时,您才应该使用low_priority write锁定。

每个事务被存储在一个组块中的二进制日志中,在commit之上。被回滚的事务不被计入日志。(例外情况:对非事务表的更改不会被 回滚。如果一个被回滚的事务包括对非事务表的更改,则整个事务使用一个在末端的rollback语句计入日志,以确保对这些表的更改进行复制。)见5.11.3节,“二进制日志”。

savepoint语句用于设置一个事务保存点,带一个标识符名称。如果当前事务有一个同样名称的保存点,则旧的保存点被删除,新的保存点被设置。

·         如果您使用的表来自多个事务安全型存储引擎(例如innodb和bdb),并且事务隔离等级不是serializable,则有可能当一个事务提交时,其它正在进行中的、使用同样的表的事务将只会发生由第一个事务产生的变更。也就是,用混合引擎不能保证事务的原子性,并会造成不一致。(如果混合引擎事务不经常有,则您可以根据需要使用set transaction isolation level把隔离等级设置到serializable。)

为了获得最好的结果,事务应只使用由单一事务存储引擎管理的表执行。否则,会出现以下问题:

13.4.5. lock tables和unlock tables语法
lock tables    tbl_name [as alias] {read [local] | [low_priority] write}    [, tbl_name [as alias] {read [local] | [low_priority] write}] ...unlock tableslock tables可以锁定用于当前线程的表。如果表被其它线程锁定,则造成堵塞,直到可以获取所有锁定为止。unlock tables可以释放被当前线程保持的任何锁定。当线程发布另一个lock tables时,或当与服务器的连接被关闭时,所有由当前线程锁定的表被隐含地解锁。

mysql> lock table t read;mysql> select * from t as myalias;error 1100: table 'myalias' was not locked with lock tables相反的,如果您使用一个别名锁定一个表,您必须使用该别名在您的查询中引用该表。

如果您想要对于一个单一系列的语句禁用autocommit模式,则您可以使用start transaction语句:

start transaction, commit和rollback语法
start transaction | begin [work]commit [work] [and [no] chain] [[no] release]rollback [work] [and [no] chain] [[no] release]set autocommit = {0 | 1}start transaction或begin语句可以开始一项新的事务。commit可以提交当前事务,是变更成为永久变更。rollback可以 回滚当前事务,取消其变更。set autocommit语句可以禁用或启用默认的autocommit模式,用于当前连接。

您可以使用set transaction isolation level更改事务的隔离等级。请参见13.4.6节,“set transaction语法”。

·         如果您正在使用mysql中的一个不支持事务的存储引擎,则如果您想要确定在select和update之间没有其它线程,您必须使用lock tables。本处所示的例子要求lock tables,以便安全地执行:

事务不能被嵌套。这是隐含commit的结果。当您发布一个start transaction语句或其同义词时,该commit被执行,用于任何当前事务。

  表锁定只用于防止其它客户端进行不正当地读取和写入。保持锁定(即使是读取锁定)的客户端可以进行表层级的操作,比如drop table。

通常,您不需要锁定表,因为所有的单个update语句都是原子性的;没有其它的线程可以干扰任何其它当前正在执行的sql语句。但是,在几种情况下,锁定表会有好处:

本文由美高梅网站是多少发布于美高梅-数据,转载请注明出处:美高梅网站是多少开发进阶篇系列,Innodb表导致

上一篇:没有了 下一篇:Server数据导入导出工具BCP详解,使用脚本输出e
猜你喜欢
热门排行
精彩图文