临时表VS表变量--因地制宜,合理使用 - ShanksGao - 博客园

mikel阅读(1117)

来源: 临时表VS表变量–因地制宜,合理使用 – ShanksGao – 博客园

一直以来大家对临时表与表变量的孰优孰劣争论颇多,一些技术群里的朋友甚至认为表变量几乎一无是处,比如无统计信息,不支持事务等等.但事实并非如此.这里我就临时表与表变量做个对比,对于大多数人不理解或是有歧义的地方进行详细说明.
注:这里只讨论一般临时表,对全局临时表不做阐述.
生命周期
临时表:会话中,proc中,或使用显式drop
表变量:batch中
这里用简单的code说明表变量作用域
复制代码
DECLARE @t TABLE(i int) ----定义表变量@t

SELECT *FROM @t        -----访问OK

insert into @t select 1 -----插入数据OK

select * from  @t      -------访问OK
go                     -------结束批处理
select * from @t       -------不在作用域出错
复制代码
注意:虽然说sqlserver在定义表变量完成前不允许你使用定义的变量.但注意下面情况仍然可正常运行!

 


if 'a'='b'
begin
DECLARE @t TABLE(i int)
end
SELECT *FROM @t        -----仍然可以访问!

日志机制
临时表与表变量都会记录在tempdb中记录日志
不同的是临时表的活动日志在事务完成前是不能截断的.
这里应注意的是由于表变量不支持truncate,所以完全清空对象结果集时临时表有明显优势,而表变量只能delete
事务支持
临时表:支持
表变量:不支持
我们通过简单的实例加以说明
复制代码
create table #t (i int)
declare @t table(i int)
BEGIN TRAN ttt
insert into #t select 1
insert into @t select 1
SELECT * FROM #t  ------returns 1 rows
SELECT * FROM @t  ------returns 1 rows
ROLLBACK tran ttt
SELECT * FROM #t    -------no rows
SELECT * FROM @t    -------still 1 rows
drop table #t       ----no use drop @t in session
复制代码

 

锁机制(select)
临时表 会对相关对象加IS(意向共享)锁
表变量 会对相关对象加SCH-S(架构共享)锁(相当于加了nolock hint)
可以看出虽说锁的影响范围不同,但由于作用域都只是会话或是batch中,临时表的IS锁虽说兼容性不如表变量的SCH-S但绝大多数情况基本无影响.
感兴趣的朋友可以用TF1200测试
索引支持
临时表  支持
表变量  条件支持(仅SQL2014)
没错,在sql2014中你可以在创建表的同时创建索引 图1-1
注:在sql2014之前表变量只支持创建一个默认的唯一性约束
code
复制代码
DECLARE @t TABLE 
(
col1 int index inx_1 CLUSTERED, 
col2 int  index index_2 NONCLUSTERED,
       index index_3 NONCLUSTERED(col1,col2)
)

复制代码

图1-1

 

用户自定义函数(UDFs)
临时表 不支持作为UDF的结果集返回
表变量 支持作为UDF的结果集返回
注:当表变量作为UDF的结果集返回时分为TVF(Table-Valued Function),TVP(Table-Valued Parameters)两种类型,只有TVF支持plan cache
如图1-2
Code
复制代码
CREATE FUNCTION TVP_Customers (@cust nvarchar(10))
RETURNS TABLE
AS
 RETURN
 (SELECT RowNum, CustomerID, OrderDate, ShipCountry
 FROM BigOrders
 WHERE CustomerID = @cust);
GO
CREATE FUNCTION TVF_Customers (@cust nvarchar(10))
RETURNS @T TABLE (RowNum int, CustomerID nchar(10), OrderDate date,
 ShipCountry nvarchar(30))
AS
BEGIN
 INSERT INTO @T
  SELECT RowNum, CustomerID, OrderDate, ShipCountry
  FROM BigOrders
  WHERE CustomerID = @cust
  RETURN
END;

DBCC FREEPROCCACHE
GO
SELECT * FROM TVF_Customers('CENTC');
GO
SELECT * FROM TVP_Customers('CENTC');
GO
SELECT * FROM TVF_Customers('SAVEA');
GO
SELECT * FROM TVP_Customers('SAVEA');
GO

