Oracle数据库死锁和MySQL死锁构造和比较

最近在复习数据库的事务隔离性,顺便构造了一下在Oracle上和MySQL上的死锁以比较异同。

在Oracle上面的实验

  • 在Oracle中,因为是显式提交,所以默认可以认为在一个会话中若没有使用commit进行提交,则可以认为在同一个事务里面

  • 首先构造测试用表

SQL> create table t(a1 number,b varchar2(10), c varchar2(10));
SQL> insert into t1 (1,'a','b');
SQL> insert into t values (2, 'aa','bb');
  • 开两个窗口形成死锁

  • 同时这个过程中,可以在第三会话中进行查询,未提交的数据是不能够被查看到的。

在MySQL上的实验

  • 使用的版本


mysql> status

mysql Ver 14.14 Distrib 5.6.26, for Linux (x86_64) using EditLine wrapper

Connection id: 2
Current database: test
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.6.26 MySQL Community Server (GPL)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 4 hours 52 min 1 sec

Threads: 3 Questions: 107 Slow queries: 0 Opens: 69 Flush tables: 1 Open tables: 62 Queries per second avg: 0.006

mysql> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

  • 在MySQL中,默认采用repeatable read的隔离级别,且在事务执行过程中使用的是隐式提交,所以需要显式指定事务。根据《高性能MySQL》书中第5页的方式试图构造出死锁。

这时,可以发现问题,此时innodb竟然执行的不是row lock而是table lock。 这个问题已经在stackoverflow上面进行提问, 获得的解答是必须在表上增加一个主键或者索引,否则innodb无法判断准确的行信息,就无法实现行级锁。

关于MySQL中的死锁实现方式,参考了MySQL Innodb表导致死锁日志情况分析与归纳

比如,通过可以通过锁升级造成锁队列阻塞。

原文地址:https://www.cnblogs.com/shenfeng/p/db_deadlocak.html