马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?开始注册
x
执行导出数据库:
3 Y3 A- T; y* A9 ~: t/ T. c, O4 ?mysqldump -u root -predh3 nova >/root/zhongnan-nova.sql . ?2 p# F6 I) T5 J+ X* v
mysqldump: Got error: 1033: "Incorrect information in file: './nova/agent_builds.frm'" when using LOCK TABLES
: R( U: S; u# J报错了:. Z$ u& W( f0 H! K
Got error: 1033: ) j7 G. Z9 Z# D. M1 Q
when using LOCK TABLES# S% \- p1 r p1 s2 H7 ^ W. j
解决方法授予用户锁表权限即可。 网上有人说使用 –skip-lock-tables,这个会影响数据的一致性(可能比丢数据还要遭糕),故不推荐使用这个方法。 –single-transaction 用于 Innodb 引擎的数据库 dump 时,可以不锁表。 mysql 锁表原理深入下去还有很多细节可以学习,可以参考 Ref 相关资料。 导数据库报上面错,添加参数--single-transaction . e/ M- s! |- F& Q% e5 l
[root@compute03 ~]# mysqldump -u root -predh3 nova --single-transaction >/root/zhongnan-nova.sql
! T* I! D# y( X8 H8 Pmysqldump: Couldn't execute 'show create table `agent_builds`': Incorrect information in file: './nova/agent_builds.frm' (1033)
8 ]1 o9 P7 F, i" F7 l' v
2 i: r4 |: y9 Z" l8 M0 |还是报错:: P! h: w3 V. v& f
登录到数据库中show ; ~: W1 p& L, g8 _. K
MariaDB [nova]> show create table `agent_builds` ;
/ [; G, L- N% WERROR 1033 (HY000): Incorrect information in file: './nova/agent_builds.frm'& ?" X9 J7 \' Q: c9 x4 z
查看数据结构:1 K; L% `2 `3 K3 I
MariaDB [nova]> desc agent_builds;
5 L( W, p3 g* q6 C/ K4 fERROR 1033 (HY000): Incorrect information in file: './nova/agent_builds.frm'
; h' s z( S$ e. q' r- `$ x8 y
( b- L: H- d: G. v# B$ |! Jroot@compute03 ~]# mysqldump -u root -predhat123 nova --single-transaction --skip-lock-tables >/root/zhongnan-nova.sql
" q# K* Q6 ^6 o0 E+ `6 J- {mysqldump: Couldn't execute 'show create table `agent_builds`': Incorrect information in file: './nova/agent_builds.frm' (1033)2 S4 m: D6 P/ {% c6 @* A. T3 h
" G6 @; f- T: G8 L; s9 k% s% h3 @0 l0 D# C( l# z9 X: A0 \
今天在备份一位客户的mysql数据库的时候,使用mysqldump命令备份,出现when using LOCK TABLES的提示。如果对mysql中的用户的权限进行过详细设置的话,会知道用户可以被分配LOCK TABLES和UNLOCK TABLES两个权限,使该用户在对该用户的表进行读写锁设定。
! k8 |6 O: `3 C. ^ 遇到该问题,解决方案如下:
% V" a8 q/ w& q# `8 d2 r" s1 e# S 在执行备份的时候,将命令中添加 --skip-lock-tables,即命令如下:
# ~/ W+ u* C6 _/ f mysqldump -u 用户名 -p 用户密码 --skip-lock-tables -R database > /root/database_1120.dmp) m8 D0 C9 {* y; j* ]- }! J$ K
- \6 {* C! j( Y8 l 下面是对事务表使用LOCK TABLES的说明:, z* O& l6 b* ~- }# H3 m" h
在尝试锁定表之前,LOCK TABLES不是事务安全型的,会隐含地提交所有活性事务。同时,开始一项事务(例如,使用START TRANSACTION),会隐含地执行UNLOCK TABLES
4 p& I, D* w9 J, T* P 对事务表(如InnoDB)使用LOCK TABLES的正确方法是,设置AUTOCOMMIT=0并且不能调用UNLOCK TABLES,直到您明确地提交事务为止。当您调用LOCK TABLES时,InnoDB会内部地取其自己的表锁定,MySQL取其自己的表锁定。InnoDB在下一个提交时释放其表锁定,但是,对于MySQL,要释放表锁定,您必须调用UNLOCK TABLES。您不应该让AUTOCOMMIT=1,因为那样的话,InnoDB会在调用LOCK TABLES之后立刻释放表锁定,并且很容易形成死锁定。注意,如果AUTOCOMMIT=1,我们根本不能获取InnoDB表锁定,这样就可以帮助旧的应用软件避免不必要的死锁定。
& M; v/ r5 e! o1 c ROLLBACK不会释放MySQL的非事务表锁定。+ L" |1 a1 t; x& Y, l! `
要使用LOCK TABLES,您必须拥有相关表的LOCK TABLES权限和SELECT权限。
2 o' ~. v; [. N P+ x 使用LOCK TABLES的主要原因是仿效事务,或在更新表时加快速度。这将在后面进行更详细的解释。/ N6 n+ i' k9 O/ o/ y1 e
如果一个线程获得对一个表地READ锁定,该线程(和所有其它线程)只能从该表中读取。如果一个线程获得对一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。其它的线程被阻止,直到锁定被释放时为止。, U4 [9 S- x# j! y3 f
READ LOCAL和READ之间的区别是,READ LOCAL允许在锁定被保持时,执行非冲突性INSERT语句(同时插入)。但是,如果您正打算在MySQL外面操作数据库文件,同时您保持锁定,则不能使用READ LOCAL。对于InnoDB表,READ LOCAL与READ相同。' L ~: ^0 w- {: h
当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。虽然使用LOCK TABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,在此情况下,您必须分别获得对每个别名的锁定。
- X& G' O. D6 I* v( J. W2 Smysql> LOCK TABLE t WRITE, t AS t1 WRITE;
( @; R. A. x$ P" k/ z- [% y2 f
2 n: D* s5 u: p1 rmysql> INSERT INTO t SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLES1 Z4 J& s1 b) J9 B. k; D m$ D
+ g3 ^; r b% t+ r: j/ V! d- V5 N
mysql> INSERT INTO t SELECT * FROM t AS t1; 如果您的查询使用一个别名引用一个表,那么您必须使用同样的别名锁定该表。如果没有指定别名,则不会锁定该表。
* k7 f2 J7 _: N6 j1 omysql> LOCK TABLE t READ;
/ e! v$ X* K' u p: A7 w7 F! ~1 k) C# ^8 L
mysql> SELECT * FROM t AS myalias;ERROR 1100: Table 'myalias' was not locked with LOCK TABLES相反的,如果您使用一个别名锁定一个表,您必须使用该别名在您的查询中引用该表。! v6 L. j& E$ |4 l
mysql> LOCK TABLE t AS myalias READ;9 D) Y& x- R/ ]: O) ^1 M! E
4 l1 h `8 K; ]8 a9 `
mysql> SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLES
( E, _7 R5 e! l2 E( p% N* a4 Q2 t! o0 C) } L
mysql> SELECT * FROM t AS myalias;6 X% D% o# P; S( @
WRITE锁定通常比READ锁定拥有更高的优先权,以确保更新被尽快地处理。这意味着,如果一个线程获得了一个READ锁定,则另一个线程会申请一个WRITE锁定,后续的READ锁定申请会等待,直到WRITE线程获得锁定并释放锁定。您可以使用LOW_PRIORITY WRITE锁定来允许其它线程在该线程正在等待WRITE锁定时获得READ锁定。只有当您确定最终将有一个时机,此时没有线程拥有READ锁定时,您才应该使用LOW_PRIORITY WRITE锁定。
' N1 J/ w) N6 q+ J8 s( u% cLOCK TABLES按照如下方式执行:, D; R" I% \' B& P( G
1. 按照内部定义的顺序,对所有要被锁定的表进行分类。从用户的角度,此顺序是未经定义的。, B1 P& R; O. T/ X
2. 如果使用一个读取和一个写入锁定对一个表进行锁定,则把写入锁定放在读取锁定之前。9 H' b3 ?& ~8 V' z7 v. g2 K
3. 一次锁定一个表,直到线程得到所有锁定为止。3 O$ r' m9 O7 @( e8 ~' w5 h
该规则确保表锁定不会出现死锁定。但是,对于该规则,您需要注意其它的事情:
& @1 \1 O; o3 r9 J2 }" X) g6 A如果您正在对一个表使用一个LOW_PRIORITY WRITE锁定,这只意味着,MySQL等待特定的锁定,直到没有申请READ锁定的线程时为止。当线程已经获得WRITE锁定,并正在等待得到锁定表清单中的用于下一个表的锁定时,所有其它线程会等待WRITE锁定被释放。如果这成为对于应用程序的严重的问题,则您应该考虑把部分表转化为事务安全型表。
% I( z2 O+ b3 a6 {: z6 E B您可以安全地使用KILL来结束一个正在等待表锁定的线程。
+ {6 X! Z) C L, O/ d注意,您不能使用INSERT DELAYED锁定任何您正在使用的表,因为,在这种情况下,INSERT由另一个线程执行。/ ^+ g% }2 l+ p- N
通常,您不需要锁定表,因为所有的单个UPDATE语句都是原子性的;没有其它的线程可以干扰任何其它当前正在执行的SQL语句。但是,在几种情况下,锁定表会有好处:
" g8 q- p) Q& B/ {7 {" B 如果您正在对一组MyISAM表运行许多操作,锁定您正在使用的表,可以快很多。锁定MyISAM表可以加快插入、更新或删除的速度。不利方面是,没有线程可以更新一个用READ锁定的表(包括保持锁定的表),也没有线程可以访问用WRITE锁定的表(除了保持锁定的表以外)。
( n& b/ i2 P" h) N2 h有些MyISAM操作在LOCK TABLES之下更快的原因是,MySQL不会清空用于已锁定表的关键缓存,直到UNLOCK TABLE被调用为止。通常,关键缓存在每个SQL语句之后被清空。) H# U/ G( U9 D% `. Z9 A
如果您正在使用MySQL中的一个不支持事务的存储引擎,则如果您想要确定在SELECT和UPDATE之间没有其它线程,您必须使用LOCK TABLES。本处所示的例子要求LOCK TABLES,以便安全地执行:7 y1 E, R& \; I' G$ q& l
mysql> LOCK TABLES trans READ, customer WRITE;·
% `, @" i3 h* J3 o; h7 m" Q6 Y; @) E# ]) L- Z0 e7 l
mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;·
2 [. h# n9 B [6 z7 _3 W! m! {+ ~! r/ p( v. ]0 N
mysql> UPDATE customer· 9 b, i& o6 u" q) V
-> SET total_value=sum_from_previous_statement·
- G7 d2 b7 }# ]5 ] -> WHERE customer_id=some_id;· 3 k* W' p9 |; `8 Q
/ w/ ]3 i: j' ?1 B4 |- mmysql> UNLOCK TABLES;如果没有LOCK TABLES,有可能另一个线程会在执行SELECT和UPDATE语句之间在trans表中插入一个新行。
$ T Y. v7 x* g% Z通过使用相对更新(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函数,您可以在许多情况下避免使用LOCK TABLES。" s+ {. p& G- X
通过使用用户层级的顾问式锁定函数GET_LOCK()和RELEASE_LOCK(),您也可以在有些情况下避免锁定表。这些锁定被保存在服务器中的一个混编表中,使用pthread_mutex_lock() 和pthread_mutex_unlock(),以加快速度。
n- T0 f1 H6 O% [- t要了解更多有关锁定规则的说明
, \* b e0 t2 v* |5 O您可以使用FLUSH TABLES WITH READ LOCK语句锁定位于所有带有读取锁定的数据库中的所有表。如果您有一个可以及时拍摄快照的文件系统,比如Veritas,这是获得备份的一个非常方便的方式。: h, d7 ]/ I6 x' ~
注释:如果您对一个已锁定的表使用ALTER TABLE,该表可能会解锁。# k9 I( ?; q7 H1 f
3 h7 ` c+ q4 |6 Y) x: S2 k% a
1 v' f7 j! M# L: ]
+ r! f/ ~+ i. N7 l7 d- P
在一个网站上看到一个解决方法:
7 b7 h+ F& y1 w% U4 L1.创建一个暂存鱼眼/坩埚服务器
" X4 ]# t; ?2 F2.连接到另一个MySQL数据库服务器
! I' H; |+ x. c3 H4 M. U' A) Y3.从新数据库中,复制相同的 .frm 文件以替换生产服务器中有问题的 .frm 文件- g9 r _8 w3 u! e N+ B" @
4.重启Fisheye/Crucible生产服务器
" f P- S' g/ v- w% M& O# A: ^% K& M
( a9 Z8 O; k" `, K& o |