select b.text,a.execution_count,a.* from sys.dm_exec_query_stats a
cross apply sys.dm_exec_sql_text(a.sql_handle) b
where b.text like '%_Customers%'
复制代码

 

图1-2

 

其它方面
表变量不支持select into,alter,truncate,dbcc等
表变量不支持table hint 如(force seek)

 

执行计划预估
我想这里可能是引起使用何种方式争论比较突出的地方,由于表变量没有统计信息,无法添加索引等使得大家对其在执行计划中的性能表现嗤之以鼻,但实际情况呢?我们需要深入分析.
关于临时表的预估这里我就不做介绍了,主要对表变量的预估做详细阐述.
表变量在sql2000引入的一个原因就是为了在一些执行过程中减少重编译.以获得更好的性能.当然带来好处的同时也会带来一定弊端.由于其不涉及重编译,优化器其实并不知道表变量中的具体行数,此时他采取了保守的预估方式:预估行数为1行.如图2-1

Code

复制代码
declare @t table (i int)
select * from @t-----此时0行预估行数为1行
insert into @t select 1
select * from @t-----此时1行,预估行数仍为1行
insert into @t values (2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(14),(15),(16),(17),(18),(19),(20)
select * from @t ----此时19行,预估行数仍为1行

--....无论实际@t中有多少行,由于没有重编译,预估均为1行
复制代码

 

 

图2-1

所以当我们加上重编译的的操作,此时优化器就知道了表变量的具体行数.如图2-2

Code

 

复制代码
declare @t table (i int)
select * from @t option(recompile)-----此时0行预估行数为1行
insert into @t select 1
select * from @t  option(recompile)-----此时1行,预估行数为1行
insert into @t values (2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(14),(15),(16),(17),(18),(19),(20)
select * from @t  option(recompile)----此时19行,预估行数为19行
--....当加入重编译hint时,优化器就知道的表变量的行数.
复制代码

 

图2-2

 

至此,我们可以看到优化器知道了表变量中的行数.这样在表变量扫描的过程中,尤其针对数据量较大的情形,不会因为预估总是1而引起一些问题.
如果你刚知道这里的预估原理,现有的代码都加上重编译那工作量可想而知了..这里介绍一个新的跟踪标记,Trace Flag 2453.
TF2453可以一定程度上替代重编译Hint,但只是在非简单计划(trivial plans)的情形下
注:TF2453只在sql2012 SP2和SQL2014中的补丁中起作用

表变量谓词预估
由于表变量木有统计信息,在优化器知道整体行数的前提下将会根据谓词的情形
采用不同的规则"猜"来进行预估.
注:这里有些规则笔者未找到微软相应的算法文档,经过自己根据数据推算得出.
看到这里的朋友请为我点个赞J(很长时间推算得出.可能数学忘得差不多了)
注:由于检索对象本身及为变量,谓词为变量,或是常数无影响
常见谓词下预估算法:
a ">", "<" 运算符 按照表变量数据量的30%进行预估
b "like" 运算符 按照表变量数据量的10%进行预估
c "="  运算符 按照表变量数据量的0.75次方预估
实例如图2-3
code
复制代码
declare @i int
set @i=13
DECLARE @T TABLE(I INT);
INSERT INTO @T VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(14),(15),(16),(17),(18),(19),(20)
------表变量中存在个数字
select * from @T where I < 1  option(recompile) ------20*30% 预估数为6
select * from @T where I > @i option(recompile) --------20*30%预估数为6
select * from @T where I like @i  option(recompile) --------20*10% 预估数为2
select * from @T where I like 1  option(recompile)  --------20*10 预估数为2
select * from @T where I = @i  option(recompile) --------POWER(20.00000,0.75) 预估数为9.45742
select * from @T where I = 1  option(recompile)  --------POWER(20.00000,0.75) 预估数为9.45742

insert into @T
select DatabaseLogID from AdventureWorks2008R2.dbo.DatabaseLog------insert new records
select * from @T option(recompile) ------------此时数据为行
select * from @T where I = 1  option(recompile)--------------------POWER(1617.00000,0.75) 预估数为254.99550
复制代码

 

图2-3

可以看出根据不同的谓词优化器会采用不同的预估方式,虽然它不如统计信息下的密度,直方图等来的精确(尤其是等值预估,在数据量巨大的情形下,其效果可能接近统计信息),但在了解数据的前提下如果适合表变量我们还是可以大胆使用的.

Tempdb竞争
tempdb的竞争本身涵盖的知识面比较大,这里我们只讨论临时表与表变量的孰优孰劣.
通过前面的介绍我们知道临时表是支持事务的,而表变量时不支持的.正因如此很多人放弃了表变量的使用.但任何事情都有两方面,支持就一定好吗?由于临时表对事务的支持,在高并发的情形中可能正因为其事务的支持造成系统表锁,总而影响并发.

我们通过一个简单的实例来说明

日常管理中,我发现很多开发人员在使用临时表时采用select * into #t from …的语法,这样的写法如果数据量稍大,将会造成事务持有系统表锁的时间变长,从而影响并发,吞吐.我们通过一个简单的实例说明.如图3-1

 

Code 我们通过SQLquerystress模拟并发

复制代码
----SSMS测试数据
Use tempdb
create table t
( id int identity,str1 char(8000))----more pages for many records

insert into t select 'a'
go 100

----sqlquerystress
select * into #t
from t----57s

----sqlquerystress
declare @t table
( id int,str1 char(8000))
insert into @t
select * from t-----1s
复制代码

 

 

图3-1

 

通过图3-1可以看出上述情形中临时表简直不堪重负.临时表与表变量到底该如何应用不是看谁比谁的优点多,应视具体情形而定

结语:借用火影忍者中宇智波. 鼬的一句名言:”任何术都是有缺陷的” 同样,在数据库的世界里没有哪项技术是完美无缺的.根据实际的场景,情形,选择合理的实现方式才是我们的初衷.

在网页中在线浏览ppt文档 - 每天进步多一点 - 博客园

mikel阅读(1746)

来源: 在网页中在线浏览ppt文档 – 每天进步多一点 – 博客园

方法一:

把ppt文件的扩展名直接修改为pps,嵌入到网页中

缺点:这种方式浏览器会提示是打开,还是下载,选择打开的话会直接在浏览器中打开,并且客户端一定要安装Office PowerPoint才能打开

方法二:

把ppt文件在PowerPoint中另存为网页,保存类型为htm,可以直接在网页中打开

缺点:每一个ppt文档都需要在PowerPoint中另存为网页,因为需要转换格式,在特殊场景下可能不适用

方法三:

使用微软提供的ocx控件

下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyId=CE2CA4FD-2169-4FAC-82AF-770AA9B60D77

介绍地址:http://support.microsoft.com/default.aspx?scid=kb;en-us;311765

缺点:学习难度较大,需要修改浏览器权限,琢磨了许久,不得不放弃

方法四:

使用第三方软件,如SOAOffice、iweboffice、ntko等

没有做具体研究

方法五:

用PPT To Video Scout转换成avi,flv等影片格式

缺点:不能手动控制要跳转到哪个页面

方法六:

使用PowerPoint to Flash将ppt文件转换为flash文件,转换的flash用鼠标点击flash可以播放影片,并且可以通过选项设定在flash上添加前进或后退的按钮

 方法七:

将ppt转换为图片,但是对于ppt中存在视频的话,可能不适用,而且截图会存在像素的问题,所以播放图片会模糊。

我暂时采用了方法二的方式,查看了一下数字标牌的播放方式,找到了它存储的temp文件,发现为htm格式的网页,但是我用ppt转换为的htm与他存储的htm格式的图标不同,而且由ppt转换后的htm会存在大纲,通过下边的方法我将大纲去掉了,不知道和网页格式htm还会不会存在区别,暂定这种方式把!

去掉大纲的方法:

不显示大纲可以实现!当你将ppt文件保存为html文件时,它会自动生成一个文件夹,到里面找到frame.html,并用记事本打开它。你会看到有下面这段代码。其实只要改动两个地方就行了:第一去掉这句“ <frame src=outline.htm title=”大纲” name=PPTOtl>”。再将“<frameset cols=”25%,*” onload=”Load()” id=PPTHorizAdjust framespacing=1 frameborder=1>”中的cols=”25%”改为cols=”100%”。

第二把这句<frame src=outline.htm title=”大纲导航栏” name=PPTOtlNav scrolling=no noresize>去掉,再把<frameset cols=”25%,*” framespacing=1>
这句中的cols=”25%”改为cols=”100%”。

MYSQL limit用法 - 就是你baby - 博客园

mikel阅读(1033)

来源: MYSQL limit用法 – 就是你baby – 博客园

1、MySQL的limit用法

 

在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mySQL已经为我们提供了这样一个功能。

 

  1. SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset  
SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset

 

LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1): 为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。

 

  1. mysql> SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15   
  2. //为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
  3. mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.   
  4. //如果只给定一个参数,它表示返回最大的记录行数目:
  5. mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行   
  6. //换句话说,LIMIT n 等价于 LIMIT 0,n。
mysql> SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15

//为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1: 
mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.

//如果只给定一个参数,它表示返回最大的记录行数目: 
mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行

//换句话说,LIMIT n 等价于 LIMIT 0,n。

 

引用,路人乙:Mysql中limit的用法详解

 

2、Mysql的分页查询语句的性能分析

 

 

MySql分页sql语句,如果和MSSQL的TOP语法相比,那么MySQL的LIMIT语法要显得优雅了许多。使用它来分页是再自然不过的事情了。

 

2.1最基本的分页方式:

 

  1. SELECT … FROM … WHERE … ORDER BY … LIMIT …  
 
SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT ...

 

在中小数据量的情况下,这样的SQL足够用了,唯一需要注意的问题就是确保使用了索引:

举例来说,如果实际SQL类似下面语句,那么在category_id, id两列上建立复合索引比较好:

 

  1. SELECT * FROM articles WHERE category_id = 123 ORDER BY id LIMIT 50, 10  
SELECT * FROM articles WHERE category_id = 123 ORDER BY id LIMIT 50, 10

 

 

2.2子查询的分页方式:

 

随着数据量的增加,页数会越来越多,查看后几页的SQL就可能类似:

  1. SELECT * FROM articles WHERE category_id = 123 ORDER BY id LIMIT 10000, 10  
SELECT * FROM articles WHERE category_id = 123 ORDER BY id LIMIT 10000, 10

 

一言以蔽之,就是越往后分页,LIMIT语句的偏移量就会越大,速度也会明显变慢。

此时,我们可以通过子查询的方式来提高分页效率,大致如下:

  1. SELECT * FROM articles WHERE  id >=   
  2.  (SELECT id FROM articles  WHERE category_id = 123 ORDER BY id LIMIT 10000, 1) LIMIT 10  
SELECT * FROM articles WHERE  id >=
 (SELECT id FROM articles  WHERE category_id = 123 ORDER BY id LIMIT 10000, 1) LIMIT 10

 

 

2.3JOIN分页方式

 

  1. SELECT * FROM `content` AS t1    
  2. JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT “.($page-1)*$pagesize.”, 1) AS t2    
  3. WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;   
