我们专注攀枝花网站设计 攀枝花网站制作 攀枝花网站建设
成都网站建设公司服务热线:400-028-6601

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

mysql长事务怎么 mysql长事务有什么影响

MySQL数据库表被锁、解锁,删除事务

在程序员的职业生涯中,总会遇到数据库表被锁的情况,前些天就又撞见一次。由于业务突发需求,各个部门都在批量操作、导出数据,而数据库又未做读写分离,结果就是:数据库的某张表被锁了!

创新互联建站是一家专注于网站建设、成都做网站与策划设计,佛山网站建设哪家好?创新互联建站做网站,专注于网站建设十年,网设计领域的专业建站公司;建站业务涵盖:佛山等地区。佛山做网站价格咨询:028-86922220

用户反馈系统部分功能无法使用,紧急排查,定位是数据库表被锁,然后进行紧急处理。这篇文章给大家讲讲遇到类似紧急状况的排查及解决过程,建议点赞收藏,以备不时之需。

用户反馈某功能页面报502错误,于是第一时间看服务是否正常,数据库是否正常。在控制台看到数据库CPU飙升,堆积大量未提交事务,部分事务已经阻塞了很长时间,基本定位是数据库层出现问题了。

查看阻塞事务列表,发现其中有锁表现象,本想利用控制台直接结束掉阻塞的事务,但控制台账号权限有限,于是通过客户端登录对应账号将锁表事务kill掉,才避免了情况恶化。

下面就聊聊,如果当突然面对类似的情况,我们该如何紧急响应?

想象一个场景,当然也是软件工程师职业生涯中会遇到的一种场景:原本运行正常的程序,某一天突然数据库的表被锁了,业务无法正常运转,那么我们该如何快速定位是哪个事务锁了表,如何结束对应的事物?

首先最简单粗暴的方式就是:重启MySQL。对的,网管解决问题的神器——“重启”。至于后果如何,你能不能跑了,要你自己三思而后行了!

重启是可以解决表被锁的问题的,但针对线上业务很显然不太具有可行性。

下面来看看不用跑路的解决方案:

遇到数据库阻塞问题,首先要查询一下表是否在使用。

如果查询结果为空,那么说明表没在使用,说明不是锁表的问题。

如果查询结果不为空,比如出现如下结果:

则说明表(test)正在被使用,此时需要进一步排查。

查看数据库当前的进程,看看是否有慢SQL或被阻塞的线程。

执行命令:

该命令只显示当前用户正在运行的线程,当然,如果是root用户是能看到所有的。

在上述实践中,阿里云控制台之所以能够查看到所有的线程,猜测应该使用的就是root用户,而笔者去kill的时候,无法kill掉,是因为登录的用户非root的数据库账号,无法操作另外一个用户的线程。

如果情况紧急,此步骤可以跳过,主要用来查看核对:

如果情况紧急,此步骤可以跳过,主要用来查看核对:

看事务表INNODB_TRX中是否有正在锁定的事务线程,看看ID是否在show processlist的sleep线程中。如果在,说明这个sleep的线程事务一直没有commit或者rollback,而是卡住了,需要手动kill掉。

搜索的结果中,如果在事务表发现了很多任务,最好都kill掉。

执行kill命令:

对应的线程都执行完kill命令之后,后续事务便可正常处理。

针对紧急情况,通常也会直接操作第一、第二、第六步。

这里再补充一些MySQL锁相关的知识点:数据库锁设计的初衷是处理并发问题,作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则,而锁就是用来实现这些访问规则的重要数据结构。

根据加锁的范围,MySQL里面的锁大致可以分成全局锁、表级锁和行锁三类。MySQL中表级别的锁有两种:一种是表锁,一种是元数据锁(metadata lock,MDL)。

表锁是在Server层实现的,ALTER TABLE之类的语句会使用表锁,忽略存储引擎的锁机制。表锁通过lock tables… read/write来实现,而对于InnoDB来说,一般会采用行级锁。毕竟锁住整张表影响范围太大了。

另外一个表级锁是MDL(metadata lock),用于并发情况下维护数据的一致性,保证读写的正确性,不需要显式的使用,在访问一张表时会被自动加上。

常见的一种锁表场景就是有事务操作处于:Waiting for table metadata lock状态。

MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景。

一旦alter table TableA的操作停滞在Waiting for table metadata lock状态,后续对该表的任何操作(包括读)都无法进行,因为它们也会在Opening tables的阶段进入到Waiting for table metadata lock的锁等待队列。如果核心表出现了锁等待队列,就会造成灾难性的后果。

