Postgresql 如何选择正确的关闭模式

停止数据库的命令:

pg_ctl stop -D $PGDATA [-m shutdown-mode]

shutdown-mode有如下几种模式:

1. smart: 等所有的连接中止后,关闭数据库。如果客户端连接不终止, 则无法关闭数据库。

开启一个空会话:

[root@localhost ~]# su - postgres
[postgres@localhost ~]$ psql
psql (9.4.4)
Type "help" for help.

postgres=#

用smart关闭数据库:

[postgres@localhost ~]$ pg_ctl stop -D $PGDATA -m smart
waiting for server to shut down............................................................... failed
pg_ctl: server does not shut down
HINT: The "-m fast" option immediately disconnects sessions rather than
waiting for session-initiated disconnection

2. fast: 快速关闭数据库, 断开客户端的连接,让已有的事务回滚,然后正常关闭数据库。

[postgres@localhost ~]$ pg_ctl stop -D $PGDATA -m fast
waiting for server to shut down.... done
server stopped

查看关闭日志:

LOG: received fast shutdown request
LOG: aborting any active transactions
FATAL: terminating connection due to administrator command
LOG: shutting down
LOG: database system is shut down

会话被强制中断,然后关闭数据库。

起一个事务,然后测试关闭:

postgres=# create table t(id int primary key, name varchar(9));
CREATE TABLE
postgres=# begin;
BEGIN
postgres=# insert into t values(1,'a')
postgres-# ;
INSERT 0 1

不提交, 然后用FAST MODE去关闭数据库:

[postgres@localhost ~]$ pg_ctl stop -D $PGDATA -m fast
waiting for server to shut down.... done
server stopped

查看日志:

LOG: received fast shutdown request
LOG: aborting any active transactions
LOG: autovacuum launcher shutting down
FATAL: terminating connection due to administrator command
LOG: shutting down
LOG: database system is shut down

同样是直接中断会话, 而不去管事务有没有提交。

postgres=# select * from t;
id | name
----+------
(0 rows)

没有提交的数据, 在重启之后并不能查到。

3. immediate: 立即关闭数据库,立即停止数据库进程,直接退出,下次启动时会进行实例恢复。

postgres=# insert into t values(1,'a')
;
INSERT 0 1
postgres=# select * from t;
id | name
----+------
1 | a
(1 row)

关闭数据库:

[postgres@localhost ~]$ pg_ctl stop -D $PGDATA -m immediate
waiting for server to shut down.... done
server stopped

查看日志:

LOG: received immediate shutdown request
WARNING: terminating connection because of crash of another server process
DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT: In a moment you should be able to reconnect to the database and repeat your command.
WARNING: terminating connection because of crash of another server process
DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT: In a moment you should be able to reconnect to the database and repeat your command.

启动数据库:

[postgres@localhost ~]$ pg_ctl -D /apps/pgsql/pgdata -l 1.log start
server starting

查看日志:

LOG: database system was interrupted; last known up at 2017-04-27 18:56:47 PDT
LOG: database system was not properly shut down; automatic recovery in progress #提示非正常关机,自动开启恢复。
LOG: redo starts at 0/181F910
LOG: record with zero length at 0/181FA90
LOG: redo done at 0/181FA60
LOG: last completed transaction was at log time 2017-04-27 18:59:13.727213-07
LOG: MultiXact member wraparound protections are now enabled
LOG: autovacuum launcher started
LOG: database system is ready to accept connections

查看数据:

[postgres@localhost ~]$ psql
psql (9.4.4)
Type "help" for help.

postgres=# select * from t;
id | name
----+------
1 | a
(1 row)

提交的数据已通过实例恢复。

小结:

对比以上三种关库模式:

smart最为安全,但最慢, 需要将所有连接都断开后,才会关库,默认关库模式。

fast强制中断会话,而不管有操作有没有提交,在做系统维护(系统维护时一般应用都正常关闭了,或者不再会有事务操作。)时,需要这种模式来关闭数据库。

