MySQL数据库表锁定的几种方法实现

MySQL数据库表锁定的几种方法实现,第1张

如果两个程序都向表中写数据显然会造成很大的麻烦,甚至会有意外情况发生。如果表正由一个程序写入,同时进行读取的另一个程序也会产生混乱的结果。

锁定表的方法

防止客户机的请求互相干扰或者服务器与维护程序相互干扰的方法主要有多种。如果你关闭数据库,就可以保证服务器

和myisamchk和isamchk之间没有交互作用。但是停止服务器的运行并不是一个好注意,因为这样做会使得没有故障的数据库和表也不可用。本节主

要讨论的过程,是避免服务器和myisamchk或isamchk之间的交互作用。实现这种功能的方法是对表进行锁定。

服务器由两种表的锁定方法:

1内部锁定

内部锁定可以避免客户机的请求相互干扰——例如,避免客户机的SELECT查询被另一个客户机的UPDATE查询所干扰。也可以利用内部锁定机制防止服务器在利用myisamchk或isamchk检查或修复表时对表的访问。

语法:锁定表:LOCK TABLES tbl_name {READ | WRITE},[ tbl_name {READ | WRITE},…]

解锁表:UNLOCK TABLES

LOCK TABLES为当前线程锁定表。UNLOCK TABLES释放被当前线程持有的任何锁。当线程发出另外一个LOCK TABLES时,或当服务器的连接被关闭时,当前线程锁定的所有表自动被解锁。

如果一个线程获得在一个表上的一个READ锁,该线程(和所有其他线程)只能从表中读。如果一个线程获得一个表上的一个WRITE锁,那么只有持锁的线程READ或WRITE表,其他线程被阻止。

每个线程等待(没有超时)直到它获得它请求的所有锁。

WRITE锁通常比READ锁有更高的优先级,以确保更改尽快被处理。这意味着,如果一个线程获得READ锁,并且然后另外一个线程请求一个WRITE锁, 随后的READ锁请求将等待直到WRITE线程得到了锁并且释放了它。

显然对于检查,你只需要获得读锁。再者钟情跨下,只能读取表,但不能修改它,因此他也允许其它客户机读取表。对于修复,你必须获得些所以防止任何客户机在你对表进行 *** 作时修改它。

2外部锁定

服务器还可以使用外部锁定(文件级锁)来防止其它程序在服务器使用表时修改文件。通常,在表的检查 *** 作中服务器

将外部锁定与myisamchk或isamchk作合使用。但是,外部锁定在某些系统中是禁用的,因为他不能可靠的进行工作。对运行myisamchk或

isamchk所选择的过程取决于服务器是否能使用外部锁定。如果不使用,则必修使用内部锁定协议。

如果服务器用--skip-locking选项运行,则外部锁定禁用。该选项在某些系统中是缺省的,如Linux。可以通过运行mysqladmin variables命令确定服务器是否能够使用外部锁定。检查skip_locking变量的值并按以下方法进行:◆如果skip_locking为off,则外部锁定有效您可以继续并运行人和一个实用程序来检查表。服务器和实用程序将合作对表进行访问。但是,运行任何

一个实用程序之前,应该使用mysqladmin flush-tables。为了修复表,应该使用表的修复锁定协议。

◆如果skip_locaking为on,则禁用外部锁定,所以在myisamchk或isamchk检查修复表示服务器并不知道,最好关闭服务器。如果坚

持是服务器保持开启状态,月确保在您使用此表示没有客户机来访问它。

一些ORACLE中的进程被杀掉后,状态被置为"killed",但是锁定的资源很长时间不释放,有时实在没办法,只好重启数据库。现在提供一种方法解决这种问题,那就是在ORACLE中杀不掉的,在OS一级再杀。

1下面的语句用来查询哪些对象被锁:

select object_name,machine,ssid,sserial#

from v$locked_object l,dba_objects o ,v$session s

where lobject_id = oobject_id and lsession_id=ssid;

2下面的语句用来杀死一个进程:

alter system kill session '24,111'; (其中24,111分别是上面查询出的sid,serial#)

注以上两步,可以通过Oracle的管理控制台来执行。

3如果利用上面的命令杀死一个进程后,进程状态被置为"killed",但是锁定的资源很长时间没有被释放,那么可以在os一级再杀死相应的进程(线程),首先执行下面的语句获得进程(线程)号:

select spid, osuser, sprogram

from v$session s,v$process p

where spaddr=paddr and ssid=24 (24是上面的sid)

4在OS上杀死这个进程(线程):

1)在unix上,用root身份执行命令:

#kill -9 12345(即第3步查询出的spid)

2)在windows(unix也适用)用orakill杀死线程,orakill是oracle提供的一个可执行命令,语法为:

orakill sid thread

其中:

sid:表示要杀死的进程属于的实例名

thread:是要杀掉的线程号,即第3步查询出的spid。

例:c:>orakill orcl 12345

详细步骤如下:

1、点击新建查询按钮,打开SQL命令编辑框,对数据库表的 *** 作以及维护都可以通过编辑SQL命令实现。

2、在编辑框内编辑创建数据库表的代码,确认代码无误后,单击执行按钮,创建数据表。