SELECT * FROM `content` AS t1 
JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) AS t2 
WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;

 

经过我的测试,join分页和子查询分页的效率基本在一个等级上,消耗的时间也基本一致。

explain SQL语句:

id select_type table type possible_keys key key_len ref rows Extra

1 PRIMARY <derived2> system NULL NULL NULL NULL 1

1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 6264 Using where

2 DERIVED content index NULL PRIMARY 4 NULL 27085 Using index

 

—————————————-

 

为什么会这样呢?因为子查询是在索引上完成的,而普通的查询时在数据文件上完成的,通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。

 

实际可以利用类似策略模式的方式去处理分页,比如判断如果是一百页以内,就使用最基本的分页方式,大于一百页,则使用子查询的分页方式。

【引用原文,energy1010的空间:MySql分页sql语句

 

 

3、Oracle分页查询语句

Oralce数据库

从数据库表中第M条记录开始检索N条记录

  1. SELECT * FROM (SELECT ROWNUM r,t1.* From 表名称 t1 where rownum < M + N) t2    
  2.  where t2.r >= M   
SELECT * FROM (SELECT ROWNUM r,t1.* From 表名称 t1 where rownum < M + N) t2 
 where t2.r >= M

例如从表Sys_option(主键为sys_id)中从第10条记录开始检索20条记录,语句如下:

  1. SELECT * FROM (SELECT ROWNUM R,t1.* From Sys_option where rownum < 30 ) t2    
  2. Where t2.R >= 10   
