
相关免费学习推荐:mysql数据库(视频)
前面我们讲了mysql数据库底层的数据结构与算法、mysql性能优化篇一些内容。我们再来聊聊mysql的锁与事务隔离级别,分上下两篇,本篇重点讲mysql的行锁与事务隔离级别。
锁是计算机协调多个进程或线程并发访问某一资源的机制。
在数据库中,除了传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供需要用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。
对于锁深入的理解,可以查看《关于J*a中锁的理解》。
行锁(Record Locks)
间隙锁(Gap Locks)
临键锁(Next-key Locks)
共享锁/排他锁(Shared and Exclusive Locks)
意向共享锁/意向排他锁(Intention Shared and Exclusive Locks)
插入意向锁(Insert Intention Locks)
自增锁(Auto-inc Locks)
预测锁,这种锁主要用于存储了空间数据的空间索引。
下篇来分别聊聊,本篇重点是行锁以及事务隔离级别。
每次操作锁住整张表。
示例表,如下:
# 建表SQLCREATE TABLE mylock ( id INT(11) NOT NULL AUTO_INCREMENT, NAME VARCHAR(20) DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE = MyISAM DEFAULT CHARSET = utf8;
# 插入数据INSERT INTO`test`.`mylock`(`id`,`NAME`) VALUES ('1','a');
INSERT INTO`test`.`mylock`(`id`,`NAME`) VALUES ('2','b');
INSERT INTO`test`.`mylock`(`id`,`NAME`) VALUES ('3','c');
INSERT INTO`test`.`mylock`(`id`,`NAME`) VALUES ('4','d');复制代码lock table 表名称 read(write), 表名称2 read(write);复制代码
show open tables;复制代码
unlock tables;复制代码
LOCK TABLE mylock read;复制代码

当前 session 和其他 seesion 都可以读该表;
当前 session 中插入或者更新锁定表都会报错,其他 session 插入或者更新则会等待。

LOCK TABLE mylock WRITE;复制代码

当前 session 对该表的增删改查都没有问题,其他 session 对该表的所有操作都会被阻塞 。
MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁;在执行增删改查操作前,会自动给涉及的表加写锁。
总结:读锁会阻塞写,但不会阻塞读;而写锁则会把读和写都阻塞。
每次操作锁住一行数据。
InnoDB 和 MyISAM 的最大不同点:
事务是由一组 SQL 语句组成的逻辑处理单元,事务具有以下四个属性,通常简称为事务的 ACID属性。
当两个或多个事务选择同一行,然后基于最初选定的值更新该行值,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题,最后的更新覆盖来其他事务所做的更新。
一个事务正在对一条记录做修改,在这个事务完成并提交前,这个条记录的数据就处于不一致的状态;这时另外一个事务也来读取同一条记录,如果不加控制,第二个事务读取来这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象的叫做“脏读”。
总结:事务A读取到来事务B已经修改但尚未提交的数据,还在这个数据基础上做来操作。此时,如果事务B回滚,事务A读取的数据无效,不符合一致性要求。
一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生来改变、或某些记录已经被删除了,这种现象就叫做“不可重复读”。
总结:事务A读取到了事务B已经提交的修改数据,不符合隔离性。
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。
总结:事务A读取到了事务B提交的新增数据,不符合隔离性。
“脏读”、“不可重复读”、“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的。
同时,不同应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读” 并不敏感,可能更关系数据并发访问的能力。
查看当前数据库的事务隔离级别
show variables like 'tx_isolation';复制代码

