随笔-23  评论-127  文章-0  trackbacks-1
  2008年7月10日

今天有被问到:sqlserver锁定一行的最小锁是什么?
当时答曰:行级锁

回来查文档,得有关锁的信息(sql2k用syslockinfo表查, sql2k5用sys.dm_tran_locks表查)

资源类型:
1 = NULL 资源(未使用)
2 = 数据库
3 = 文件
4 = 索引
5 = 表
6 = 页
7 = 键
8 = 区
9 = RID(行 ID)
10 = 应用程序

OK,现在来看看锁定到一行的最小级别的锁是什么。

 1D:\Program Files\Microsoft SQL Server\90\Tools\Binn>osql -Usa -Pdba123 -Sdragon
 21> create table t_pk(t_id int primary key, t_desc varchar(50));
 32> create table t_heap(t_id int, t_desc varchar(50));
 43> go
 51> insert into t_pk values(1'welcome');
 62> insert into t_pk values(2'nice to meet you');
 73> insert into t_pk values(3'wall street, stock');
 84> go
 9(1 行受影响)
10(1 行受影响)
11(1 行受影响)
121> insert into t_heap select * from t_pk;
132> go
14(3 行受影响)
151> begin tran
162> update t_pk set t_desc = 'have a nice day' where t_id = 3;
173> go
18(1 行受影响)
19

现在,我更新有主键的表t_pk,看看sqlserver锁了些什么东东:



这里,sqlserver对t_pk表以及相应的page加上了IX锁,对更新的那一行加上了X锁。

再来,现在试试对堆表的更新:

1> rollback;
2> go
1> begin tran
2> update t_heap set t_desc = 'have a nice day' where t_id = 3;
3> go

看看sqlserver对堆表锁了些什么:


sqlserver 2005很聪明,也只锁了一行(曾记得,sql2k对堆表会锁住一个page的,待找sql2k再测试)。

这2个测试中的锁定,一个是KEY, 一个是RID, 基本符合我所说的行级锁的意思。但真较上劲的话,我的答案又似乎不足,:)

posted @ 2008-07-10 18:38 楚潇 阅读(2109) 评论(9) 编辑
  2006年4月28日


作者:jll                       日期:2006-04-30
出处:http://jll.cnblogs.com

一、前言
        2005年7月下旬至8月中旬,我做了一个实现联通sgip1.2二级网关的项目,由于种种原因这个项目只完成了核心模块的2/5左右。此系统的源码几番周折,从硬盘转到邮箱,又从邮箱转到QQ网络硬盘。我想,应该赶在它“发霉”之前共享出来,一则可以让需要有的朋友作为参考; 二则或许可以得到相关朋友的指正,以此提高自已的水平。

二、为什么要选择.net 2.0作为开发平台
         开始这个项目的时候,我有几个会用的平台或工具作为选择:
        (1) Delphi             这东东就不用说了,组件多,开发资料也丰富,Indy 开发网络程序就足够强大
        (2) C++ Builder    跟Delphi差不多,但是调用Socket API方便些
        (3) .net                 在多线程编程方面相对简单,同时对Socket也提供了很好地封装
        之所以选择.net, 一方面是看中它强大的多线程库的支持,另一方面则是为了体验一下.net的威力[当时(当然也包括现在)对.net不是很熟悉]。考虑到这个项目是应用在服务器端且服务器性能较好,而用户也不会反感装一个20多兆的Framework,所以俺选择了它。