3、创建数据表的源代码如下:

use test go

if exists(select name from systables where name='Student')

drop table Student go

create table Student

(sname nchar(10) primary key,

sex nchar(2) not null,

bir datetime)

数据库管理系统,database management system,简称dbms,是一种 *** 纵和管理数据库的大型软件,用于建立、使用和维护数据库。用户通过dbms访问数据库中的数据,数据库管理员也通过dbms进行数据库的维护工作。它可使多个应用程序和用户用不同的方法在同时或不同时刻去建立,修改和询问数据库。

提供数据定义语言(ddl)。用它书写的数据库模式被翻译为内部表示。数据库的逻辑结构、完整性约束和物理储,存结构保存在内部的数据字典中。数据库的各种数据 *** 作(如查找、修改、插入和删除等)和数据库的维护管理都是以数据库模式为依据的。

ALTER SYSTEM KILL SESSION '4033,33518'; --解除被锁定的会话信息

select session_id from v$locked_object; --查看哪个会话被锁了

SELECT sid, serial#, username, osuser FROM v$session where sid = 4033; --查看具体被锁会话信息

在DB2的命令行中输入:

update monitor switches using lock on table on

然后打开另一个DB2命令窗口执行我的那个被吊死的Update语句。

然后在第一个DB2命令窗口执行: [@more@]get snapshot for locks on Database_Name(你的数据库的名字)> locksTXT

然后,可以看到第一个DB2的窗口有一个信息输出,把这些信息输出到TXT中,大致如下:

应用程序句柄 = 36

应用程序标识 = AC100C47IC0500F6C6095828

序号 = 0246

应用程序名 = javaexe

CONNECT 授权标识 = DB2ADMIN

应用程序状态 = UOW 正在等待

状态更改时间 = 未收集

应用程序代码页 = 1208

挂起的锁定 = 0

总计等待时间(毫秒) = 0

应用程序句柄 = 43

应用程序标识 = LOCALDB2060512054331

序号 = 2273

应用程序名 = javaexe

CONNECT 授权标识 = DB2ADMIN

应用程序状态 = 联合请求暂挂

状态更改时间 = 未收集

应用程序代码页 = 1208

挂起的锁定 = 6

总计等待时间(毫秒) = 0

锁定列表

锁定名称 = 0x031F9052000000000000000055

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 255

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部

方式 = S

锁定名称 = 0x26800000000000000000000044

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部

方式 = S

锁定名称 = 0x020006000F1700000000000052

锁定属性 = 0x00000000

发行版标志 = 0x00000001

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 5903

对象类型 = 行

表空间名 = USERSPACE1

表模式 = DB2ADMIN

表名 = C_USER

方式 = NS

锁定名称 = 0x01000000010000000500BC0056

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部变化锁定

方式 = S

锁定名称 = 0x535953534E333030FD965C0641

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部方案锁定

方式 = S

锁定名称 = 0x02000600000000000000000054

锁定属性 = 0x00000000

发行版标志 = 0x00000001

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 6

对象类型 = 表

表空间名 = USERSPACE1

表模式 = DB2ADMIN

表名 = C_USER

方式 = IS

应用程序句柄 = 557

应用程序标识 = LOCALDB2060512053913

序号 = 1254

应用程序名 = javaexe

CONNECT 授权标识 = DB2ADMIN

应用程序状态 = 联合请求暂挂

状态更改时间 = 未收集

应用程序代码页 = 1208

挂起的锁定 = 6

总计等待时间(毫秒) = 0

锁定列表

锁定名称 = 0x031F9052000000000000000055

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 255

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部

方式 = S

锁定名称 = 0x26800000000000000000000044

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部

方式 = S

锁定名称 = 0x02000600071D00000000000052

锁定属性 = 0x00000000

发行版标志 = 0x00000001

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 7431

对象类型 = 行

表空间名 = USERSPACE1

表模式 = DB2ADMIN

表名 = C_USER

方式 = NS

锁定名称 = 0x01000000010000000500BC0056

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部变化锁定

方式 = S

锁定名称 = 0x535953534E333030FD965C0641

锁定属性 = 0x00000000

发行版标志 = 0x40000000

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 0

对象类型 = 内部方案锁定

方式 = S

锁定名称 = 0x02000600000000000000000054

锁定属性 = 0x00000000

发行版标志 = 0x00000001

锁定计数 = 1

挂起计数 = 0

锁定对象名 = 6

对象类型 = 表

表空间名 = USERSPACE1

表模式 = DB2ADMIN

表名 = C_USER

方式 = IS

其中应用程序句柄43和557的状态都是死锁了,猜测是这2个应用争用DB2的表,造成死锁,根据日志提示,在DB2的命令窗口输入:

force application (43)

force application (557)

提示这个 *** 作是异步的,我执行list applicaions,结果进程中还有那2个进程,那2个进程可能是在执行比较大的 *** 作,需要耐心等待,如何还不行,则使用下面的命令来强制所有的应用都停止,然后重启DB2:

force application all

terminate

db2stop force

db2start

