对一个DROP MV 语句长时间无返回的处理步骤。


接到客户电话说一个drop mview语句 花了4个小时没有结果。
客户说建立一个MV但觉得不对想删除但删除语句一直无返回。

我按如下步骤对库进行检查。


SQL> set head off
SQL> select sid,OPNAME,sofar,TOTALWORK,trunc(sofar/totalwork*100,2)||'%' as perwork,elapsed_seconds,message
2 from v$session_longops where sofar!=totalwork;


57
Rowid Range Scan
453033 934531
48.47%
446
Rowid Range Scan: SGREPORTS.SUMMARY: 453033 out of 934531 Blocks done

26
Table Scan
8829 57660
15.31%
36
Table Scan: CNSADMIN.CNSRPT_AUDIT: 8829 out of 57660 Blocks done


15
SYS_EXPORT_FULL_41
21238 47705
44.51%
18308
SYS_EXPORT_FULL_41: EXPORT : 21238 out of 47705 MB done

46
Rowid Range Scan
9288 66726
13.91%
91

Rowid Range Scan: REPORTER.REPORTER_STATUS_MV: 9288 out of 66726 Blocks done

109
Rowid Range Scan
8068 94717
8.51%
16
Rowid Range Scan: REPORTER.REPORTER_STATUS_MV: 8068 out of 94717 Blocks done

36
Sort Output
72807 74632
97.55%

1488
Sort Output: : 72807 out of 74632 Blocks done


已选择6行。

没发现DROP MV语句。

SQL> select * from dba_blockers;

221


SQL> select sql_address from v$session where sid =221

SQL_ADDRESS
----------------
00

表示没有事务在运行。但有可能保有锁。

SQL>
SQL> SELECT
2 a.session_id, username,type,mode_held,mode_requested,
3 lock_id1,lock_id2
4 FROM
5 sys.v_$session b,
6 sys.dba_blockers c,
7 sys.dba_lock a
8 WHERE
9 c.holding_session=a.session_id AND
10 c.holding_session=b.sid
11 /

221 REPORTER
USER
Exclusive
None
0
1264

221 REPORTER
USER
Exclusive
None
44178
0


221 REPORTER
USER
Row-X (SX)
None
212
0

221 REPORTER
USER
Exclusive
None
65537

173202


果然在221语句上有锁。

分析:一定是客户在建立MV时设定了刷新,所以对应的JOB启动。但没等待JOB刷新结束,客户又启动了DROP MV.
SQL> set head on
SQL>
select * from dba_jobs_running;

SID JOB FAILURES LAST_DATE
---------- ---------- ---------- --------------
LAST_SEC THIS_DATE
------------------------------------------------ --------------
THIS_SEC INSTANCE
------------------------------------------------ ----------
36 305 0 04-10月-08
07:24:46 05-10月-08
07:24:50 0

221 1264     -----这个就是那个造成DROP MV BLOCK的JOB。



SID JOB FAILURES LAST_DATE
---------- ---------- ---------- --------------
LAST_SEC THIS_DATE
------------------------------------------------ --------------
THIS_SEC INSTANCE
------------------------------------------------ ----------


SQL> select * from dba_jobs where job=1264;

未选定行



SQL> select s.sid,s.serial#,s.username,s.status,p.spid
2 from v$session s, v$process p
3 where s.sid in (221) and s.paddr = p.addr;

SID SERIAL#
---------- ----------
USERNAME STATUS
------------------------------------------------------------ ----------------
SPID
------------------------
221 27367
REPORTER ACTIVE
23087