SELECT * FROM (SELECT ROWNUM R,t1.* From Sys_option where rownum < 30 ) t2 
Where t2.R >= 10 

 

3、MSSQLServer分页查询语句

 

SQL Server主要利用 SELECT TOP语句分页,具体方案,请参考

 

————————————-

 

分页方案一:(利用Not In和SELECT TOP分页)

语句形式:

 

  1. SELECT TOP 10 *    
  2. FROM TestTable    
  3. WHERE (ID NOT IN    
  4. (SELECT TOP 20 id    
  5. FROM TestTable    
  6. ORDER BY id))    
  7. ORDER BY ID   
SELECT TOP 10 * 
FROM TestTable 
WHERE (ID NOT IN 
(SELECT TOP 20 id 
FROM TestTable 
ORDER BY id)) 
ORDER BY ID

 

  1. SELECT TOP 页大小 *    
  2. FROM TestTable    
  3. WHERE (ID NOT IN    
  4. (SELECT TOP 页大小*页数 id    
  5. FROM 表    
  6. ORDER BY id))    
  7. ORDER BY ID    
  8. SELECT TOP 页大小 *   
SELECT TOP 页大小 * 
FROM TestTable 
WHERE (ID NOT IN 
(SELECT TOP 页大小*页数 id 
FROM 表 
ORDER BY id)) 
ORDER BY ID 
SELECT TOP 页大小 *
  1. FROM TestTable    
  2. WHERE (ID >    
  3. (SELECT MAX(id)    
  4. FROM (SELECT TOP 页大小*页数 id    
  5. FROM 表    
  6. ORDER BY id) AS T))    
  7. ORDER BY ID   
