+ -
当前位置:首页 → 问答吧 → 事务的操作

事务的操作

时间:2011-12-05

来源:互联网

innodb的表。

1 innodb的物理数据文件在哪呢 我只找到表定义的frm文件。

2 如果set autocommit=0 禁止自动提交,
  那么select也需要begin COMMIT这样写吗?
  如果insert 或者update的时候没有用begin COMMIT,是不是会报错?

3 如果set autocommit=1,在更新操作的时候,会自动锁行?

4 insert操作的时候,是不是既不会锁表也不会锁行?

作者: nindeping4   发布时间: 2011-12-05

引用1 innodb的物理数据文件在哪呢 我只找到表定义的frm文件。
在ibdata中 ,这个文件在 datadir 指定的目录中。

引用2 如果set autocommit=0 禁止自动提交,
那么select也需要begin COMMIT这样写吗?
如果insert 或者update的时候没有用begin COMMIT,是不是会报错?
SELECT只是查询,它不做任何修改,有什么好提交的?
INSERT/UPDATE没有BIGIN则会自动开始。 没有COMMIT则一直不提交。

引用3 如果set autocommit=1,在更新操作的时候,会自动锁行?
会。

引用4 insert操作的时候,是不是既不会锁表也不会锁行?
是,锁索引间隙

作者: ACMAIN_CHM   发布时间: 2011-12-05

建议先看一下手册中关于INNODB存储引擎锁与事务的介绍。 

引用
15.2.10. InnoDB事务模型和锁定
15.2.10.1. InnoDB锁定模式

15.2.10.2. InnoDB和AUTOCOMMIT

15.2.10.3. InnoDB和TRANSACTION ISOLATION LEVEL

15.2.10.4. 持续非锁定读

15.2.10.5. 锁定读SELECT ... FOR UPDATE和SELECT ... LOCK IN SHARE MODE

15.2.10.6. Next-Key锁定:避免匪夷所思的问题

15.2.10.7. 持续读如何在InnoDB中作用的例子

15.2.10.8. 在InnoDB中用不同的SQL语句设定锁

15.2.10.9. MySQL什么时候提交或回滚一个事务?

15.2.10.10. 死锁检测&回滚

15.2.10.11. 如何应对死锁

在InnoDB事务模式中,目的是把多版本数据库的最好特性与传统的二相锁定合并起来。InnoDB以Oracle的风格,对行级进行锁定,并且默认运行查询作为非锁定持续读。在InnoDB中锁定的表被存储得如此节省空间,以至于不需要锁定增大:典型地,数个用户被允许在数据库中锁定每一行,或者行的任何随机子集,而InnoDB不会耗尽内存。

15.2.10.1. InnoDB锁定模式
InnoDB实现标准行级锁定,在这里有两种类型的锁: locks:

· 共享的(S)锁允许一个事务去读一行(tuple)。

· 独占的锁(X)允许一个事务更新或删除一行。

如果事务A 在tuple t上持有独占锁定,来自不同事务B的对t上任一类型的锁的请求不被马上许可,取而代之地,事务B 不得不等待事务t释放在tuple t上的锁。

如果事务 A 在tuple t上持有一个共享的锁(S),那么

· 来自不同的事务B对在t 上X的锁定请求不能被马上许可。

· 来自不同的事务B对在t 上S的锁定请求可以被马上获准。因此A和B持有t上的S锁定。

不仅如此,InnoDB支持多间隔尺寸锁定,它允许记录锁和对整个表的锁共存。要使得多间隔尺寸级别的锁定实际化,额外类型的锁,被称为intention locks被使用。在InnoDB中,意图锁定是表锁定。 对于一个事务,意图锁定之后理想的是指明在该表中对一个行随后需要哪一类型的锁定(共享还是独占)。有两种意图锁被用在InnoDB中(假设事务T 在表R中要求一个已指出的类型的锁):

· 意图共享(IS):事务T 意图给表T上单独的tuple设置S 锁定。

· 意图独占(IX):事务T 意图给这些tuple设置X 锁定。

意图锁协议如下:

· 在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。

· 在假设的事务可以获得对某假定行的X 锁定之前,它必须首先获得对包含该行的表的一个IX 锁定。

这些结果可以方便地用一个锁类型兼容矩阵来总结:


X
IX
S
IS

X
冲突
冲突
冲突
冲突
IX
冲突
兼容
冲突
兼容

S
冲突
冲突
兼容
兼容

IS
冲突
兼容
兼容
兼容


如果一个锁定与现在锁定兼容的话,它被授给一个委托事务。如果一个锁定与现存锁定冲突,它就不被授予一个委托事务。事务等待着直到冲突的现存锁定被释放掉。如果一个锁定请求与现存锁定相冲突,且不能被授予,因为它可能会导致死锁,一个错误产生。

因此,意图锁定不阻碍任何东西,除了完全表请求(比如LOCK TABLES ... WRITE)。IX 和IS锁定的主要目的是显示某人正锁定一行,或将要在表中锁定一行。

下列的例子演示当锁定请求可能会导致死锁之时一个错误会如何发生。例子中包括两个客户端A和B。

首先客户端A创建一个包含一个行的表,然后开始一个事务。在这个事务内,A通过在共享模式选择行获得对行的S 锁定:

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)

mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+
| i |
+------+
| 1 |
+------+
1 row in set (0.10 sec)
接着,客户端B开始一个事务并尝试从该表删除行:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM t WHERE i = 1;
删除操作要求一个X 锁定。因为这个锁定不兼容客户端A持有的S锁定,所以X 锁定不被允许,所以请求进入对行及客户端阻挡的锁定请求队列。

最后,客户端A也试图从表中删除该行:

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
因为客户端A需要一个X 锁定来删除该行,所以在这里发生死锁。尽管如此,锁定请求不被允许,因为客户端B已经有一个对X锁定的请求并且它正等待客户端A释放S锁定。因为客户端B之前对X 锁定的请求,被客户端A持有的S锁定也不能升级到X锁定。因此,InnoDB对客户端A产生一个错误,并且释放它的锁定。在那一点上,客户端B的锁定请求可以被许可,并且客户端B从表中删除行。

15.2.10.2. InnoDB和 AUTOCOMMIT
在InnoDB中,所有用户行为都在事务内发生。如果自动提交模式被允许,每个SQL语句在它自己上形成一个单独的事务。MySQL总是带着允许自动提交来开始一个新连接。

如果自动提交模式被用SET AUTOCOMMIT = 0关闭,那么我们可以认为一个用户总是有一个事务打开着。一个SQL COMMIT或ROLLBACK语句结束当前事务并且一个新事务开始。两个语句都释放所有在当前事务中被设置的InnoDB锁定。一个COMMIT语句意味着在当前事务中做的改变被生成为永久的,并且变成其它用户可见的。一个ROLLBACK语句,在另一方面,撤销所有当前事务做的修改。

如果连接有被允许的自动提交,通过用明确的START TRANSACTION或BEGIN语句来开始一个事务,并用COMMIT或者ROLLBACK语句来结束它,这样用户仍旧可以执行一个多重语句事务。

15.2.10.3. InnoDB和TRANSACTION ISOLATION LEVEL
按照SQL:1992 事务隔离级别,InnoDB默认是可重复读的(REPEATABLE READ)。MySQL/InnoDB 提供SQL标准所描述的所有四个事务隔离级别。你可以在命令行用--transaction-isolation选项,或在选项文件里,为所有连接设置默认隔离级


作者: ACMAIN_CHM   发布时间: 2011-12-05