果然有一个JOB HANG到这了。
alter system kill session '221,27367';
from OS:
kill -9 23087
一切OK了。
<think>我们正在讨论的是GBase数据库。根据引用[2]的内容,GBase数据库修改字段的varchar长度有两种方法: 方法1:重建新表并导入数据(适合大表或结构变动较大时) 方法2:使用四步骤(适合增加字段长度的情况): 步骤1:添加一个新字段(临时字段)到表中,位于原字段之后 步骤2:将原字段的值更新到临时字段 步骤3:删除原字段 步骤4:将临时字段重命名为原字段名,并设置正确的数据类型和约束 但是,引用[1]中提到了一个更简单的语句:`alter table tablename modify ff varchar(30);`,这看起来像是直接修改字段长度的语句。 需要注意的是,引用[1]和引用[2]之间似乎有矛盾。我们需要判断哪个适用于GBase。 根据引用[1]的标题是“添加表字段”,其中提到了修改表字段长度使用`modify`,但是引用[2]明确指出在GBase中修改字段长度有两个“蠢办法”,并给出了四步骤方法,说明直接使用`modify`可能不可行。 由于用户明确要求GBase数据库,我们应该以引用[2]为准,因为引用[2]明确针对GBase。同时,我们也可以参考引用[3]来查询表结构。 因此,在GBase数据库中,直接修改字段长度的`MODIFY`语句可能不被支持,或者有风险。所以推荐使用引用[2]的四步骤方法。 但是,为了验证,我们可以考虑:不同版本的GBase可能支持不同的语法。我们也可以尝试查看官方文档,但当前没有官方文档引用。 因此,我们给出两种方案: 方案一(如果支持直接修改):尝试使用`ALTER TABLE ... MODIFY COLUMN`(但引用[2]暗示可能不支持,所以不推荐) 方案二(安全通用):使用四步骤方法。 由于用户的需求是修改字段长度,我们按照引用[2]提供的方法。 具体步骤(以将表`mytable`的字段`mycolumn`的长度从原长度增加到50为例): 1. 添加一个新列(比如`mycolumn_temp`),类型为`VARCHAR(50)`,放在原字段后面(或者指定位置,一般放在原字段后)。 2. 将原字段的值更新到新字段。 3. 删除原字段。 4. 将新字段重命名为原字段名。 注意:如果字段有约束(如非空、默认值等),需要在添加新字段时加上,并在重命名后确保约束正确。 详细SQL语句: 假设表名为`mytable`,原字段名为`mycolumn`,要修改为`VARCHAR(50)`,且原字段有非空约束。 步骤1:添加新字段(注意非空约束,如果原字段允许空,这里可以不加非空,但为了数据一致性,我们建议按照原字段的约束来添加) ```sql ALTER TABLE mytable ADD COLUMN mycolumn_temp VARCHAR(50) NOT NULL COMMENT '临时字段' AFTER mycolumn; ``` 注意:`AFTER mycolumn`表示将新字段加在原字段后面,这样在删除原字段后,新字段的位置可能还需要调整?但一般不影响。如果不需要指定位置,可以省略。 步骤2:将原字段的值更新到新字段 ```sql UPDATE mytable SET mycolumn_temp = mycolumn; ``` 注意:如果数据量大,这个操作可能会很慢,而且会锁表,需要在业务低峰期操作。 步骤3:删除原字段 ```sql ALTER TABLE mytable DROP COLUMN mycolumn; ``` 步骤4:将新字段重命名为原字段名 ```sql ALTER TABLE mytable CHANGE COLUMN mycolumn_temp mycolumn VARCHAR(50) NOT NULL COMMENT '字段注释'; ``` 注意:在重命名时,我们需要重新指定类型和约束,以及注释(如果有的话)。 但是,引用[2]的步骤中,在最后一步使用了`CHANGE COLUMN`并重新指定了类型和约束。这样做的目的是确保字段的定义正确。 另外,如果原字段有索引、外键等约束,那么上述步骤会更复杂,需要先删除约束,修改后再重新加上。这里我们假设没有这些约束。 因此,针对GBase数据库修改表字段长度的标准方法是使用四步骤法。 同时,我们也可以参考引用[1]中提到的直接修改的方法,但在GBase中可能不适用,所以不推荐。 总结回答: 在GBase数据库中,修改表字段长度的推荐方法是使用四步骤操作(添加新字段->更新数据->删除原字段->重命名新字段)。以下是具体的SQL语句示例: ### GBase修改表字段长度的SQL操作步骤 1. **添加临时字段** 在表`your_table`中添加一个与原字段同类型的临时字段,指定新长度(注意位置和约束): ```sql ALTER TABLE your_table ADD COLUMN temp_column VARCHAR(新长度) [约束] COMMENT '临时字段' AFTER original_column; ``` 2. **迁移数据** 将原字段数据复制到临时字段: ```sql UPDATE your_table SET temp_column = original_column; ``` 3. **删除原字段** 移除不再需要的原字段: ```sql ALTER TABLE your_table DROP COLUMN original_column; ``` 4. **重命名临时字段** 将临时字段重命名为原字段名: ```sql ALTER TABLE your_table CHANGE COLUMN temp_column original_column VARCHAR(新长度) [约束] COMMENT '字段注释'; ``` **注意事项**: - **减少长度风险**:若缩小字段长度,需确保现有数据长度不超过新长度,否则步骤2会失败[^2] - **约束处理**:若字段有默认值、索引或外键约束,需在操作前后额外处理(先删除约束再重建) - **锁表问题**:大表操作建议在业务低峰期进行 - **事务备份**:生产环境操作前务必备份数据 ### 相关查询(引用[3]) 查询表字段信息(用于确认当前结构): ```sql SELECT * FROM syscolumnsext col WHERE col.tabid = (SELECT tabid FROM systables WHERE UPPER(tabname) = UPPER('your_table')); ``` §§ 相关问题 §§ 1. 如何在GBase中安全修改带主键的字段长度? 2. 修改字段长度时如何保留原有默认值? 3. GBase数据库修改字段长度有哪些限制? 4. 如何验证GBase表字段修改后的结构? 5. 大表字段修改如何避免长时间锁表? 注意:在回答中,我们引用了引用[2]和引用[3],所以在末尾添加了引用标识。 </think>### GBase数据库修改表字段长度的SQL语句 在GBase数据库中,**直接修改字段长度存在限制**(如减少长度可能导致数据截断),需通过四步操作实现安全修改。以下是完整操作流程: --- #### **安全修改步骤**(以表`mytable`的字段`mycolumn`长度从20改为50为例): ```sql -- 1. 添加临时字段(长度需≥原字段) ALTER TABLE mytable ADD COLUMN temp_column VARCHAR(50) NOT NULL COMMENT '临时字段' AFTER mycolumn; -- 指定字段位置 -- 2. 复制原字段数据到临时字段 UPDATE mytable SET temp_column = mycolumn; -- 3. 删除原字段 ALTER TABLE mytable DROP COLUMN mycolumn; -- 4. 重命名临时字段为原字段名 ALTER TABLE mytable CHANGE COLUMN temp_column mycolumn VARCHAR(50) NOT NULL COMMENT '字段注释'; ``` --- ### ️ 关键注意事项 1. **字段约束处理** - 若原字段有`NOT NULL`或默认值,需在`ADD COLUMN`和`CHANGE COLUMN`中显式声明 - 示例:添加默认值约束 ```sql ALTER TABLE mytable CHANGE COLUMN temp_column mycolumn VARCHAR(50) DEFAULT 'default_value' NOT NULL; ``` 2. **长度缩小风险** - 当**减小字段长度**时,需先验证数据兼容性: ```sql SELECT MAX(LENGTH(mycolumn)) FROM mytable; -- 确认最大数据长度 ``` - 若新长度 < 现有数据长度,需先清理数据再操作 3. **索引/外键处理** 若字段涉及索引或外键,需先删除约束: ```sql -- 查询索引名 SELECT indexname FROM sysindexes WHERE tabid = ( SELECT tabid FROM systables WHERE tabname = 'mytable' ); -- 删除索引 DROP INDEX indexname; -- 完成字段修改后重建索引 CREATE INDEX indexname ON mytable(mycolumn); ``` 4. **大表优化建议** - 分批更新数据避免长事务: ```sql UPDATE mytable SET temp_column = mycolumn WHERE id BETWEEN 1 AND 10000; ``` - 使用`pt-online-schema-change`等在线DDL工具(需安装) --- ### 验证修改结果 ```sql -- 查询字段信息 SELECT colname, collength FROM syscolumnsext WHERE tabid = ( SELECT tabid FROM systables WHERE tabname = 'mytable' ); ``` 输出示例: ``` colname | collength ----------|---------- mycolumn | 50 -- 确认新长度生效 ``` --- ### 📌 替代方案(仅长度增加时可用) 若**只增大字段长度**且确认无数据冲突,可尝试直接修改(非所有版本支持): ```sql ALTER TABLE mytable MODIFY COLUMN mycolumn VARCHAR(50); ``` > ⚠️ 此操作可能在部分GBase版本报错,生产环境推荐四步法[^2] --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值