如果DB2在Window上,则可以使用“控制中心”->实例->右键“应用程序”,可以看到当前的锁定情况,并且可以强行关闭某个进程,也可以显示“锁定链”。

出现锁的根本解决办法不是去手动解锁啊,

而是应该去看,是哪个SESSION,哪个sql语句锁的,锁了哪些资源,是不是应该锁定这些资源!

如果有些锁是不必要的,要么commit事务来释放锁,要不就不锁定这些资源!

修改应用才是应该做的!

1 数据库表锁定原理

11 目前的C/S,B/S结构都是多用户访问数据库,每个时间点会有成千上万个user来访问DB,其中也会同时存取同一份数据,会造成数据的不一致性或者读脏数据

12 事务的ACID原则

13 锁是关系数据库很重要的一部分, 数据库必须有锁的机制来确保数据的完整和一致性

131 SQL Server中可以锁定的资源:

132 锁的粒度:

133 锁的升级:

锁的升级门限以及锁升级是由系统自动来确定的,不需要用户设置

134 锁的类型:

(1) 共享锁:

共享锁用于所有的只读数据 *** 作

(2) 修改锁:

修改锁在修改 *** 作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象

(3) 独占锁:

独占锁是为修改数据而保留的。它所锁定的资源,其他事务不能读取也不能修改。独占锁不能和其他锁兼容。

(4) 架构锁

结构锁分为结构修改锁(Sch-M)和结构稳定锁(Sch-S)。执行表定义语言 *** 作时,SQL Server采用Sch-M锁,编译查询时,SQL Server采用Sch-S锁。

(5) 意向锁

意向锁说明SQL Server有在资源的低层获得共享锁或独占锁的意向。

(6) 批量修改锁

批量复制数据时使用批量修改锁

134 SQL Server锁类型

(1) HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。

(2) NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。

(3) PAGLOCK:指定添加页锁(否则通常可能添加表锁)。 

(4) READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上 *** 作。

(5) READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,

READPAST仅仅应用于READ COMMITTED隔离性级别下事务 *** 作中的SELECT语句 *** 作。 

(6) READUNCOMMITTED:等同于NOLOCK。 

(7) REPEATABLEREAD:设置事务为可重复读隔离性级别。 

(8) ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。

(9) SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。 

(10) TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。 (11) TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。 

(12) UPDLOCK :指定在

读表中数据时设置更新 锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。

2 如何解除表的锁定,解锁就是要终止锁定的那个链接,或者等待该链接事务释放

21 Activity Monitor

可以通过Wait Type, Blocked By栏位查看到,SPID 54 被SPID 53 阻塞 可以右键Details查到详细的SQL 语句,或Kill掉这个进程

22 SQL Server提供几个DMV,查看locks

sysdm_exec_requests

sysdm_tran_locks

sysdm_os_waiting_tasks

sysdm_tran_database_transactions

(1)

select  from sysdm_tran_locks where  resource_type<>'DATABASE' --and resource_database_id=DB_ID()

(2)

SELECT session_id, blocking_session_id,

FROM sysdm_exec_requests

WHERE blocking_session_id > 0

(3)代码

SELECT

request_session_id as Spid,

Coalesce(sname + '' + oname + isnull('' + iname,''),

s2name + '' + o2name,

dbname) AS Object,

lresource_type as Type,

request_mode as Mode,

request_status as Status

FROM sysdm_tran_locks l

LEFT JOIN syspartitions p

ON lresource_associated_entity_id = phobt_id

LEFT JOIN sysindexes i

ON pobject_id = iobject_id

AND pindex_id = iindex_id

LEFT JOIN sysobjects o

ON pobject_id = oobject_id

LEFT JOIN sysschemas s

ON oschema_id = sschema_id

LEFT JOIN sysobjects o2

ON lresource_associated_entity_id = o2object_id

LEFT JOIN sysschemas s2

ON o2schema_id = s2schema_id

LEFT JOIN sysdatabases db

ON lresource_database_id = dbdatabase_id

WHERE resource_database_id = DB_ID()

ORDER BY Spid, Object, CASE lresource_type

When 'database' Then 1

when 'object' then 2

when 'page' then 3

when 'key' then 4

Else 5 end

你先查一下你的数据表示不是锁表了。

select sesssid,

sessserial#,

looracle_username,

loos_user_name,

aoobject_name,

lolocked_mode

from v$locked_object lo,

dba_objects ao,

v$session sess 

where aoobject_id = loobject_id and losession_id = sesssid

通过以上sql就可以知道哪个进程、序列,oracle用户名、 *** 作系统用户名、表名、锁表模式几个字段

下面一步就是将改锁表的进程和序列杀掉了,执行下面的语句即可。

alter system kill session '1020,38953' --(1020,就是执行第一步语句得到的sid字段值,38953就是serial#字段值)

详细的请参照:网页链接

以上就是关于MySQL数据库表锁定的几种方法实现全部的内容,包括:MySQL数据库表锁定的几种方法实现、oracle 锁表、解锁的语句、sqlserver怎么用sql查看具体那个表被锁住了等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/9537750.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-29
下一篇2023-04-29

发表评论

登录后才能评论

评论列表(0条)

    保存