InnoDB 事务隔离级别
InnoDB是一种平衡高可靠性和高性能的通用存储引擎。在MySQL数据库5.5.8版本开始,InnoDB是默认的MySQL存储引擎。
InnoDB的主要优势
- 其DML操作遵循ACID,具有提交,回滚和崩溃恢复功能的事务,以保护用户数据
行锁设定类似于Oracle风格的一致性读,可提高多用户并发性和性能。
InnoDB表将数据以聚集(clustered)方式进行存储,因此每张表的存储都是按主键的顺序进行存放,如果没有显示地在表定义时指定主键,InnoDB存储引擎会为每一行生成一个6字节的ROWID,并以此作为主键。
支持外键约束。使用外键时,将检查插入,更新和删除,以确保他们不会导致不同表之间的不一致。
InnoDB通过使用多版本并发控制(MVCC)来获得高并发性,并且实现了SQL标准的4种隔离级别,more是
REPEATABLE-READ
级别
特性 | 支持 |
---|---|
B-tree indexes | Yes |
基于时间点的备份恢复(在服务器中实现,而不是在存储引擎中实现。) | YES |
Cluster database support | No |
Clustered indexes | No |
Compressed data | Yes |
Data caches | Yes |
数据加密(加密功能在服务器中实现。 在MySQL 5.7及更高版本中可以使用静态数据表空间加密。) |
Yes |
Foreign key support | Yes |
Full-text search indexes | Yes(MySQL 5.6及更高版本中提 供了InnoDB对FULLTEXT索引的支持。) |
地理空间数据类型支持 | Yes |
地理空间索引支持 | Yes(在MySQL 5.7及更高版本中可以使用InnoDB对地理空间索引的支持。) |
Hash 索引 | No(InnoDB在内部利用其自适应哈希索引来实现哈希索引功能。) |
Index caches | Yes |
Locking 粒度 | Row |
MVCC | Yes |
Replication support(在服务器中实现,而不是在存储引擎中实现。) | Yes |
存储限制 | 64TB |
T-tree indexes | No |
Transactions | Yes |
更新数据字典的统计信息 | Yes |
1. 事务的基本要素
原子性(Atomicity)
事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。一致性(Consistency)
一致性指事务将数据库从一种状态转变为下一种一致的状态。从事务开始之前和事务结束之后,数据库的晚自习约束没有被破坏。隔离性(Isolation)
事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,即该事务提交前对其他事务都不可见,通常这使用锁来实现,当前数据库系统中都提供了一种粒度锁(granular lock)的策略,允许事务仅锁住一个实体对象的子集,以此来提高事务之间的并发度。持久性(Durability)
事务一旦提交,其结果就永久性的。即使发生宕机等故障,数据库也能将数据恢复。
2. 事务的隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
读已提交(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
脏读
A事务,会读取到B事务还未提交的数据。因为B事务可能会因为各种原因数据回滚,所以如果A事务读取了B未提交的数据,然后基于此进行一些业务操作,但是B事务发生错误回滚了,那A事务的业务操作就错了。不可重复读
在同一个事务生命周期内,也就是这个事务还未提交之前。如果另外一个事务,对数据进行了编辑(update)或者删除(delete)操作。那么A事务就会读取到。简单理解,就是在一个事务生命周期内,多次查询数据,每次都可能查出来的不一样。幻读
幻读的结果其实和不可重复读是一样的表现,差异就在于,不可重复读,主要是针对其他事务进行了编辑(update)和删除(delete)操作。而幻读主要是针对插入(insert)操作。也就是在一个事务生命周期内,会查询到另外一个事务新插入的数据。
如果想在MySQL数据库启动时设置事务的默认隔离级别,那就需要修改MySQL的配置文件,
在[mysqld]中添加如下:
[mysqld]
transaction-isolation = READ-COMMITTED
查看当前的会话事务隔离级别,可以使用:
root@localhost [(none)] 14:53:10>select @@tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [(none)] 14:54:49>SHOW VARIABLES LIKE 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
查看全局的事务隔离级别,可以使用:
root@localhost [(none)] 14:53:10>select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [(none)] 14:54:49>SHOW global variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
在InnoDB存储引擎中,可以使用以下命令来设置当前会话或全局的事务隔离级别:
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{
READ-UNCOMMITED
| READ-COMMITTED
| REPEATABLE-READ
| SERIALIZABLE
}
3. 各隔离级别示例
首先创建示例表,并插入数据
create table account(id int,name char(30),balance int);
insert into account values(1,'wb',18000);
insert into account values(2,'wb2',28000);
insert into account values(3,'wb3',38000);
commit;
关闭自动提交
set autocommit = 0;
set global autocommit = 0;
3.1 读未提交(read-uncommitted)
- 实验步骤
1)分别在session1,与session2 终端设置隔离级别为set session transaction isolation level read uncommitted;
2)分别在session1,session2上开始事务,执行begin;
3)分别在session1,session2上开始事务,执行查询语句select * from account;
4)在session1上,执行update语句,不提交update account set balance=balance - 50 where id= 1;
5)在session2上,执行查询语句select * from account;
,session2上能返回session1未提交的数据,这种读叫做脏读。
##############session 1##############
root@localhost [test] 10:20:11>select @@autocommit; #操作1
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
root@localhost [test] 10:21:58>set session transaction isolation level read uncommitted; #操作3
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 10:22:54>select @@tx_isolation; #操作5
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 10:23:21>begin; #操作6
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 10:23:37>select * from account; #操作7
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
| 2 | wb2 | 28000 |
| 3 | wb3 | 38000 |
+------+------+---------+
3 rows in set (0.00 sec)
root@localhost [test] 10:23:46>update account set balance=balance - 50 where id= 1; #操作10
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
##############session 2##############
root@localhost [test] 10:20:38>select @@autocommit; #操作2
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
root@localhost [test] 10:20:46>set session transaction isolation level read uncommitted; #操作4
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 10:23:00>begin #操作8
-> ;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 10:24:08>select * from account; #操作9
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
| 2 | wb2 | 28000 |
| 3 | wb3 | 38000 |
+------+------+---------+
3 rows in set (0.00 sec)
root@localhost [test] 10:24:18>select * from account; #操作11
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 17950 |
| 2 | wb2 | 28000 |
| 3 | wb3 | 38000 |
+------+------+---------+
3 rows in set (0.00 sec)
【结论】:可以看到,我们在session1, insert一条数据,但是未进行提交操作(commit),但是在session2事务中,却查询到了。我们称这种现象叫做脏读,在实际开发过程中,我们一般较少使用Read uncommitted隔离级别,这种隔离级别对任何的数据操作都不会进行加锁。
3.2 读已提交(read-committed)
3.2.1 read committed 脏读与不可重复读示例
- 实验步骤
1)分别在session1与session2上设置隔离级别set session transaction isolation level read committed;
2)分别在session1,session2上开始事务,执行begin;
3)分别在session1,session2上开始事务,执行查询语句select * from account where id=1;
4)在session1上执行update语句update account set balance=20000 where id=1;
5)在session2上执行select语句select * from account where id = 1;
,返回的还是旧数据,说明不能脏读。
6)在session2上执行select + for update
语句,for update读取数据,被阻塞,需等待session1,结束事务
7)在session1上执行commit;
8)session2立马返回最新数据,加不加for update都能返回最新数据。
##############session 1##############
root@localhost [test] 11:10:21>select @@autocommit; #操作1
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
root@localhost [test] 11:12:32>set session transaction isolation level read committed; #操作3
Query OK, 0 rows affected (0.01 sec)
root@localhost [test] 11:12:44>select @@tx_isolation; #操作5
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 11:12:55>begin; #操作7
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:13:23>select * from account where id=1; #操作9
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:13:56>update account set balance=20000 where id=1;#操作11
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
root@localhost [test] 11:14:59>commit; #操作14
Query OK, 0 rows affected (0.01 sec)
##############session 2##############
root@localhost [test] 11:10:11>select @@autocommit; #操作2
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
root@localhost [test] 11:12:05>set session transaction isolation level read committed; #操作4
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:13:02>select @@tx_isolation; #操作6
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 11:13:11>begin; #操作8
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:13:36>select * from account where id = 1; #操作10
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:14:16>select * from account where id = 1; #操作12 session 1:未提交时,还是读取到旧数据
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:15:05>select * from account where id = 1 for update;
#操作13:for update读取数据,被阻塞,需等待session1,结束事务
#操作15: session1执行commit后,加不加for update能读取到最新数据
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 20000 |
+------+------+---------+
1 row in set (5.62 sec)
【总结】:在read committed隔离级别下,可以避免脏读,但是避免不了不可重复读,在session2 这一事务周期间,我们并没有结束事务,但多次查询的结果不一致,说明是进行了不可重复读。
3.2.2 read-committed下的幻读示例
给account表增加索引
alter table account add index idx_id (id);
- 实验步骤
1)分别在session1与session2上设置隔离级别set session transaction isolation level read committed;
2)分别在session1,session2上开始事务,执行begin;
3)在session1上执行查询语句select * from account where id=2;
4)在session2上执行for update查询语句select * from account where id=2 for update;
5)在session1上insert语句insert into account select 2,'wb4',58000;
,这里为什么不产生锁等待?因为id上有索引,session2的查询语句只锁定索引记录
6)在session2上执行查询语句select * from account where id=2;
读取的是旧数据,然后再执行for update语句,有行锁等待
7)在session1上 执行commit;
8)在session2上,立马返回最新数据,产生了幻读。加不加for update都可以读到新数据。
###############session1###############
root@localhost [test] 09:55:58>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 09:56:22>select * from account where id=2;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 09:56:34>insert into account select 2,'wb4',58000;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
root@localhost [test] 09:58:18>commit;
Query OK, 0 rows affected (0.01 sec)
###############session2###############
root@localhost [test] 09:57:11>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 09:57:32>select * from account where id=2 for update;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 09:57:43>select * from account where id=2;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 09:58:35>select * from account where id=2 for update;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
| 2 | wb4 | 58000 |
+------+------+---------+
2 rows in set (4.17 sec)
root@localhost [test] 09:58:45>select * from account where id=2;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
| 2 | wb4 | 58000 |
+------+------+---------+
2 rows in set (0.00 sec)
【总结】在Read committed隔离级别中,可以有效解决脏读问题,但是有不可重复读、幻读问题,而不可重复读和幻读的差异主要是,不可重复读主要是针对修改和删除操作、幻读针对插入数据操作。
3.3 可重复读(repeatable-read)
- 实验步骤
1)在session1与session2上查询当前默认隔离级别:select @@tx_isolation
,返回为REPEATABLE-READ
隔离级别
2)session1与session2分别执行begin
,表明开始一个事务
3)session1与session2分别查询语句select * from account where id=3;
4)在session1上执行insert 语句insert into account select 3,'wb4',68000;
5)在session2上执行查询语句select * from account where id=3;
,没有返回最新数据,说明没有脏读
现象.
6)在session1上执行commit
操作
7)在session2上多次执行查询语句,select * from account where id=3;
,没有返回最新数据,说明没有幻读
现象。
8)在session2上执行commit操作,然后执行查询语句能返回最新结果l
9)分别在session1 与session2上执行begin;
,表明开始一个事务
10)session1上执行update语句update account set balance=balance-50 where id=1;
然后执行commit;
11)session2上多次执行select语句select * from account where id=1;
,结果都是一样,没有最新数据,说明没有不可重复读
现象。
12)session2上执行commit
,能返回最新数据。
###############session1###############
root@localhost [test] 10:58:39>select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 10:58:47>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 10:58:51>select * from account;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
| 2 | wb2 | 28000 |
| 3 | wb3 | 38000 |
| 2 | wb4 | 58000 |
+------+------+---------+
4 rows in set (0.00 sec)
root@localhost [test] 10:59:11>select * from account where id=3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:00:31>insert into account select 3,'wb4',68000;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
root@localhost [test] 11:02:01>select * from account where id =3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:02:49>insert into account select 3,'wb4',68000;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
root@localhost [test] 11:02:57>commit;
Query OK, 0 rows affected (0.02 sec)
root@localhost [test] 11:03:06>update account set balance=balance-50 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
root@localhost [test] 11:05:04>commit;
Query OK, 0 rows affected (0.01 sec)
###############session1###############
root@localhost [test] 10:57:11>select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 10:57:28>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 10:58:55>select * from account;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
| 2 | wb2 | 28000 |
| 3 | wb3 | 38000 |
| 2 | wb4 | 58000 |
+------+------+---------+
4 rows in set (0.00 sec)
root@localhost [test] 10:59:49>select * from account where id=3 for update;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:01:25>select * from account where id=2 for update;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
| 2 | wb4 | 58000 |
+------+------+---------+
2 rows in set (0.00 sec)
root@localhost [test] 11:01:43>commit;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:02:24>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:02:28>select * from account where id=3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:02:38>select * from account where id=3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:03:01>select * from account where id=3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:03:09>select * from account where id=3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:03:13>commit;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:03:50>select * from account where id=3;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 3 | wb3 | 38000 |
| 3 | wb4 | 68000 |
+------+------+---------+
2 rows in set (0.00 sec)
root@localhost [test] 11:03:52>select * from account ;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
| 2 | wb2 | 28000 |
| 3 | wb3 | 38000 |
| 2 | wb4 | 58000 |
| 3 | wb4 | 68000 |
+------+------+---------+
5 rows in set (0.00 sec)
root@localhost [test] 11:05:19>select * from account where id=1;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:05:24>select * from account where id=1;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:05:32>select * from account where id=1;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.01 sec)
root@localhost [test] 11:05:34>select * from account where id=1;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 18000 |
+------+------+---------+
1 row in set (0.00 sec)
root@localhost [test] 11:05:44>commit;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:05:46>select * from account where id=1;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 1 | wb | 17950 |
+------+------+---------+
1 row in set (0.00 sec)
【总结】在Repeatable read级别中,脏读、不可重复读、幻读现象都没有。在mysql中,该级别也是默认的事务隔离级别,我们日常在开发中,也是主要使用该隔离级别。
3.4 串行化(serializable)
- 实验步骤
1)session1 与 session2分别设置隔离级别set session transaction isolation level serializable;
2) session1 与 session2分别执行begin;
开始事务
3)session1 与 session2分别执行查询语句select * from account where id=2;
4)session1上执行update语句update account set balance=balance+100 where id=2;
5)session1上提示报错ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
,有行锁等待
6)session2上执行update语句update account set balance=balance+100 where id=1;
能成功更新,说明session2只是行级锁定。
##########session1##########
root@localhost [test] 11:23:58>select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 11:24:31>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:24:43>select * from account where id=2;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
| 2 | wb4 | 58000 |
+------+------+---------+
2 rows in set (0.00 sec)
root@localhost [test] 11:25:10>update account set balance=balance+100 where id=2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
root@localhost [test] 11:30:18>update account set balance=balance+100 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
##########session2##########
root@localhost [test] 11:22:59>set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
root@localhost [test] 11:24:22>select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [test] 11:24:37>select * from account where id=2;
+------+------+---------+
| id | name | balance |
+------+------+---------+
| 2 | wb2 | 28000 |
| 2 | wb4 | 58000 |
+------+------+---------+
2 rows in set (0.00 sec)
Serializable完全串行化的读,每次读都需要获得表级共享锁,读写相互会相互互斥,这样可以更好的解决数据一致性的问题,但是同样会大大的降低数据库的实际吞吐性能。所以该隔离级别因为损耗太大,一般很少在开发中使用。
InnoDB 事务隔离级别的更多相关文章
- InnoDB事务隔离级别
转载于:http://blog.csdn.net/wudongxu/article/details/8623610 SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的 ...
- Innodb中的事务隔离级别和锁的关系
前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...
- Innodb中的事务隔离级别和锁的关系(转)
原文:http://tech.meituan.com/innodb-lock.html 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库 ...
- innodb是如何巧妙实现事务隔离级别
之前的文章mysql锁机制详解中我们详细讲解了innodb的锁机制,锁机制是用来保证在并发情况下数据的准确性,而要保证数据准确通常需要事务的支持,而mysql存储引擎innodb是通过锁机制来巧妙地实 ...
- MySQL InnoDB中的事务隔离级别和锁的关系
前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...
- InnoDB锁问题 & DB事务隔离级别
<参考:http://www.cnblogs.com/jack204/archive/2012/06/09/2542940.html>InnoDB行锁实现方式InnoDB行锁是通过给索引上 ...
- 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系
重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...
- Innodb 中的事务隔离级别和锁的关系
转自:https://tech.meituan.com/innodb-lock.html 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据 ...
- Innodb中的事务隔离级别和锁的关系(转载)
nodb中的事务隔离级别和锁的关系 原文:https://tech.meituan.com/innodb-lock.html ameng ·2014-08-20 15:50 前言: 我们都知道事务的几 ...
随机推荐
- python 类型转换总结
一.数字和字符串 >>> ord('a') # ascii码 97 >>> chr(97) 'a' >>> >>> hex(16 ...
- Luogu P1736 创意吃鱼法【dp】By cellur925
题目传送门 题意:给出一个01矩阵,找出一条对角线,使得对角线上的元素都为1,而对角线所在矩阵其他元素均为0,使得这样的对角线最长. 状态:$f[i][j]$表示以($i$,$j$)为对角线端点的最长 ...
- springboot&mybatis 增删改查系列(二)
数据库篇 我的数据库名为data0525,数据表名为user,其中有五列uid,uname,upass,usex,umessage.uid为主键并且自动生成,由于是练习表,所以并没有考虑设计的合理性. ...
- C++类 单冒号
1.继承 class Base { }; class Derived : public Base { }; 示列: class Base { public: int a=10; }; class ...
- Educational Codeforces Round 19 A
Description Given a positive integer n, find k integers (not necessary distinct) such that all these ...
- h5-26-web本地存储
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 130 Surrounded Regions 被围绕的区域
给定一个二维的矩阵,包含 'X' 和 'O'(字母 O), 找到所有被 'X' 围绕的区域.并将区域里所有 'O'用 'X' 填充.例如,X X X XX O O XX X O XX O X X运行你 ...
- 你不知道的border-radius
对于border-radius这个属性,我们知道它可以用来设置边框圆角,利用它我们可以画出很多形状 这就需要了解到border-radius的各式写法: border-radius的写法: 1.只设置 ...
- poj2385 Apple Catching
思路: 简单dp. 实现: #include <iostream> #include <cstdio> #include <cstring> using names ...
- placeholder字体样式及兼容
样式修改css::-webkit-input-placeholder { /* WebKit browsers */ color: #fff!important;}:-moz-placeholder ...