三、.net下socket编程的一些注意事项
        (1) 如何将一个结构体转换为byte[],或者如何将byte[]转换为相应的结构体
             有3种方式可以作为选择:
             a) 一是采用序列化的方式,在发送前将对象序列化成byte[], 通过socket转发之后再将byte[]还原
             b)用BitConvert类来处理
             c)使用Unsafe方式
             三种方式的详细实现请参见我的这篇blog:   http://jll.cnblogs.com/archive/2005/07/23/198851.aspx

        (2) 网络字节顺序与主机字节顺的转换
              在写socket程序时要注意,如果要发送整型(short, int, long等)类型的数据,需要将这些值转换成网络字节顺序后才后再发送,同时接收方也要将网络字节顺序的值转为主机字节顺序的。System.Net.IPAddress类提供了HostToNetworkOrderHostToNetworkOrder 来完成相应的功能。

       (3) 如何判断socket已经断开了
             tcp的实现机制决定了这个处理这个问题的复杂性。 已连接的socket, 如果网络突然断开了或者是对方突然死机,tcp的默认实现机制是不能检测到这种情况的。然而,在.net下的Socket,即使你按照正常的程序来关闭Socket,它也不会有相应的事件或属性来告知您。
            我的这篇blog: http://jll.cnblogs.com/archive/2005/07/29/203090.html  较详细地叙述了这个问题。

四、联通的sgip 1.2协议
        网上资料很多,请自行google或baidu,^_^

