mysql 存储过程 行锁_mySQL教程 第10章 事务和锁

第10章 事务和锁

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。

表级锁

myISAM存储引擎和InnoDB存储引擎都支持表级锁。

myISAM存储引擎支持表级锁,为了保证数据的一致性,更改数据时,防止其他人更改数据,可以人工添加表级锁。我们可以使用命令对数据库的表枷锁,使用命令对数据库的表解锁。

给表加锁的命令Lock Table,给表解锁的命令Unlock Tables

现在是学习阶段,用lock Tables和Unlock Tables显示加锁和解锁。其实MyISAM引擎在用户读数据自动加read锁,更改数据自动加write锁。

准备实验环境

使用sqlmanager建立两个回话连接到MySQL。

验证给表加锁,对其他用户的影响。

50dbcee38fe90bc6209ce34eafd74502.png

a8d9d8f035e6d490f73584117f1dbb1a.png

注意数据库别名schoolDB session_1表明是第一个回话。

c156aa47363726a247a21d7ba8922a10.png

在添加一个回话

f540be356806d3240c225c52d737997e.png

d33d7249e74b6b4446bee3d881a88540.png

注意数据库别名是schoolDB session_2表明是第二个回话。

1c67ddbd5787f8a7951e70d60165f668.png

双击 session 1,点击红框图标

a387635cdebfdbe4bf5eeae794538c0c.png

可以看到session1建立的回话。

bc41e47a7cfe1288b2423e09d84facae.png

创建存储引擎为myISAM的表。

CREATE TABLE `TStudent` (

`StudentID` varchar(15) NOT NULL,

`Sname` varchar(10) DEFAULT NULL,

`sex` char(1) DEFAULT NULL,

`cardID` varchar(20) DEFAULT NULL,

`Birthday` datetime DEFAULT NULL,

`Email` varchar(40) DEFAULT NULL,

`Class` varchar(20) DEFAULT NULL,

`enterTime` datetime DEFAULT NULL

) ENGINE=myISAM DEFAULT CHARSET=utf8;

创建成绩表

CREATE TABLE `TScore` (

`StudentID` varchar(15) DEFAULT NULL,

`subJectID` varchar(10) DEFAULT NULL,

`mark` decimal(10,0) DEFAULT NULL

) ENGINE=myISAM DEFAULT CHARSET=utf8;

插入记录

insert into TStudent values

('00001','张四非','男','132302189009082324','19820203','zsf@hotmail.com','JAVA',NOW()),

('00002','张二臣','男','132302192009082324','19890203','zec@hotmail.com','JAVA',NOW()),

('00003','李玉红','女','132302189009082324','19890203','LYH@hotmail.com','NET',NOW())

插入成绩

insert TScore values

('00001','0001',89),

('00001','0002',97),

('00002','0001',89),

('00002','0002',68),

('00003','0001',78),

('00003','0002',76)

在以同样的方式建立使用root建立一个回话session2

d24cba494d64599f257f1f49367fd334.png

01c83953dbc5baa73cdc909aa22955a1.png

05622f21621f3d262becb5e47d6f61a0.png

练习1:验证表级锁对用户并发性影响

Read锁是共享锁,不影响其他回话的读取,但是不能更新加read锁的数据。MyISAM表的读写是串行的,但这是总体而言的,在一定条件下,myISAM表也支持查询和插入操作的并发进行。

MyISAM有个系统变量concurrent Insert,设置为0时,不允许并发插入。

设置为1时,MyISAM表没有空洞,允许一个进程读取表时,另一个进程从表尾插入记录,这是默认设置。

设置为2时,无论MyISAM表中有没有空洞,都允许在表末尾并发插入记录。

1. 验证read锁

在session1执行以下语句给TStudent表加read锁,该锁允许其他回话能够查询,但是不能更改。

lock tables TStudent read local

在session2上执行以下语句

select * from TStudent

可以看到能够查询出结果。

25f1726851382159c271f95b7eb150a5.png

2. 在session_2可以并发插入新记录

insert into TStudent values

('00004','刘立秋','男','132302189009082324','19820203','llq@hotmail.com','JAVA',NOW())

327596c60f37f227b0ce4a3b4bae213e.png

3. 在session_1上不能删除更新数据

添加read锁后,自己也不能更改数据

dddd405eac3a86beeec0d90e827e0d09.png

4. 在Session_1上不能查看没有锁定的表

a6ac5716463cde473a4d349ecdee63be.png

5. Session2更新表中的一个记录

update TStudent set sname='韩利刚'

where studentid='00001'

你会发现一直没有执行完的结果出现

在Session1上执行以下命令 解锁表

unlock tables

可以看到session_2完成更新。

979ff92ea5bffd34789f4f828120f2a4.png

练习2:在session1给TStudent表添加write锁

write锁,是独占锁。其他回话不能查询加了write锁的表。

6. 在session1上给TStudent表添加write锁,在session2上查询TStudent表,你会处于发现等待状态。

lock tables TStudent write