immediate最暴力的方式,不管数据有没有落盘(POSGRE是遵循WAL机制),就直接关掉, 待启动时进行实例恢复, 如果在关库前有大量的事务没有写入磁盘, 那这个恢复过程可能会非常的漫长。

补充:postgresql 异步 stream replication 环境关闭 master 的验证

os: ubuntu 16.04

db: postgresql 9.6.8

验证在异步 stream replication环境下,主动关闭master时,数据是否有丢失,能丢失多少。

版本

# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.5 LTS
Release: 16.04
Codename: xenial
# su - postgres -c "psql -c \"select version();\""
                 version
----------------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 9.6.8 on x86_64-pc-linux-gnu (Ubuntu 9.6.8-1.pgdg16.04+1), compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609, 64-bit
(1 row)

用 pgbench 模拟数据库的大量数据操作

postgres=# create database pgbenchdb;
# su - postgres
$ pgbench -i -s 20 pgbenchdb
$ pgbench -r -j2 -c4 -T300 pgbenchdb

关闭 master

# su - postgres
$ /usr/lib/postgresql/9.6/bin/pg_ctl stop -m fast -D "/data/pg9.6/main"

提升 slave

# su - postgres
$ /usr/lib/postgresql/9.6/bin/pg_ctl promote -D "/data/pg9.6/main"

查看 old master 的 xlog location

$ /usr/lib/postgresql/9.6/bin/pg_xlogdump 000000010000000000000016
rmgr: XLOG  len (rec/tot): 106/ 106, tx:   0, lsn: 0/16000028, prev 0/152C9A10, desc: CHECKPOINT_SHUTDOWN redo 0/16000028; tli 1; prev tli 1; fpw true; xid 0:118746; oid 16432; multi 1; offset 0; oldest xid 543 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 550/118745; oldest running xid 0; shutdown
pg_xlogdump: FATAL: error in WAL record at 0/16000028: invalid record length at 0/16000098: wanted 24, got 0

可以看到 lsn: 0/16000028, prev 0/152C9A10, desc: CHECKPOINT_SHUTDOWN redo 0/16000028;

查看 new master 的 .history文件

$ ls -lt|more
total 360456
-rw------- 1 postgres postgres 16777216 Nov 30 10:32 000000020000000000000016
drwx------ 2 postgres postgres  4096 Nov 30 10:16 archive_status
-rw------- 1 postgres postgres  42 Nov 30 10:16 00000002.history
-rw------- 1 postgres postgres 16777216 Nov 30 10:16 000000010000000000000016.partial
-rw------- 1 postgres postgres 16777216 Nov 30 10:16 000000010000000000000015
-rw------- 1 postgres postgres 16777216 Nov 30 10:16 000000010000000000000014
-rw------- 1 postgres postgres 16777216 Nov 30 10:05 000000010000000000000013
$ cat 00000002.history
1 0/16000098 no recovery target specified
$ /usr/lib/postgresql/9.6/bin/pg_xlogdump 000000010000000000000016
rmgr: XLOG  len (rec/tot): 106/ 106, tx:   0, lsn: 0/16000028, prev 0/152C9A10, desc: CHECKPOINT_SHUTDOWN redo 0/16000028; tli 1; prev tli 1; fpw true; xid 0:118746; oid 16432; multi 1; offset 0; oldest xid 543 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 550/118745; oldest running xid 0; shutdown
rmgr: XLOG  len (rec/tot):  42/ 42, tx:   0, lsn: 0/16000098, prev 0/16000028, desc: END_OF_RECOVERY tli 2; prev tli 1; time 2018-11-30 10:16:57.249408 CST
rmgr: Standby  len (rec/tot):  50/ 50, tx:   0, lsn: 0/160000C8, prev 0/16000098, desc: RUNNING_XACTS nextXid 118746 latestCompletedXid 118745 oldestRunningXid 118746
rmgr: XLOG  len (rec/tot):  51/ 312, tx:   0, lsn: 0/16000100, prev 0/160000C8, desc: FPI_FOR_HINT , blkref #0: rel 1664/0/1260 blk 0 FPW
rmgr: Standby  len (rec/tot):  50/ 50, tx:   0, lsn: 0/16000238, prev 0/16000100, desc: RUNNING_XACTS nextXid 118746 latestCompletedXid 118745 oldestRunningXid 118746
pg_xlogdump: FATAL: error in WAL record at 0/16000238: invalid record length at 0/16000270: wanted 24, got 0