通过show processlist可以看到表上有正在进行的操作(包括读),此时alter table语句无法获取到metadata 独占锁,会进行等待。

通过show processlist看不到表上有任何操作,但实际上存在有未提交的事务,可以在information_schema.innodb_trx中查看到。在事务没有完成之前,表上的锁不会释放,alter table同样获取不到metadata的独占锁。

处理方法:通过 select * from information_schema.innodb_trxG, 找到未提交事物的sid,然后kill掉,让其回滚。

通过show processlist看不到表上有任何操作,在information_schema.innodb_trx中也没有任何进行中的事务。很可能是因为在一个显式的事务中,对表进行了一个失败的操作(比如查询了一个不存在的字段),这时事务没有开始,但是失败语句获取到的锁依然有效,没有释放。从performance_schema.events_statements_current表中可以查到失败的语句。

处理方法:通过performance_schema.events_statements_current找到其sid,kill 掉该session,也可以kill掉DDL所在的session。

总之,alter table的语句是很危险的(核心是未提交事务或者长事务导致的),在操作之前要确认对要操作的表没有任何进行中的操作、没有未提交事务、也没有显式事务中的报错语句。

如果有alter table的维护任务,在无人监管的时候运行,最好通过lock_wait_timeout设置好超时时间,避免长时间的metedata锁等待。

关于MySQL的锁表其实还有很多其他场景,我们在实践的过程中尽量避免锁表情况的发生,当然这需要一定经验的支撑。但更重要的是,如果发现锁表我们要能够快速的响应,快速的解决问题,避免影响正常业务,避免情况进一步恶化。所以,本文中的解决思路大家一定要收藏或记忆一下,做到有备无患,避免突然状况下抓瞎。

Mysql中的事务是什么如何使用

什么是事务?

事务是逻辑上的一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务

注意:mysql数据支持事务,但是要求必须是innoDB存储引擎

解决这个问题:

mysql的事务解决这个问题,因为mysql的事务特性,要求这组操作,要不全都成功,要不全都失败,这样就避免了某个操作成功某个操作失败。利于数据的安全

如何使用:

(1)在执行sql语句之前,我们要开启事务 start transaction;

(2)正常执行我们的sql语句

(3)当sql语句执行完毕,存在两种情况:

1,全都成功,我们要将sql语句对数据库造成的影响提交到数据库中,committ

2,某些sql语句失败,我们执行rollback(回滚),将对数据库操作赶紧撤销

(注意:mysql数据支持事务,但是要求必须是innoDB存储引擎)

mysql create table bank(name varchar(20),money decimal(5,1))engine=innodb defau

lt charset=utf8;

mysql inset into bank values('shaotuo',1000),('laohu',5000);

mysql select*from bank;

+---------+--------+

| name | money |

+---------+--------+

| shaotuo | 1000.0 |

| laohu | 5000.0 |

+---------+--------+

------没有成功“回滚”执行rollback

mysql start transaction; //开启事务

Query OK, 0 rows affected (0.00 sec)

mysql update bank set money=money+500 where name='shaotuo';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql update bank set moey=money-500 where name='laohu';

ERROR 1054 (42S22): Unknown column 'moey' in 'field list'

mysql rollback; //只要有一个不成功,执行rollback操作

Query OK, 0 rows affected (0.01 sec)

mysql select*from bank;

+---------+--------+

| name | money |

+---------+--------+

| shaotuo | 1000.0 |

| laohu | 5000.0 |

+---------+--------+

------成功之后 进行commit操作

mysql start transaction; //开启事务

Query OK, 0 rows affected (0.00 sec)

mysql update bank set money=money+500 where name='shaotuo';