FROM TestTable 
WHERE (ID > 
(SELECT MAX(id) 
FROM (SELECT TOP 页大小*页数 id 
FROM 表 
ORDER BY id) AS T)) 
ORDER BY ID

 

————————————-

 

分页方案二:(利用ID大于多少和SELECT TOP分页)

语句形式:

  1. SELECT TOP 10 *    
  2. FROM TestTable    
  3. WHERE (ID >    
  4. (SELECT MAX(id)    
  5. FROM (SELECT TOP 20 id    
  6. FROM TestTable    
  7. ORDER BY id) AS T))    
  8. ORDER BY ID   
SELECT TOP 10 * 
FROM TestTable 
WHERE (ID > 
(SELECT MAX(id) 
FROM (SELECT TOP 20 id 
FROM TestTable 
ORDER BY id) AS T)) 
ORDER BY ID

 

————————————-

分页方案三:(利用SQL的游标存储过程分页)

 

  1. create procedure XiaoZhengGe    
  2. @sqlstr nvarchar(4000), –查询字符串    
  3. @currentpage int, –第N页    
  4. @pagesize int –每页行数    
  5. as    
  6. set nocount on    
  7. declare @P1 int, –P1是游标的id    
  8. @rowcount int    
  9. exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output    
  10. select ceiling(1.0*@rowcount/@pagesize) as 总页数–,@rowcount as 总行数,@currentpage as 当前页    
  11. set @currentpage=(@currentpage-1)*@pagesize+1    
  12. exec sp_cursorfetch @P1,16,@currentpage,@pagesize    
  13. exec sp_cursorclose @P1    
  14. set nocount off   
create procedure XiaoZhengGe 
@sqlstr nvarchar(4000), --查询字符串 
@currentpage int, --第N页 
@pagesize int --每页行数 
as 
set nocount on 
declare @P1 int, --P1是游标的id 
@rowcount int 
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output 
select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页 
set @currentpage=(@currentpage-1)*@pagesize+1 
exec sp_cursorfetch @P1,16,@currentpage,@pagesize 
exec sp_cursorclose @P1 
set nocount off

 

其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。

建议优化的时候,加上主键和索引,查询效率会提高。

 

通过SQL 查询分析器,显示比较:我的结论是:

分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句

分页方案一:(利用Not In和SELECT TOP分页) 效率次之,需要拼接SQL语句

分页方案三:(利用SQL的游标存储过程分页) 效率最差,但是最为通用

 

在实际情况中,要具体分析。

mysql select into的用法_zwldx的博客-CSDN博客

mikel阅读(1066)

来源: mysql select into的用法_zwldx的博客-CSDN博客

MySQL不支持Select Into语句直接备份表结构和数据,一些种方法可以代替,如下:

#MYSQL不支持:
Select * Into new_table_name from old_table_name; 这是sql server中的用法
#替代方法:
Create table new_table_name (Select * from old_table_name);

————————————————
版权声明:本文为CSDN博主「zwldx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zwldx/article/details/82227533

Lock wait timeout exceeded; try restarting transaction_萌神30号 ↝-CSDN博客

mikel阅读(906)

来源: Lock wait timeout exceeded; try restarting transaction_萌神30号 ↝-CSDN博客

目录

一、问题抛出

二、解决方案

三、三张表字段说明

innodb_trx

innodb_locks

innodb_lock_waits

四、终极方法

小结


一、问题抛出

在做查询语句时,MySQL 抛出了这样的异常:

  1. MySQL server error report:Array
  2. (
  3. [0] => Array
  4. (
  5. [message] => MySQL Query Error
  6. )
  7. [1] => Array
  8. (
  9. => SELECT * FROM taobao_trade WHERE order_status = 1 and orderID =‘2018061812306547’ AND is_tran_success=0 for update
  10. )
  11. [2] => Array
  12. (
  13. [error] => Lock wait timeout exceeded; try restarting transaction
  14. )
  15. [3] => Array
  16. (
  17. [errno] => 1205
  18. )
  19. )

Lock wait timeout exceeded; try restarting transaction的异常,错误提示的意思,很明显,是因为这条语句被锁住了,所以释放这个锁。

二、解决方案

我们可以通过到information_schema 中来进行查找被锁的语句。

解释: information_schema这张数据表保存了MySQL服务器所有数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。再简单点,这台MySQL服务器上,到底有哪些数据库、各个数据库有哪些表,每张表的字段类型是什么,各个数据库要什么权限才能访问,等等信息都保存在information_schema表里面。

我们可以用下面三张表来查原因:

  • innodb_trx 当前运行的所有事务
  • innodb_locks 当前出现的锁
  • innodb_lock_waits 锁等待的对应关系

如果数据库中有锁的话,我们可以使用这条语句来查看:

select * from information_schema.innodb_trx

clipboard.png

图中红色语句 LOCK WAIT为占用系统资源的语句,我们需要杀掉这个锁,执行 kill 线程id号。上面这条记录的id为199120823069, trx_mysql_thread_id 为 738178711, 所以我们执行:kill 738178711杀掉这个MySQL语句的线程即可。

执行之后:

  1. kill 738178711
  2. // 查询线程
  3. // SELECT * from information_schema.processlist WHERE id = 738178711;
  4. // show full processlist;

clipboard.png

其他的记录不需要关注,因为其他的记录状态为“RUNNING” 即正在执行的事务,并没有锁。

三、三张表字段说明

innodb_trx

desc information_schema.innodb_trx;

clipboard.png

innodb_locks

desc information_schema.innodb_locks;

clipboard.png

innodb_lock_waits

desc information_schema.innodb_lock_waits

clipboard.png

四、终极方法

如果以上方法杀掉线程,但还是不能解决,则我们就可以查找执行线程用时比较久的用户,然后直接干掉。

  1. SELECT * from information_schema.`PROCESSLIST` WHERE Time > 1000 AND USER = ‘wonguser’ ORDER BY TIME desc;
  2. kill 740097562

这样把所有耗时比较久的任务干掉,就可以解决这个问题了。

小结

关于我的那个问题,我通过这个方法 select * from information_schema.innodb_trx 已经杀掉了线程,但通过表直接修改那个id对应的数据,还是会弹出Lock wait timeout exceeded; try restarting transaction这样的异常,在网上找了许多未找出具体的解决方法,后来自己灵光一现,可以找出那些好事比较久的线程,然后把那些可疑的线程杀掉,没想到这个问题就解决了,可以正常对这行数据进行操作了。

[转]MySQL select into,SQLServer select into - 阿彬 - 博客园

mikel阅读(886)

来源: [转]MySQL select into,SQLServer select into – 阿彬 – 博客园

以下的文章主要介绍的是MySQL select into 与 SQLServer select  into,我们大家都知道MySQL数据库是对Select Into 语句的直接备份表的结构与相关实际应用数据是不支持的,由于工作中的需要在网上找到一种方法可以代替, 也有其它方法可以处理,总结如下:

方法1:

MYSQL不支持:

  1. Select * Into new_table_name from old_table_name