可以看到关键记录

lsn: 0/16000028, prev 0/152C9A10, desc: CHECKPOINT_SHUTDOWN redo 0/16000028
lsn: 0/16000098, prev 0/16000028, desc: END_OF_RECOVERY

而 END_OF_RECOVERY 对应的 lsn 为 0/16000098,和 00000002.history 时间线文件的内容完全一致。

所以在异步 stream replication 环境下,主动关闭master时,会将最后一条记录(CHECKPOINT_SHUTDOWN)发送给slave,不会造成数据的丢失。

而 synchronous_commit = on 保证事务有两份持久化的落盘数据。

分析 pg_log 日志

old master 上的最后几条日志

2018-11-30 10:16:40.986 CST,"postgres","pgbenchdb",7559,"[local]",5c009d79.1d87,4,"UPDATE waiting",2018-11-30 10:16:25 CST,,0,LOG,00000,"disconnection: session time: 0:00:15.723 user=postgres database=pgbenchdb host=[local]",,,,,,,,,"pgbench"
2018-11-30 10:16:40.993 CST,"postgres","pgbenchdb",7558,"[local]",5c009d79.1d86,3,"idle",2018-11-30 10:16:25 CST,4/0,0,FATAL,57P01,"terminating connection due to administrator command",,,,,,,,,"pgbench"
2018-11-30 10:16:40.994 CST,"postgres","pgbenchdb",7560,"[local]",5c009d79.1d88,3,"idle",2018-11-30 10:16:25 CST,5/0,0,FATAL,57P01,"terminating connection due to administrator command",,,,,,,,,"pgbench"
2018-11-30 10:16:40.994 CST,"postgres","pgbenchdb",7558,"[local]",5c009d79.1d86,4,"idle",2018-11-30 10:16:25 CST,,0,LOG,00000,"disconnection: session time: 0:00:15.729 user=postgres database=pgbenchdb host=[local]",,,,,,,,,"pgbench"
2018-11-30 10:16:40.994 CST,"postgres","pgbenchdb",7560,"[local]",5c009d79.1d88,4,"idle",2018-11-30 10:16:25 CST,,0,LOG,00000,"disconnection: session time: 0:00:15.725 user=postgres database=pgbenchdb host=[local]",,,,,,,,,"pgbench"
2018-11-30 10:16:40.999 CST,"postgres","pgbenchdb",7561,"[local]",5c009d79.1d89,3,"idle",2018-11-30 10:16:25 CST,6/0,0,FATAL,57P01,"terminating connection due to administrator command",,,,,,,,,"pgbench"
2018-11-30 10:16:41.001 CST,"postgres","pgbenchdb",7561,"[local]",5c009d79.1d89,4,"idle",2018-11-30 10:16:25 CST,,0,LOG,00000,"disconnection: session time: 0:00:15.731 user=postgres database=pgbenchdb host=[local]",,,,,,,,,"pgbench"
2018-11-30 10:16:41.010 CST,,,7156,,5c009735.1bf4,7,,2018-11-30 09:49:41 CST,,0,LOG,00000,"shutting down",,,,,,,,,""
2018-11-30 10:16:41.209 CST,,,7156,,5c009735.1bf4,8,,2018-11-30 09:49:41 CST,,0,LOG,00000,"checkpoint starting: shutdown immediate",,,,,,,,,""
2018-11-30 10:16:47.623 CST,,,7156,,5c009735.1bf4,9,,2018-11-30 09:49:41 CST,,0,LOG,00000,"checkpoint complete: wrote 29357 buffers (89.6%); 0 transaction log file(s) added, 0 removed, 0 recycled; write=5.931 s, sync=0.399 s, total=6.418 s; sync files=53, longest=0.179 s, average=0.007 s; distance=311294 kB, estimate=311294 kB",,,,,,,,,""
2018-11-30 10:16:47.683 CST,"repl","",7227,"192.168.56.90:52556",5c009795.1c3b,3,"streaming 0/16000098",2018-11-30 09:51:17 CST,,0,LOG,00000,"disconnection: session time: 0:25:30.149 user=repl database= host=192.168.56.90 port=52556",,,,,,,,,"walreceiver"
2018-11-30 10:16:47.730 CST,,,7153,,5c009735.1bf1,5,,2018-11-30 09:49:41 CST,,0,LOG,00000,"database system is shut down",,,,,,,,,""