Query OK, 1 row affected (0.01 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql update bank set money=money-500 where name='laohu';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql commit; //两个都成功后执行commit(只要不执行commit,sql语句不会对真实的数据库造成影响)

Query OK, 0 rows affected (0.05 sec)

mysql select*from bank;

+---------+--------+

| name | money |

+---------+--------+

| shaotuo | 1500.0 |

| laohu | 4500.0 |

+---------+--------+

Mysql数据库中,事务是指什么?如何使用该功能?

什么是事务? \x0d\x0a\x0d\x0a事务是逻辑上的一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务 \x0d\x0a\x0d\x0a注意:mysql数据支持事务,但是要求必须是innoDB存储引擎 \x0d\x0a\x0d\x0a解决这个问题: \x0d\x0a\x0d\x0amysql的事务解决这个问题,因为mysql的事务特性,要求这组操作,要不全都成功,要不全都失败,这样就避免了某个操作成功某个操作失败。利于数据的安全 \x0d\x0a\x0d\x0a如何使用: \x0d\x0a\x0d\x0a(1)在执行sql语句之前,我们要开启事务 start transaction; \x0d\x0a\x0d\x0a(2)正常执行我们的sql语句 \x0d\x0a\x0d\x0a(3)当sql语句执行完毕,存在两种情况: \x0d\x0a\x0d\x0a1,全都成功,我们要将sql语句对数据库造成的影响提交到数据库中,committ \x0d\x0a\x0d\x0a2,某些sql语句失败,我们执行rollback(回滚),将对数据库操作赶紧撤销 \x0d\x0a\x0d\x0a(注意:mysql数据支持事务,但是要求必须是innoDB存储引擎) \x0d\x0amysql create table bank(name varchar(20),money decimal(5,1))engine=innodb defau \x0d\x0alt charset=utf8; \x0d\x0a\x0d\x0amysql inset into bank values('shaotuo',1000),('laohu',5000); \x0d\x0a\x0d\x0amysql select*from bank; \x0d\x0a+---------+--------+ \x0d\x0a| name | money | \x0d\x0a+---------+--------+ \x0d\x0a| shaotuo | 1000.0 | \x0d\x0a| laohu | 5000.0 | \x0d\x0a+---------+--------+ \x0d\x0a\x0d\x0a------没有成功“回滚”执行rollback \x0d\x0amysql start transaction; //开启事务 \x0d\x0aQuery OK, 0 rows affected (0.00 sec) \x0d\x0a\x0d\x0amysql update bank set money=money+500 where name='shaotuo'; \x0d\x0aQuery OK, 1 row affected (0.00 sec) \x0d\x0aRows matched: 1 Changed: 1 Warnings: 0 \x0d\x0a\x0d\x0amysql update bank set moey=money-500 where name='laohu'; \x0d\x0aERROR 1054 (42S22): Unknown column 'moey' in 'field list' \x0d\x0amysql rollback; //只要有一个不成功,执行rollback操作 \x0d\x0aQuery OK, 0 rows affected (0.01 sec) \x0d\x0a\x0d\x0amysql select*from bank; \x0d\x0a+---------+--------+ \x0d\x0a| name | money | \x0d\x0a+---------+--------+ \x0d\x0a| shaotuo | 1000.0 | \x0d\x0a| laohu | 5000.0 | \x0d\x0a+---------+--------+ \x0d\x0a------成功之后 进行commit操作 \x0d\x0amysql start transaction; //开启事务 \x0d\x0aQuery OK, 0 rows affected (0.00 sec) \x0d\x0a\x0d\x0amysql update bank set money=money+500 where name='shaotuo'; \x0d\x0aQuery OK, 1 row affected (0.01 sec) \x0d\x0aRows matched: 1 Changed: 1 Warnings: 0 \x0d\x0a\x0d\x0amysql update bank set money=money-500 where name='laohu'; \x0d\x0aQuery OK, 1 row affected (0.00 sec) \x0d\x0aRows matched: 1 Changed: 1 Warnings: 0 \x0d\x0a\x0d\x0amysql commit; //两个都成功后执行commit(只要不执行commit,sql语句不会对真实的数据库造成影响) \x0d\x0aQuery OK, 0 rows affected (0.05 sec) \x0d\x0a\x0d\x0amysql select*from bank; \x0d\x0a+---------+--------+ \x0d\x0a| name | money | \x0d\x0a+---------+--------+ \x0d\x0a| shaotuo | 1500.0 | \x0d\x0a| laohu | 4500.0 | \x0d\x0a+---------+--------+

mysql 死锁排查

一、show ENGINE INNODB status

查看死锁位置,分析。

二、

首先解决死锁可以从死锁发生的条件入手,最容易解决的就是更改获取资源的顺序;

其次是避免长事务,让事务执行的时间尽可能少,让事务的覆盖范围尽可能小,长事务会导致并发度降低,且会有更多的SQL查 询延迟;

给整个方法加事务是否是必须的?可以不加事务的尽量不加。

如何在mysql 的存储过程中使用事务

6.7 MySQL 事务与锁定命令

6.7.1 BEGIN/COMMIT/ROLLBACK 句法

缺省的,MySQL 运行在 autocommit 模式。这就意味着,当你执行完一个更新时,MySQL 将立刻将更新存储到磁盘上。

如果你使用事务安全表 (例如 InnoDB、BDB),通过下面的命令,你可以设置 MySQL 为非 autocommit 模式:

SET AUTOCOMMIT=0

在此之后,你必须使用 COMMIT 来存储你的更改到磁盘上,或者使用 ROLLBACK ,如果你希望忽略从你的事务开始所做的更改。

如果你希望为一系列语句从 AUTOCOMMIT 模式转换,你可以使用 START TRANSACTION 或 BEGIN 或 BEGIN WORK 语句:

START TRANSACTION;

SELECT @A:=SUM(salary) FROM table1 WHERE type=1;

UPDATE table2 SET summmary=@A WHERE type=1;

COMMIT;

START TRANSACTION 在 MySQL 4.0.11 中被加入;这是被推荐的开始一个特别(ad-hoc)事务的方式,因为这是 ANSI SQL 句法。

注意,如果你使用的是一个非事务安全表,更改会立刻被存储,不受 autocommit 模式状态的约束。

当你更新了一个非事务表后,如果你执行一个 ROLLBACK,你将得到一个错误 (ER_WARNING_NOT_COMPLETE_ROLLBACK) 作为一个警告。所有事务安全表将被恢复,但是非事务安全表将不会改变。

如果你使用 START TRANSACTION 或 SET AUTOCOMMIT=0,你应该使用 MySQL

二进制日志做备份以代替老的更新日志。事务处理被以一个大块形式存储在二进制日志中,在 COMMIT

上面,为了保护回滚的事务,而不是被存储的。查看章节 4.9.4 二进制日志。 如果您使用起动事务处理或集AUTOCOMMIT=0

,您应该使用MySQL 二进制日志为备份代替更旧的更新日志。 事务处理存储在二进制登录一大块,做,保证, 滚的事务处理不存储。 参见部分4

。9.4 二进制日志。

下列命令自动的结束一个事务 (就好像你在执行这个命令之前,做了一个 COMMIT):

命令 命令 命令

ALTER TABLE BEGIN CREATE INDEX

DROP DATABASE DROP TABLE RENAME TABLE

TRUNCATE

你可以使用 SET TRANSACTION ISOLATION LEVEL ... 改变事务的隔离级。查看章节 6.7.3 SET TRANSACTION 句法。

6.7.2 LOCK TABLES/UNLOCK TABLES 句法

LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}