五、程序源码及开发文档
       这篇blog的核心就在于这里(http://files.cnblogs.com/JLL/sgipSMG.rar)了, 包括整个源代码和开发文档。请阅读里面的 "开发文档.doc"  文件; 用vs 2005打开sgipSMG.sln后,在“解决方案资源管理器”下会看到4个项目,其中 "sgipSMG 项目" 为核心代码所在。
       需要的朋友请下载之。

good luck and have a good day!
     

posted @ 2006-04-28 11:25 楚潇 阅读(2288) 评论(13) 编辑
  2006年4月26日
TreeNode竟然没有HasChildren属性,ft!

今天写程序时遇到这个问题,找了msdn及参考这里:http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B313134,花了2个小时才搞定这个问题,特此一记。

代码如下(vs2k5上调试通过):
using System.Runtime.InteropServices;
    class TreeNodeHelper
    
{
        TreeNode treeNode 
= null;
        
public TreeNodeHelper(TreeNode tr)
        
{
            treeNode 
= tr;
        }


        
/// <summary>
        
/// 返回TreeNode是否有子结点
        
/// </summary>

        public bool HasChildren
        
{
            
get
            
{
                
return IsTreeNodeHasChildren(treeNode);
            }

            
set
            
{
                MakeTreeNodeHasChildren(treeNode, value);
            }

        }


        
public const UInt32 TV_FIRST = 4352;
        
public const UInt32 TVSIL_NORMAL = 0;
        
public const UInt32 TVSIL_STATE = 2;
        
public const UInt32 TVM_SETIMAGELIST = TV_FIRST + 9;
        
public const UInt32 TVM_GETNEXTITEM = TV_FIRST + 10;
        
public const UInt32 TVIF_HANDLE = 16;
        
public const UInt32 TVIF_STATE = 8;
        
public const UInt32 TVIS_STATEIMAGEMASK = 61440;
        
public const UInt32 TVM_SETITEM = TV_FIRST + 13;
        
public const UInt32 TVM_GETITEM = TV_FIRST + 12;
        
public const UInt32 TVGN_ROOT = 0;
        
public const int TVIF_CHILDREN = 64;

        
// Use a sequential structure layout to define TVITEM for the TreeView.
        [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
        
public struct TV_ITEM
        
{
            
public uint mask;
            
public IntPtr hItem;
            
public uint state;
            
public uint stateMask;
            
public IntPtr pszText;
            
public int cchTextMax;
            
public int iImage;
            
public int iSelectedImage;
            
public int cChildren;
            
public IntPtr lParam;
        }


        
// Declare two overloaded SendMessage functions. The
        
// difference is in the last parameter: one is ByVal and the
        
// other is ByRef.
        [DllImport("user32.dll")]
        
public static extern UInt32 SendMessage(IntPtr hWnd, UInt32 Msg,
            UInt32 wParam, UInt32 lParam);

        [DllImport(
"User32", CharSet = CharSet.Auto)]
        
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg,
            UInt32 wParam, 
ref TV_ITEM lParam);

        
/// <summary>
        
/// 指定TreeNode是否有子结点(有子结点则TreeNode会显示+号,没有则不会显示)
        
/// </summary>
        
/// <param name="tr"></param>
        
/// <param name="bHasChildren"></param>

        public static void MakeTreeNodeHasChildren(TreeNode tr, bool bHasChildren)
        
{
            TV_ITEM tvItem 
= new TV_ITEM();
            tvItem.mask 
= TVIF_CHILDREN | TVIF_HANDLE;
            tvItem.hItem 
= tr.Handle;
            tvItem.cChildren 
= bHasChildren ? 1 : 0;
            SendMessage(tr.TreeView.Handle, TVM_SETITEM, 
0ref tvItem);
        }


        
/// <summary>
        
/// 返回树结点是否有子结点
        
/// </summary>
        
/// <param name="?"></param>
        
/// <returns></returns>

        public static bool IsTreeNodeHasChildren(TreeNode tr)
        
{
            
if (tr.Nodes.Count > 0)
            
{
                
return true;
            }

            TV_ITEM tvItem 
= new TV_ITEM();
            tvItem.mask 
= TVIF_CHILDREN | TVIF_HANDLE;
            tvItem.hItem 
= tr.Handle;
            SendMessage(tr.TreeView.Handle, TVM_GETITEM, 
0ref tvItem);
            
return tvItem.cChildren == 1;
        }

    }

posted @ 2006-04-26 14:42 楚潇 阅读(600) 评论(2) 编辑
  2005年12月14日
目标:用gridview显示northwind中employee表的photo字段

步骤一:用SqlDataSource连接到northwind并获取employee表,我这里选取了:EmployeeID, LastName, FirstName, Country, Photo这几个字段。完成后如果:




步骤二:从“GridView Tasks”上选择"Edit Columns", 弹出Fields对话框。在“Availabe fields”里选ImageField之后,点击“Add”按钮,在ImageField Properties中的HeadText填入"Picture", 然后点击“Convert this field into a TemplateField”链接,最后点击 OK 按钮。



步骤三:新增一个名为GetEmployeeImage.aspx的页面,在Page_Load里写上一段代码。我写好的代码如下:
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    
protected void Page_Load(object sender, EventArgs e)
    
{
        
string strEmployeeID = Request.QueryString["ID"];
        
if (strEmployeeID == null)
        
{
            
return;
        }


        SqlConnection con 
= new SqlConnection(WebConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);
        SqlCommand cmd 
= new SqlCommand("select Photo from Employees where EmployeeID=" + strEmployeeID, con);
        con.Open();
        
byte[] buffer = (byte[])cmd.ExecuteScalar();
        con.Close();
        Response.BinaryWrite(buffer);
        Response.End();
    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>Untitled Page</title>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
    
    
</div>
    
</form>
</body>
</html>

步骤四:修改步骤二中(在文件default.aspx中)所设定的模板列, 代码如下:
 <asp:TemplateField HeaderText="Picture">
                    
<EditItemTemplate>
                        
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    
</EditItemTemplate>
                    
<ItemTemplate>
                        <asp:Image ID="Image1" runat="server" ImageUrl='<%# "GetEmployeeImage.aspx?ID=" + Eval("EmployeeID") %>'/>
                    </ItemTemplate>
                
</asp:TemplateField>

最终default.aspx的代码如下:
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>Untitled Page</title>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
        
<asp:SqlDataSource ID="employeeDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>"
            SelectCommand
="SELECT [EmployeeID], [LastName], [FirstName], [Photo], [Country] FROM [Employees]">
        
</asp:SqlDataSource>
    
    
</div>
        
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="EmployeeID"
            DataSourceID
="employeeDataSource" Height="172px" Width="335px">
            
<Columns>
                
<asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" InsertVisible="False"
                    ReadOnly
="True" SortExpression="EmployeeID" />
                
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
                
<asp:BoundField DataField="Country" HeaderText="Country" SortExpression="Country" />
                
<asp:TemplateField HeaderText="Picture">
                    
<EditItemTemplate>
                        
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    
</EditItemTemplate>
                    
<ItemTemplate>
                        
<asp:Image ID="Image1" runat="server" ImageUrl='<%# "GetEmployeeImage.aspx?ID=" + Eval("EmployeeID") %>'/>
                    
</ItemTemplate>
                
</asp:TemplateField>
            
</Columns>
        
</asp:GridView>
    
</form>
</body>
</html>


步骤五:将default.aspx设为启动页之后运行,在浏览器中查看结果如下:



附:
web.config中所做的修改:
1.
 <connectionStrings>
  <add name="Northwind" connectionString="Data Source=cc;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient"/>
 </connectionStrings>

2.  
  <pages>
      <namespaces>
        <add namespace="System.Data.SqlClient"/>
        <add namespace="System.Web.Configuration"/>
      </namespaces>
    </pages>
posted @ 2005-12-14 16:47 楚潇 阅读(1381) 评论(3) 编辑
  2005年11月20日
       冬天里的太阳是极受欢迎的,恰好今天风和日丽,我便乘此机会到院子里走走。
       一位母亲带着她的孩子和一群儿童在玩耍。
       一位老人慢慢地在走,享受着这温和的阳光。
       一辆车在不远处停下,出来两位美女。
       最难得一见的是,一颗树上有一个鸟窝,鸟窝里有一群小鸟在“叽叽”地叫。这让我想起小时候爬上树去掏鸟窝的趣事。
        然而,即使我发现了鸟窝,却已过了掏鸟窝的年纪。小鸟已不是当年的小鸟儿,我亦不再是当年的我!
        谁又没有在变呢!
posted @ 2005-11-20 16:12 楚潇 阅读(121) 评论(1) 编辑
  2005年11月9日
摘要: 今天学习asp.net2.0提供的membership功能,在vs2k5中 Website\ASP.NET configuration 菜单调出 “asp.net Web Site Administration Tool "后,选择 Security 选项卡老是出错,结果在下面的网址找到了答案:http://forums.microsoft.com/msdn/showpost.aspx...阅读全文
posted @ 2005-11-09 21:23 楚潇 阅读(466) 评论(2) 编辑
  2005年11月2日
摘要: 我的这个DVD光驱好久不用了,这两天在BT完VS2K5的RTM版本想要重装系统的时候,光驱竟然认不出碟来!再从室友哪里借一张盘来还是认不出,晕晕,难道就这样死了?这个DVD自从买回来之后,由于读碟能力差,我一般只拿它来装系统,连DVD都没看得几部。就这样坏了?我心有不甘啊,于是上网搜索修光驱的资料,在经过一翻学习之后,我便要拿它开刀了。 第一步,升级firmware 光驱的firmware就相当于...阅读全文
posted @ 2005-11-02 12:53 楚潇 阅读(880) 评论(2) 编辑
  2005年10月30日
摘要: 转自铁血 http://www.tiexue.net/我是八一年出生的,根红苗正,第一代八十年代的人。我们这一代人是幸福的一代,因为我们没有挨过饿,挨过整,我们也是不幸的一代,因为我们是实验品的一代。俺是实验品,从俺上小学开始,俺就是教学改革的实验班,初中的时候赶上教材改革,高中的时候赶上高考改革,俺就这么一路的被试验了下来,最后大学的时候还不错,没有赶上扩招(这个,比较幸运,俺早上一年学,而且我...阅读全文
posted @ 2005-10-30 12:56 楚潇 阅读(319) 评论(4) 编辑
  2005年10月24日
摘要: 风来疏竹,风过而竹不留声;雁渡寒塘,雁去而塘不留影。故君子事来而心始现,事去而心随空。小胜凭智,大胜靠德。阅读全文
posted @ 2005-10-24 12:06 楚潇 阅读(189) 评论(0) 编辑
  2005年10月6日
摘要: 这段时间把《windows核心编程》给读完了,感觉很爽,不愧为一本经典书籍呀。 读完这本书,我终于把原来不太明白的地方搞清楚了,感觉对windows又有了深一步的了解。我在这里要记录一下我一直以来写的错误代码。 1、Critical Section原来一直没有搞清楚Critical Section 这个东西的真正含义,我以往在线程中要保护资源经常这样写: void ThreadFunction(P...阅读全文
posted @ 2005-10-06 21:26 楚潇 阅读(1571) 评论(3) 编辑
仅列出标题  下一页