注意倒数第二条信息 streaming 0/16000098 ,说明当时的master关闭时,已经和salve沟通过,确认已经接收到 END_OF_RECOVERY 之前所有的数据了。

old slave 日志

2018-11-30 10:16:47.660 CST,,,7256,,5c009795.1c58,2,,2018-11-30 09:51:17 CST,,0,LOG,00000,"replication terminated by primary server","End of WAL reached on timeline 1 at 0/16000098.",,,,,,,,""
2018-11-30 10:16:47.660 CST,,,7256,,5c009795.1c58,3,,2018-11-30 09:51:17 CST,,0,FATAL,XX000,"could not send end-of-streaming message to primary: no COPY in progress
",,,,,,,,,""
2018-11-30 10:16:47.660 CST,,,7255,,5c009795.1c57,5,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"invalid record length at 0/16000098: wanted 24, got 0",,,,,,,,,""
2018-11-30 10:16:47.854 CST,,,7443,,5c009d8f.1d13,1,,2018-11-30 10:16:47 CST,,0,FATAL,XX000,"could not connect to the primary server: could not connect to server: Connection refused
 Is the server running on host ""192.168.56.119"" and accepting
 TCP/IP connections on port 5432?
",,,,,,,,,""
2018-11-30 10:16:52.668 CST,,,7444,,5c009d94.1d14,1,,2018-11-30 10:16:52 CST,,0,FATAL,XX000,"could not connect to the primary server: could not connect to server: Connection refused
 Is the server running on host ""192.168.56.119"" and accepting
 TCP/IP connections on port 5432?
",,,,,,,,,""
2018-11-30 10:16:56.875 CST,,,7255,,5c009795.1c57,6,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"received promote request",,,,,,,,,""
2018-11-30 10:16:56.875 CST,,,7255,,5c009795.1c57,7,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"redo done at 0/16000028",,,,,,,,,""
2018-11-30 10:16:56.875 CST,,,7255,,5c009795.1c57,8,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"last completed transaction was at log time 2018-11-30 10:16:40.986869+08",,,,,,,,,""
2018-11-30 10:16:56.888 CST,,,7255,,5c009795.1c57,9,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"selected new timeline ID: 2",,,,,,,,,""
2018-11-30 10:16:57.166 CST,,,7255,,5c009795.1c57,10,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"archive recovery complete",,,,,,,,,""
2018-11-30 10:16:57.267 CST,,,7255,,5c009795.1c57,11,,2018-11-30 09:51:17 CST,1/0,0,LOG,00000,"MultiXact member wraparound protections are now enabled",,,,,,,,,""
2018-11-30 10:16:57.267 CST,,,7257,,5c009795.1c59,1,,2018-11-30 09:51:17 CST,,0,LOG,00000,"checkpoint starting: force",,,,,,,,,""
2018-11-30 10:16:57.275 CST,,,7253,,5c009795.1c55,3,,2018-11-30 09:51:17 CST,,0,LOG,00000,"database system is ready to accept connections",,,,,,,,,""
2018-11-30 10:16:57.276 CST,,,7447,,5c009d99.1d17,1,,2018-11-30 10:16:57 CST,,0,LOG,00000,"autovacuum launcher started",,,,,,,,,""

信息也是相当的清晰。