3e6a40151d234691e511d127b7a9cc6c.png

7. 在session1上执行unlock tables,可以看到session立即出现查询结果。

bfd9f64eb9f08fe157bfc6ce3ca03046.png

行级锁

事务加锁,是这对所操作的行,对其他行不进行加锁处理。

准备实验环境

支持事务的存储引擎是InnoDB,必须将数据库或表的存储引擎设置InnoDB支持事务。

d825095120521e2a83bf08c701e8d8bf.png

默认情况下mySQL是自动提交事务,如果需要通过明确的Commit和Rollback来提交和回滚事务,那么就需要通过明确的事务控制命令开始。

练习3:不能查看其它事务未提交的数据记录

以下练习使用显示事务为你演示,每个事务使用start transaction开始,使用commit提交。

以下为你展示:只有提交了的事务,数据变化才被写到数据库,其他回话才能看到其变化。

Session1执行以下命令

select * from TStudent where studentid='00010'

在session2执行以下命令

select * from TStudent where studentid='00010'

没有该记录

a8cbf81a7e1c2285a89181cf8770f79c.png

在session1上开始一个事务,插入一条记录

start transaction

insert into TStudent values

('00010','张非','男','132302189009082324','19820203','zsf@hotmail.com','JAVA',NOW())

在session2上,输入以下命令查询插入的记录,看好了,先点击543c59b34a651b6e23cdd5aba2ffb720.png,再点击1f64fac3341b46d0e5e67decdaafc3f3.png

select * from TStudent where studentid='00010'

发现没有。因为session1的事务没有提交。

a6fd61df020860b1f13daa4a607f29da.png

在session1提交事务

Commit

在session2查看插入的记录

select * from TStudent where studentid='00010'

cb633d0f675c8edf2565c0969b145b94.png

练习4:使用select语句添加独占锁

默认情况下select不添加锁,你可以使用命令显式添加共享锁或排它锁。

在Session_1上,使用select….for update语句为studentid为00001的学生添加独占锁。

set autocommit=0 关闭自动提交

Select * from TStudent where studentid='00001' for update

update TStudent set sname='韩力刚' where studentid='00001'

commit

在Session上查询studentid是00002的记录,能够成功查询,可见InnoDB数据库引擎支持行级锁。

set autocommit=0

select * from TStudent where studentid='00001'

select * from TStudent where studentid='00001' for update

select * from TStudent where studentid='00001' for update

956a01cb562e52a4d8d7dc48855a962b.png

总结:Select 语句中使用 for update加锁记录不影响其他事务读取数据,但其他事务不能加独占锁。

练习5:使用select语句添加共享锁 (产生死锁的过程)

A事务添加共享锁后,B事务页可以添加共享锁。这时A事务udpdate锁定记录,处于等待中,于此同时B事务也update更新锁定的记录,就产生死锁。下面练习演示死锁的产生。

在session_1上的语句

set autocommit=0

select sname from TStudent where studentid='00001' lock in share mode

update TStudent set sname='韩利钢' where studentid='00001'

在session_2上的语句

set autocommit=0

select sname from TStudent where studentid='00001' lock in share mode

update TStudent set sname='韩力钢' where studentid='00001'

607bd5e09fb31953295be13563280b74.png

使用条件确定事务和回滚事务

以下代码实现了由条件控制事务的提交和回滚,事务是应该回滚还是提交,由程序员确定。

练习6:在存储过程中使用事务

创建存储过程,给指定学号的学生加分,如果超过100分,回滚事务。将加分的学生成绩放到临时表,然后再查临时表中最高分是否大于100分,如果大于100分就回滚事务,临时表用完就删除。

将TScore表的存储引擎更改为InnoDB,

03cf8abb55683d65c71edfe6a1fde40c.png

create procedure addMark(stuid varchar(6),plusMark int)

begin

declare Pmark int;

CREATE TEMPORARY TABLE tmp_table(mark int);

start transaction;

update TScore set mark= mark+plusMark where StudentID=stuid;

insert tmp_table select mark from TScore where StudentID=stuid;

select max(mark) into Pmark from tmp_table;

if Pmark>100 then

rollback;

else

commit;

end if;

end查询学号是00001的学生,现有分数。

select * from TScore where studentid='00001'

call addMark('00001',1)

为该生所有科目加1分。

496862eba17f38013409410914f4c835.png

c1fb1a0e75d50c27586db2262dc2c742.png

总结:事务是提交还是回滚,完全由开发人员定义。

关闭自动提交

默认mySQL自动提交SQL语句,如果打算显示提交,需要关闭自动提交。

关闭自动提交

set autocommit=0

查看自动提交的设置是否打开

show variables like '%autocommit%';

02b42c0d79dd2c0373a7426342293b25.png

广告

5d86e0b29079e00f5e9edc756fe1ab3e.png

3905219a5146b361ad956b12feb438eb.png

4f1ce5c4a084d6005016786624762315.png

2e2ef75bbb073a83f0b7692b62595797.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值