设置事务隔离级别
set tx_isolation='REPEATABLE-READ';复制代码
数据库版本是5.7,隔离级别是Repeatable-Read(可重复读),不同的数据库版本和隔离级别对语句的执行结果影响很大。所以需要说明版本和隔离级别
BEGIN 或 START TRANSACTION;显式地开启一个事务;COMMIT;也可以使用 COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改称为永久性的;ROLLBACK;有可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;S*EPOINT identifier;S*EPOINT允许在事务中创建一个保存点,一个事务中可以有多个S*EPOINT;RELEASE S*EPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;ROLLBACK TO identifier;把事务回滚到标记点;SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。MYSQL 事务处理主要有两种方法:
SONIFY.io
设计和开发音频优先的产品和数据驱动的解决方案
83
查看详情
BEGIN, ROLLBACK, COMMIT来实现SET AUTOCOMMIT=0 禁止自动提交SET AUTOCOMMIT=1`` 开启自动提交示例表,如下:
CREATE TABLE `user` ( `id` INT (11) NOT NULL AUTO_INCREMENT, `name` VARCHAR (255) DEFAULT NULL, `balance` INT (11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;INSERT INTO `test`.`user` (`name`,`balance`) VALUES ('zhangsan','450');INSERT INTO `test`.`user` (`name`,`balance`) VALUES ('lisi', '16000');INSERT INTO `test`.`user` (`name`,`balance`) VALUES ('wangwu','2400');复制代码一个 session 开启事务更新不提交,另一个 seesion 更新同一条记录会阻塞,更新不同记录u会阻塞。


(1)打开一个客户端A,并设置当前事务模式为 read uncommitted (读未提交),查询表 user 的初始化值
set tx_isolation='read-uncommitted';复制代码

(2)在客户端A的事务提交之前,打开另一个客户端B,更新表 user

(3)这时,虽然客户端B的事务还没提交,但是在客户端A就可以查询到B已经更新的数据

(4)一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那么客户端A查询到的数据其实就是脏数据。

(5)在客户端A执行更新语句 update user set balance = balance - 50 where id = 1; zhangsan 的 balance没有变成350,居然是400,是不是很奇怪,数据不一致啊。如果你这么想就太天真了,在应用程序中,我们会用400-50=350,并不知道其他会话回滚了,要想解决这个问题可以采用读已提交的隔离级别。

(1)打开一个客户端A,并设置当前事务模式为 read committed (读已提交),查询表 user 的所有记录
set tx_isolation='read-committed';复制代码

(2)在客户端A的事务提交之前,打开另一个客户端B,更新表 user

(3)这时,客户端B的事务还没提交,客户端A不能查询到B已经更新的数据,解决了脏读问题。

(4)客户端B的事务提交

(5)客户端A执行与上一步相同的查询,结果与上一步不一致,即产生了不可重复读的问题。

(1)打开一个客户端A,并设置当前的事务模式为 repeatable read ,查询表 user 的所有记录。
set tx_isolation='REPEATABLE-READ';复制代码

(2)在客户端A的事务提交之前,打开另一个客户端B,更新表 user 并提交。

(3)在客户端A查询表 user 的所有记录,与步骤(1)查询结果一直,没有出现不可重复读的问题。

(4)在客户端A,接着执行 update user set balance = balance - 50 where id = 1 , balance 没有变成 400 - 50 = 350, zhangsan 的 balance 的值用的是步骤(2) 中的 350 来计算的,所以是300,数据的一致性倒是没有被破坏。可重复读的隔离级别下使用了 MVCC(multi-version concurrency control)机制,select 操作不会更新版本号,是快照读(历史版本);insert、update、delete 会更新版本号,是当前读(当前版本)。
我们下篇来讲 MVCC。

(5)重新打开客户端B,插入一条新数据后提交。

(6)在客户端A查询表user 的所有记录,没有查出新增数据,所以没有出现幻读。

(7)验证幻读
在客户端A执行 update user set balance = 8888 where id = 4; ,能更新成功,再次查询到客户端B新增的数据。
(1)打开一个客户端A,并设置当前事务模式为 serializable ,查询表 user 的初始值
set tx_isolation='serializable';复制代码

(2)打开一个客户端B,并设置当前事务模式为 serializable ,插入一条记录报错,表被锁了插入失败,MySQL 中事务隔离级别为 serializable 时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。

InnoDB 存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会更高一下,但是在整体并发处理能力方面要远远优于 MyISAM 的表级锁定的。当系统并发量最高的时候,InnoDB 的整体性能和 MyISAM 相比就会有比较明显的优势。
但是,InnoDB 的行级锁定同样也有其脆弱的一面,当我们使用不当的时候,可能会让 InnoDB 的整体性能表现不仅不能比 MyISAM 高,甚至可能会更差。
通过检查 innodb_row_lock 状态变量来分析系统上的行锁的竞争情况:
show status like 'innodb_row_lock%';复制代码

对各个状态量的说明如下:
对于这5个状态变量,比较重要的主要是:
尤其是当等待次数很高,而且每次等待时长也不小的时候,我们就需要分析系统 中为什么会有如此多的等待,然后根据分析结果着手制定优化计划。
set tx_isolation='REPEATABLE-READ';复制代码
Session_1执行:select * from user where id=1 for update; Session_2执行:select * from user where id=2 for update; Session_1执行:select * from user where id=2 for update; Session_2执行:select * from user where id=1 for update;复制代码
查看近期死锁日志信息:
show engine innodb status\G;复制代码
大多数情况mysql可以自动检测死锁并回滚产生死锁的那个事务,但是有些情况 mysql没法自动检测死锁
repeatable-read,有什么办法可以解决幻读妈?间隙锁(Gap Lock)在某些情况下可以解决幻读问题,它是 Innodb 在 可重复读 提交下为解决幻读问题时引入的锁机制。要避免幻读可以用间隙锁在Session_1 下面执行 update user set name = 'hjh' where id > 10 and id ,则其他 Session 没法在这个范围锁包含的间隙里插入或修改任何数据。
如:user 表有3条数据, id > 2 and id 会把第三条记录锁住,其他会话对则无法对第三条记录做操作。


客户端A执行: update user set balance = 800 where name = 'zhangsan';

客户端B对该表任一行执行修改、删除操作都会阻塞

InnoDB 的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁。
local in share mode(共享锁) 和 for update(排它锁) ,例如: select * from test_innodb_lock where a = 2 for update; 这样其他 session 只能读这行数据,修改则会被阻塞,直到锁定行的 session 提交。以上就是你知道MySQL锁与事物隔离级别吗?的详细内容,更多请关注其它相关文章!
# 就会
# 福田网站建设系统哪个好
# seo黑猫技巧
# 崇明区搜索引擎网站优化
# 样品市场推广营销
# 近的宝安网站推广
# 修武县网站推广公司有哪些
# 散文好句网站推广文案
# 如何优化推广网站
# 怎样完成网站优化
# 如何给企业电话营销推广
# MySQL
# 则会
# 事务处理
# 不符合
# 你知道
# 多个
# 数据结构
# 镜像
# 死锁
# 客户端
# 锁与事物
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
六级准考证号怎么查_四六级准考证查询入口官网
如何用mysql开发用户注册登录功能_mysql用户注册登录数据库设计
抖音号显示企业机构号是什么意思?企业机构号申请条件是什么?
《健康大兴》注册方法介绍
GBA模拟器手柄按键设置
J*aScript调试技巧_性能分析与内存快照
QQ邮箱PC端登录页面_QQ邮箱网页版登录界面
t3出行如何使用微信支付
《地下城堡4:骑士与破碎编年史》墓穴挑战125攻略
Python类装饰器动态修改方法时的类型提示:Mypy插件实现精确静态分析
win11关机几秒又自己开机 Win11关机自动重启问题修复
《三角洲行动》战斗步枪与机枪类改装代码分享
mysql离线安装后如何启动_mysql离线安装完成后启动服务的方法
国际经济与贸易就业方向解析
美发店速赢秘籍
《花瓣》创建专辑方法
创建快捷方式启动系统保护
sublime如何处理超大文件不卡顿 _sublime打开大日志文件技巧
猫眼电影app如何参与官方的抽奖活动_猫眼电影官方抽奖参与方法
Dagster资产间数据传递与用户配置管理教程
解决CSS background 属性中 cover 关键字的常见误用
Yandex浏览器官方入口_Yandex搜索引擎中文版
谷歌学术论文搜索引擎 谷歌学术官网入口论坛永久链接
《战地6》反作弊已成功拦截240万次作弊 发售第一周98%比赛没有作弊
苹果电脑如何快速查看电池状态 苹果电脑电池信息快捷方法
Linux如何开发轻量级数据服务模块_Linux服务化设计
PHP实现等比数列:构建数组元素基于前一个值递增的方法
菜鸟裹裹怎样获得取件码_菜鸟裹裹获得取件码步骤
Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题
《浙里办》电子发票开具方法
手机自动关机是怎么回事?如何修复?手机异常关机的原因排查与修复技巧
重返未来:1999卡戎全方位攻略
菜鸟驿站的取件码忘了怎么办 手机快速查询指南
《下一站江湖2》大雪山加入方法
创客贴登录页面入口 创客贴网页版最新网址链接
mysql数据库索引类型有哪些_mysql索引类型解析
怎么恢复删除的电脑文件_数据恢复软件使用教程
Win10关闭UAC用户账户控制的方法 Win10降低安全提示等级【技巧】
QQ阅读小说搜索入口地址_QQ阅读小说搜索入口地址搜索在线阅读
XPath动态元素定位:如何精准选择文本内容变化的元素
魔法祈幻界兑换码礼包大全
Golang如何使用crypto/md5生成哈希_Golang MD5哈希生成方法
《雷电模拟器》截图方法介绍
word文档行距怎么调?word文档调行距的操作步骤
处理含命名空间的XML文件 Power Query中的高级技巧
J*a实现任务清单管理_集合框架综合入门练手
《书耽》更换手机号方法
知音漫客官网首页入口_知音漫客热门漫画推荐
小红书网页版首页入口 小红书网页版电脑端官方登录链接
Win10共享文件夹设置方法 Win10局域网文件共享全攻略【教程】
2020-10-06
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。