wal_retrieve_retry_interval = 5s 控制 salve 到 master 失败时,再次重试的等待时间。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • PostgreSQL 打印日志信息所在的源文件和行数的实例

    一直好奇在PG中, 当输出错误日志时, 如何能够附带错误信息所在的源代码文件名以及发生错误的代码行数. postgres.conf中, log信息冗余级别为"default(默认)", terse: 表示更加简单的日志信息, verbose: 表示更加冗余的日志信息(即: 附带"文件名和行数) #log_error_verbosity = default # terse, default, or verbose messages 修改为下面的"verbose&quo

  • postgresql 实现启动、状态查看、关闭

    利用psql启动数据库 [postgres@highgo ~]$ pg_ctl start 查看系统中运行的postgres进程 #ps -ef | grep postgres 连接postgresql数据库 #psql -h 127.0.0.1 -d postgres -U postgres 停止postgresql数据库实例 #pg_ctl stop #ps -ef | grep postgres 启动服务器最简单的方法是像下面这样: $ postgres -D /usr/local/pgs

  • PostgreSQL 日志文件的所在位置

    1.查看postgresql.conf文件的配置,看日志文件在哪 logging_collector = on log_directory = 'pg_log' log_filename = 'postgresql-%a.log' log_truncate_on_rotation = o 2.日志的分类 pg_log(数据库运行日志) 内容可读 默认关闭的,需要设置参数启动 pg_xlog(WAL 日志,即重做日志) 内容一般不具有可读性 强制开启 pg_clog(事务提交日志,记录的是事务的元

  • PostgreSQL 恢复误删数据的操作

    在Oracle中:删除表或者误删表记录:有个闪回特性,不需要停机操作,可以完美找回记录.当然也有一些其他的恢复工具:例如odu工具,gdul工具.都可以找回数据.而PostgreSQL目前没有闪回特性.如何在不停机情况下恢复误删数据.还好是有完整的热备份. 本文描述的方法是:利用热备份在另一台服务器进行数据恢复:再导入正式环境:这样不影响数据库操作.这方法也适用在Oracle恢复.必须满足几个条件 1.有完整的基础数据文件备份和归档文件备份.所以备份是很重要的. 2.有一台装好同款Postgre

  • Postgresql 解决pg掉电后无法重启的问题

    机房断电后重启pg数据库,报如下错误: < 2019-01-01 22:42:59.240 EST >LOG: database system was interrupted while in recovery at 2019-01-01 22:00:58 EST < 2019-01-01 22:42:59.240 EST >HINT: This probably means that some data is corrupted and you will have to use

  • postgresql 如何关闭自动提交

    postgresql中默认是自动提交的 查看是否是自动提交: postgres=# \echo :AUTOCOMMIT on 关闭自动提交: postgres=# \set AUTOCOMMIT off postgres=# \echo :AUTOCOMMIT off 另一种方式就在会话开始的时候以begin开始相当于关闭了自动提交,以end或者commit结束就可以了 补充:pg(hgdb)默认事务自动提交 默认情况下,AUTOCOMMIT(自动提交)是开着的,也就是说任何一个SQL语句执行完

  • Postgresql 如何选择正确的关闭模式

    停止数据库的命令: pg_ctl stop -D $PGDATA [-m shutdown-mode] shutdown-mode有如下几种模式: 1. smart: 等所有的连接中止后,关闭数据库.如果客户端连接不终止, 则无法关闭数据库. 开启一个空会话: [root@localhost ~]# su - postgres [postgres@localhost ~]$ psql psql (9.4.4) Type "help" for help. postgres=# 用smar

  • PHP 编程请选择正确的文本编辑软件

    如果您在修改任何PHP文件后发生: 不能登入或者不能登出:     页顶出现一条空白:     页顶出现错误警告:     其它不正常的情况.     则多半是编辑器的问题. 本程序采用UTF-8编码.现在几乎所有的文本编辑软件都可以显示并编辑UTF-8编码的文件.但是很遗憾,其中很多软件的表现并不理想. 类似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编

  • Oracle SQL tuning 数据库优化步骤分享(图文教程)

    SQL Turning 是Quest公司出品的Quest Central软件中的一个工具.Quest Central是一款集成化.图形化.跨平台的数据库管理解决方案,可以同时管理 Oracle.DB2 和 SQL server 数据库. 一.SQL Tuning for SQL Server简介 SQL语句的优化对发挥数据库的最佳性能非常关键.然而不幸的是,应用优化通常由于时间和资源的因素而被忽略.SQL Tuning (SQL优化)模块可以对比和评测特定应用中SQL语句的运行性能,提出智能化的

  • 详解WPF的InkCanvas选择模式

    InkCanvas是WPF中进行墨迹绘制的控件,本文介绍下InkCanvas控件是如何进行选择操作的.文中有误的地方希望大家进行批评指正. InkCanvas的选择效果 使用WPF可以轻松实现白板功能,只需要添加一个InkCanvas控件.修改InkCanvas的EditingMode属性可以控制InkCanvas的操作模式,如书写.选择.擦除等模式. 如下demo在窗口中添加一个InkCanvas,然后添加一个Button实现书写与选择模式的切换. // xaml <Grid> <In

  • PostgreSQL教程(十):性能提升技巧

    一.使用EXPLAIN: PostgreSQL为每个查询都生成一个查询规划,因为选择正确的查询路径对性能的影响是极为关键的.PostgreSQL本身已经包含了一个规划器用于寻找最优规划,我们可以通过使用EXPLAIN命令来查看规划器为每个查询生成的查询规划.     PostgreSQL中生成的查询规划是由1到n个规划节点构成的规划树,其中最底层的节点为表扫描节点,用于从数据表中返回检索出的数据行.然而,不同的扫描节点类型代表着不同的表访问模式,如:顺序扫描.索引扫描,以及位图索引扫描等.如果查

  • PostgreSQL教程(十一):服务器配置

    一.服务器进程的启动和关闭: 下面是pg_ctl命令的使用方法和常用选项,需要指出的是,该命令是postgres命令的封装体,因此在使用上比直接使用postgres更加方便. 复制代码 代码如下: pg_ctl init[db] [-D DATADIR] [-s] [-o "OPTIONS"]     pg_ctl start     [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o "OPTIONS"]    

  • 浅析return false的正确使用

    可能在你刚开始学习关于jQuery事件处理时,看到的第一个例子就是关于如何阻止浏览器执行默认行为,比如下面这段演示click事件的代码: 复制代码 代码如下: $("a.toggle").click(function () {      $("#mydiv").toggle();      return false; // Prevent browser from visiting `#`  }); 这个函数使用toggle来显示或者隐藏#mydiv,然后阻止浏览器

  • oracle日志操作模式(归档模式和非归档模式的利与弊)

    笔者今天就谈谈自己对这两种操作模式的理解,并且给出一些可行的建议,跟大家一起来提高Oracle数据库的安全性. 一.非归档模式的利与弊. 非归档模式是指不保留重做历史的日志操作模式,只能够用于保护例程失败,而不能够保护介质损坏.如果数据库采用的是日志操作模式的话,则进行日志切换时,新的日志会直接覆盖原有日志文件的内容,不会保留原有日志文件中的数据. 这么说听起来可能比较难理解.笔者举一个简单的例子,就会清楚许多.如现在Oracle数据库中有四个日志组,日志序列号分别为11. 12.13.14.当

  • 学习php设计模式 php实现门面模式(Facade)

    一.意图 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层次的接口,使得子系统更加容易使用[GOF95] 外部与子系统的通信是通过一个门面(Facade)对象进行. 二.门面模式结构图 三.门面模式中主要角色 门面(Facade)角色: 此角色将被客户端调用 知道哪些子系统负责处理请求 将用户的请求指派给适当的子系统 子系统(subsystem)角色: 实现子系统的功能 处理由Facade对象指派的任务 没有Facade的相关信息,可以被客户端直接调用 可以同时有一个或多个

  • jQuery制作的别致导航有阴影背景高亮模式窗口

    效果图:  html链接: 复制代码 代码如下: <a href="#" rel="registerwindow" class="model">注册</a> css: 复制代码 代码如下: img{ border:0px;} #registerwindow{ width:600px; height:400px; top:50px; right:100px; background:#FFF; display:none; bo

随机推荐