[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]

...

UNLOCK TABLES

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

为了在 MySQL 4.0.2 使用 LOCK TABLES ,你必须拥有一个全局的 LOCK TABLES 权限和一个在相关表上的

SELECT 权限。在 MySQL 3.23 中,你对该表需要有 SELECT、insert、DELETE 和 UPDATE 权限。

使用 LOCK TABLES 的主要原因是,仿效事务处理或在更新表时得到更快的速度。此后会有更详细的描述。

如果一个线程在一个表上得到一个 READ 锁,该线程 (和所有其它线程) 只能从表中读取。如果一个线程在一个表上得到一个 WRITE 锁,那么只有拥有这个锁的线程可以从表中读取和写表。其它的线程被阻塞。

READ LOCAL 和 READ 之间的不同就在于,当锁被加载时,READ LOCAL 允许非冲突(non-conflicting) INSERT 语句执行。如果当你加载着锁时从 MySQL 外部操作数据库文件,这将仍不能被使用。

当你使用 LOCK TABLES 是地,你必须锁定所有你将使用的表,并且必须使用与你的查询中将使用的别名相同!如果你在一个查询中多次使用一个表(用别名),你必须为每一个别名获得一个锁。

WRITE 锁通过比 READ 锁有更高的权限,以确保更新被尽快地处理。这就意味着,如果一个线程获得一个 READ

锁,而同时另外一个线程请求一个 WRITE 锁,并发的 READ 锁请求将等待直到 WRITE 线程得到了锁并释放了它。你可以使用

LOW_PRIORITY WRITE 锁,当该线程在等待 WRITE 锁时,它将允许其它的线程获得 READ 锁。 你应该只使用

LOW_PRIORITY WRITE 锁,如果你确信这将是最后一次,当没有线程将拥有 READ 锁。

LOCK TABLES 工作如下:

以内部定义的次序排序所有被锁定的表 (从用户立场说,该次序是不明确的)。

如果一个表被以一个读锁和一个写锁锁定,将写锁放在读锁之前。

一次只锁定一个表,只到线程得到所有的锁定。

这个方案是为了确保,表锁定死锁释放。 对于这个模式你仍然有些其它事情需要知道:

如果你对一个表使用一个 LOW_PRIORITY WRITE 锁定,这就意味着,MySQL 将等待这个锁,直到没有线程请求一个 READ

锁。当线程得到了 WRITE 锁,并等待获得锁定表列表中的下一个表的锁定时,其它所有的线程将等待 WRITE