替代方法:

  1. Create table new_table_name (Select * from old_table_name);

方法2:

1.先备份表结构和数据

导出命令 -u用户名 -p密码 -h主机IP地址 数据库名 表名1 > 导出文件.sql

  1. mysqldump -uroot -proot -h192.168.0.88 ok_db oktable2 > ok_db.sql

2.修改备份表的名字

3.登录MySQL

4.选择数据库

5.执行: Source 备份表的路径 如:Source d:\ok_db.sql 回车即可。

6.完成.

SQLServer支持 MySQL Select into语句

1.备份表直接执行如下就可以了。

  1. Select * Into new_table_name from old_table_name;

MySQL Select into outfile用于导出指定的查询数据到文件如下:

1.导出表中所有数据到C盘根目录outfile.txt中如下:

  1. Select * into outfile ‘c:\\outfile.txt’ from test;

2.导出表中指定查询条件2005-06-08号的数据到C盘根目录outfile1.txt中如下:

  1. Select * into outfile ‘c:\\outfile.txt’ from test where beginDate=‘2008-06-08’;

mysql update from 子查询_ni_hao_ya的专栏-CSDN博客

mikel阅读(1116)

来源: mysql update from 子查询_ni_hao_ya的专栏-CSDN博客

这个破问题纠结了我好久,查了mySQL的好多资料,最后还是在别人那里得到结果,特此记录一下,留个备份吧!

msSQL 子查询更新

update log set uin= b.uin
from log a,logs b
where a.accountuin = b.accountuin

mySQL 不支持 update 子查询更新

找了半天资料 终于搞定了…

update `log` a inner join `logs` b on a.`accountuin` = b.`accountuin`
set a.`uin` = b.`uin` where a.`accountuin` = b.`accountuin`

这样就能 将查询出来的字段批量更新过去了…

tp 中save保存,数据没修改,保存失败的处理_一份耕耘 一份收货-CSDN博客

mikel阅读(670)

来源: tp 中save保存,数据没修改,保存失败的处理_一份耕耘 一份收货-CSDN博客

$model->save();
if($model->geterror!=”){//判断数据执行有错误;查看tp save流程
$this->error(‘修改失败’);
return false;
}
$model->geterror() 不为空的情况,就是数据保存失败情况,其中不包含数据未修改的情况;
—————————————————————————————-
亲测 ; $model->getError(); 如果SQL语句有问题,也不会报错的;
$model->getDbError(); 如果SQL语句有错误 ,会报错的;
save() 执行失败没有返回值;
执行成功: 有修改,返回1
没修改 ,返回0
参考:
$flag=$match->where(‘id=’.$id)->save($data);
//echo $match->getDbError();
if ($flag ||($flag === 0)){ //如果save执行错误返回空,==也是相等的;要===才能区别开来;
//$id=base64_encode($id);
$json->setErr(0,’添加完成’);//添加成功
$json->Send();
}else{
$json->setErr(10001,’添加失败’);
$json->Send();

————————————————
版权声明:本文为CSDN博主「qq_34242581」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34242581/article/details/52042505

Workerman ThinkPHP5 宝塔 安装Event拓展_九城科技-CSDN博客

mikel阅读(849)

来源: Workerman ThinkPHP5 宝塔 安装Event拓展_九城科技-CSDN博客

Workerman 结合 TP5在宝塔环境下安装Event拓展

操作系统是CentOS7

先用workerman官方给的检查环境的脚本进行检查

curl -Ss http://www.workerman.net/check.php | php

全部显示OK就代表满足workman的运行环境

宝塔默认是关掉了几个PHP的函数的

需要在PHP的配置文件里面去把workman需要用到的函数给注释掉

 

然后后续操作基本一把梭

代码如下

wget https://pecl.php.net/get/event-3.0.2.tgz

tar -zxvf event-3.0.2.tgz

cd event-3.0.2

phpize

./configure –with-php-config=/www/server/php/73/bin/php-config

make && make install

echo “extension=event.so” >> /www/server/php/73/etc/php.ini

service php-fpm-73 reload
需要注意的是/www/server/php/73 为实际PHP所存在的目录

最后启动workerman

php start.php start

这样就启动起来了
————————————————
版权声明:本文为CSDN博主「九城科技」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35422558/article/details/114822862