近几年学得比较迷茫,好像什么都学,一直想好好剖析一个好产品, 好好提升一下自我,好像进展蛮慢,博客也少写了。 人的精力是有限的,还是得在某一行深入。
近来对mysql有些兴趣,专门学习了一下。
我们都知道,数据库事务隔离级别下和普通sql加锁和释放锁的时机是不同的,
mysql是如何实现的呢。(以mysql-6.0.11-alpha为例)
mysql锁释放的代码在 lock_release_off_kernel。
下面在红帽下跟踪:
首先设置断点:
break lock_release_off_kernel
在mysql客户端,连接上面,在事务和非事务下执行,看看堆栈的不同
非事务状态下面执行
select * from test1 ;
堆栈显示如下:
#0 lock_release_off_kernel (trx=0xb512ac68) at lock/lock0lock.c:3853
#1 0xb5dca803 in trx_commit_off_kernel (trx=0xb512ac68) at trx/trx0trx.c:853
#2 0xb5dcad19 in trx_commit_for_mysql (trx=0xb512ac68) at trx/trx0trx.c:1582
#3 0xb5dd2838 in innobase_commit_low (trx=0x0) at handler/ha_innodb.cc:1878
#4 0xb5dd5f42 in innobase_commit (hton=0x8f6c2e8, thd=0x982fec0, all=true)
at handler/ha_innodb.cc:2021
#5 0xb5dd9f3e in ha_innobase::external_lock (this=0x97020e0, thd=0x982fec0,
lock_type=2) at handler/ha_innodb.cc:7023
#6 0x082e25f1 in handler::ha_external_lock (this=0x97020e0, thd=0x982fec0,
lock_type=2) at handler.cc:5450
#7 0x081cb7fe in unlock_external (thd=0x982fec0, table=<value optimized out>,
count=1) at lock.cc:822
#8 0x081cb969 in mysql_unlock_read_tables (thd=0x982fec0, sql_lock=0x9831da0)
at lock.cc:503
#9 0x082586f6 in JOIN::join_free (this=0x97eb8e8) at sql_select.cc:10445
#10 0x0825f0d9 in do_select (join=0x97eb8e8, fields=0x9831170, table=0x0,
procedure=0x0) at sql_select.cc:15864
#11 0x08266372 in JOIN::exec (this=0x97eb8e8) at sql_select.cc:2886
#12 0x08266f5d in mysql_select (thd=0x982fec0, rref_pointer_array=0x98311e0,
tables=0x96fb180, wild_num=1, fields=@0x9831170, conds=0x0, og_num=0,
order=0x0, group=0x0, having=0x0, proc_param=0x0,
select_options=2147764736, result=0x96fb618, unit=0x9830e48,
select_lex=0x98310dc) at sql_select.cc:3067
#13 0x08267467 in handle_select (thd=0x982fec0, lex=0x9830dec,
result=0x96fb618, setup_tables_done_option=0) at sql_select.cc:310
#14 0x081e0877 in execute_sqlcom_select (thd=0x982fec0, all_tables=0x96fb180)
at sql_parse.cc:4922
#15 0x081e30af in mysql_execute_command (thd=0x982fec0) at sql_parse.cc:2150
#16 0x081ea940 in mysql_parse (thd=0x982fec0,
inBuf=0x96fb048 "select * from test1", length=19,
found_semicolon=0xb26f3f14) at sql_parse.cc:5937
#17 0x081eb82c in dispatch_command (command=COM_QUERY, thd=0x982fec0,
packet=0x9826231 "", packet_length=19) at sql_parse.cc:1049
#18 0x081ecaec in do_command (thd=0x982fec0) at sql_parse.cc:731
#19 0x081dc327 in handle_one_connection (arg=0x982fec0) at sql_connect.cc:1146
#20 0x4dfe92db in start_thread (arg=0xb26f4790) at pthread_create.c:296
#21 0x006cf14e in clone () from /lib/libc.so.6
由上可见,锁在join_free释放
而事务模式下面
start transaction;
select * from test; --此时断点没有命中,必须下面执行commit
commit;
堆栈为
#0 lock_release_off_kernel (trx=0xb512ac68) at lock/lock0lock.c:3853
#1 0xb5dca803 in trx_commit_off_kernel (trx=0xb512ac68) at trx/trx0trx.c:853
#2 0xb5dcad19 in trx_commit_for_mysql (trx=0xb512ac68) at trx/trx0trx.c:1582
#3 0xb5dd2838 in innobase_commit_low (trx=0x0) at handler/ha_innodb.cc:1878
#4 0xb5dd5f42 in innobase_commit (hton=0x8f6c2e8, thd=0x982fec0, all=true)
at handler/ha_innodb.cc:2021
#5 0x082e840a in ha_commit_one_phase (thd=0x982fec0, all=true)
at handler.cc:1231
#6 0x082e897d in ha_commit_trans (thd=0x982fec0, all=true) at handler.cc:1199
#7 0x083925fc in trans_commit (thd=0x982fec0) at transaction.cc:136
#8 0x081e7972 in mysql_execute_command (thd=0x982fec0) at sql_parse.cc:4130
#9 0x081ea940 in mysql_parse (thd=0x982fec0, inBuf=0x96fb048 "commit",
length=6, found_semicolon=0xb26f3f14) at sql_parse.cc:5937
#10 0x081eb82c in dispatch_command (command=COM_QUERY, thd=0x982fec0,
packet=0x9826231 "commit", packet_length=6) at sql_parse.cc:1049
#11 0x081ecaec in do_command (thd=0x982fec0) at sql_parse.cc:731
#12 0x081dc327 in handle_one_connection (arg=0x982fec0) at sql_connect.cc:1146
#13 0x4dfe92db in start_thread (arg=0xb26f4790) at pthread_create.c:296
#14 0x006cf14e in clone () from /lib/libc.so.6
可见这几个用法在释放锁的时机是不一样的。
在那里产生分支呢?
在下面的设置断点:
break ha_innodb.cc:7021
跟踪ha_innobase::external_lock下面这一行
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
if (trx->active_trans != 0) {
innobase_commit(ht, thd, TRUE);
}
} else {
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& trx->global_read_view) {
/* At low transaction isolation levels we let
each consistent read set its own snapshot */
read_view_close_for_mysql(trx);
}
从上面可以看出有事务和没事务,事务隔离级别不同采用不同的处理方法。
相关推荐
MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁...
用了Mysql 之后,发现就没有远程跟踪的工具了..所以本人利用C#开发一个工具类似于mssqlprofiler的跟踪工具.可以远程跟踪执行的语句. 在程序中屏蔽了一些系统语句.所以很清爽,不会错过一个有用的语句,比较稳定.支持...
FOR UPDATE`语句,则该事务将被阻塞,直到前一个事务释放锁。 - 通常情况下,普通的`SELECT`语句不会受到事务的影响,这意味着即使在事务中执行`SELECT`操作,也不会导致数据被锁定。 #### 四、MySQL SELECT ... ...
MySQL的锁机制是数据库管理系统中用于控制并发操作的重要机制,对于保证数据的一致性和完整性起着至关重要的作用。本文将深入解析MySQL中的锁机制,帮助读者理解其工作原理,为面试准备或日常数据库管理提供有力支持...
MySQL中的锁机制是数据库并发控制的关键部分,它确保了在多用户环境中数据的一致性和完整性。在MySQL中,主要存在两种类型的锁:行级锁(Row-Level Locks)和表级锁(Table-Level Locks)。InnoDB存储引擎默认支持...
MySQL的锁机制是数据库管理系统中用于控制并发操作的重要机制,对于多用户环境下的数据一致性、事务隔离性和系统性能有着至关重要的影响。本文将深入探讨MySQL的高级锁机制,包括表锁和行锁,并提供一些优化建议。 ...
系统介绍mysql锁机制
一旦有线程获得写锁,只有该线程可以进行写操作,其他线程的读写操作都将等待锁释放。 InnoDB存储引擎则采用行级锁,开销较大,加锁慢,但由于锁定粒度小,因此并发度较高,支持事务处理。InnoDB的行级锁类型包括...
MySQL的Insert锁机制是数据库管理系统中确保数据一致性和并发控制的重要组成部分。在MySQL的InnoDB存储引擎中,插入操作不仅涉及到行级锁,还可能涉及Gap锁和Next-Key Locks,这些锁机制的设计是为了防止幻读...
值得学习的MySQL行级锁、表级锁、页级锁详细介绍
在MySQL中,锁机制是保障数据操作安全的重要组成部分,其主要分为表锁、行锁和间隙锁。本知识点详细解读了MySQL锁机制的定义、分类、特点以及具体的应用案例。 1. 锁的定义和分类 在数据库系统中,锁是用来控制多...
mysql数据库在查询量大的情况下,有出现死锁状况,有时候死锁导致服务挂了的情况,这脚本就能很好的管理mysql死锁进程。
前者在查询结束后会自动释放锁,通常在事务中使用,以保证在读取数据后,直到事务结束前,数据不会被其他事务修改。后者则允许多个事务同时读取同一行,但不允许写入。 在实际操作中,锁的粒度也是一个重要的概念,...
MySQL锁
MySQL的锁机制对于数据库系统的性能和稳定性起着至关重要的作用。在数据库设计和开发过程中,合理地使用锁策略,能够有效避免死锁现象,提高并发处理能力。接下来,将详细介绍MySQL中的不同类型的锁及其适用场景。 ...
- **表独占写锁**:阻止任何用户对同一表进行读写操作,直至锁被释放。 #### 五、InnoDB行级锁 InnoDB是MySQL中最常用的事务型存储引擎,它支持行级锁和表级锁,但在默认情况下使用行级锁。 ##### InnoDB行级锁的...
在深入探讨MySQL数据库的锁机制之前,我们首先需要了解锁的基本概念。在数据库系统中,锁是一种用来保障并发控制的机制,它用来协调不同事务对同一个数据对象的访问。锁的目的是为了防止多个事务并发操作时造成的...