锁被释放。如果这在你的应用程序中会引起一个严重的问题,你应该考虑将你的某些表转换为事务安全表。

你可以使用 KILL 安全地杀死一个正在表锁定的线程。查看章节 4.5.5 KILL 句法。

注意,你不应该 锁定你正在对其使用 INSERT DELAYED 的表。这是因为,在这种情况下,INSERT 是通过单独的线程完成的。

通常,你不需要锁定任何表,因为所有单 UPDATE 语句都是原子的;其它的线程无法干扰当前执行的 SQL 语句。当你无论如何希望锁定表时,这里有一些情况:

如果你在一束表上运行许多操作,锁定你将要使用的表,这会更快一些。当然有不利的方面,其它线程将不能更新一个 READ

锁的表,并且没有其它线程要以读取一个 WRITE 锁的表。 在 LOCK TABLES 下,某些事运行得更快一些的原因是,MySQL

将不会转储清除被锁定表键高速缓冲,直到 UNLOCK TABLES 被调用 (通常键高速缓冲在每个 SQL 语句后都会被转储清除)。这将加速在

MyISAM 表上的插入、更新、删除。

如果你在 MySQL 中正在使用一个不支持事务的存储引擎,如果你希望能确保没有其它的线程会出现在一个 SELECT 和 一个 UPDATE 之间,你必须使用 LOCK TABLES 。下面的示例显示为了安全地执行,这里需要LOCK TABLES :

mysql LOCK TABLES trans READ, customer WRITE;

mysql SELECT SUM(value) FROM trans WHERE customer_id=some_id;

mysql UPDATE customer SET total_value=sum_from_previous_statement

- WHERE customer_id=some_id;

mysql UNLOCK TABLES;

不使用 LOCK TABLES,将可能发生在 SELECT 和 UPDATE 语句执行期间有另外一个线程可能在 trans 表中插入一行新记录。

通过使用递增更新 (UPDATE customer SET value=value+new_value) 或 LAST_INSERT_ID() 函数,你可以在很多情况下避免使用 LOCK TABLES。

你也可以使用用户级锁定函数 GET_LOCK() 和 RELEASE_LOCK() 解决一些情况,这些锁被保存在服务器上的一个哈希表中,并以

pthread_mutex_lock() 和 pthread_mutex_unlock() 实现以获得高速度。查看章节 6.3.6.2

辅助功能函数。

查看章节 5.3.1 MySQL 如何锁定表,以获取关于锁定方案的更多信息。

你可以使用 FLUSH TABLES WITH READ LOCK 命令以读锁锁定所有数据库中的所有表。查看章节 4.5.3 FLUSH 句法。如果你有一个可以及时建立文件快照的文件系统,例如 Veritas,这将是得到备份的非常方便方式。

注意:LOCK TABLES 不是事务安全的,在尝试锁定一个表之前,将自动地提交所有的活动事务。

6.7.3 SET TRANSACTION 句法

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL

{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

设置全局的、整个会话或下一个事务的事务隔离级。

缺省行为是设置下一个(未启动的)事务的隔离级。如果你使用 GLOBAL

关键词,语句为所有在那个点上建立的新连接设置默认的全局事务隔离级。为了这样做,你需要有 SUPER 权限。使用 SESSION

关键词为当前连接所有将来执行的事务设置默认的事务隔离级。

你可以使用 --transaction-isolation=... 为 mysqld 设置默认的全局隔离级。查看章节 4.1.1 mysqld 命令行选项

MySQL中的大表和大事务

千万行数据,表数据巨大。

            1、慢查询的产生:很难在一定时间内过滤出所需要的数据。

            2、建立索引需要更长的时间。

Mysql版本5.5 建立索引会锁表

Mysql版本=5.5 谁让不会锁表,但会引起主从延迟。

            3、修改表结构需要长时间锁定表

            4、会造成长时间的主从延迟。

            5、影响正常的数据操作。

1、分库分表把一张大表分为多个小表

难点:

分表主键的选择

分表后跨分区数据 的查询和统计

2、大表的历史数据归档

               好处:

减少对前后端业务的影响。

               难点:

归档时间点的选择

如何进行归档操作。

运行时间比较长,操作的数据比较多的事务。

锁定太多的数据,造成大量的阻塞和锁超时。

        回滚时间比较长

执行时间比较长,容易造成主从延迟。

避免一次处理太多的数据。

移除不必要在事务中操作的select操作


当前标题:mysql长事务怎么 mysql长事务有什么影响
转载注明:http://mswzjz.cn/article/dosojic.html

其他资讯